IVR Library
[Core Library]

Collaboration diagram for IVR Library:

Modules

 IVR Menu Library

Typedefs

typedef switch_ivr_digit_stream_parser switch_ivr_digit_stream_parser_t
typedef switch_ivr_digit_stream switch_ivr_digit_stream_t

Functions

switch_status_t switch_ivr_deactivate_unicast (switch_core_session_t *session)
switch_status_t switch_ivr_activate_unicast (switch_core_session_t *session, char *local_ip, switch_port_t local_port, char *remote_ip, switch_port_t remote_port, char *transport, char *flags)
switch_status_t switch_ivr_generate_json_cdr (switch_core_session_t *session, cJSON **json_cdr, switch_bool_t urlencode)
 Generate an JSON CDR report.
switch_status_t switch_ivr_generate_xml_cdr (switch_core_session_t *session, switch_xml_t *xml_cdr)
 Generate an XML CDR report.
int switch_ivr_set_xml_profile_data (switch_xml_t xml, switch_caller_profile_t *caller_profile, int off)
int switch_ivr_set_xml_chan_vars (switch_xml_t xml, switch_channel_t *channel, int off)
switch_status_t switch_ivr_parse_event (_In_ switch_core_session_t *session, _In_ switch_event_t *event)
 Parse command from an event.
switch_status_t switch_ivr_parse_all_events (switch_core_session_t *session)
 Parse all commands from an event.
switch_status_t switch_ivr_parse_next_event (switch_core_session_t *session)
switch_status_t switch_ivr_parse_all_messages (switch_core_session_t *session)
switch_status_t switch_ivr_parse_all_signal_data (switch_core_session_t *session)
switch_status_t switch_ivr_process_indications (switch_core_session_t *session, switch_core_session_message_t *message)
switch_status_t switch_ivr_sleep (switch_core_session_t *session, uint32_t ms, switch_bool_t sync, switch_input_args_t *args)
 Wait for time to pass for a specified number of milliseconds.
switch_status_t switch_ivr_park (switch_core_session_t *session, switch_input_args_t *args)
switch_status_t switch_ivr_collect_digits_callback (switch_core_session_t *session, switch_input_args_t *args, uint32_t digit_timeout, uint32_t abs_timeout)
 Wait for DTMF digits calling a pluggable callback function when digits are collected.
switch_status_t switch_ivr_collect_digits_count (switch_core_session_t *session, char *buf, switch_size_t buflen, switch_size_t maxdigits, const char *terminators, char *terminator, uint32_t first_timeout, uint32_t digit_timeout, uint32_t abs_timeout)
 Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up.
switch_status_t switch_ivr_play_and_detect_speech (switch_core_session_t *session, const char *file, const char *mod_name, const char *grammar, char **result, uint32_t input_timeout, switch_input_args_t *args)
 play a file to the session while doing speech recognition.
switch_status_t switch_ivr_detect_speech (switch_core_session_t *session, const char *mod_name, const char *grammar, const char *name, const char *dest, switch_asr_handle_t *ah)
 Engage background Speech detection on a session.
switch_status_t switch_ivr_stop_detect_speech (switch_core_session_t *session)
 Stop background Speech detection on a session.
switch_status_t switch_ivr_pause_detect_speech (switch_core_session_t *session)
 Pause background Speech detection on a session.
switch_status_t switch_ivr_resume_detect_speech (switch_core_session_t *session)
 Resume background Speech detection on a session.
switch_status_t switch_ivr_detect_speech_load_grammar (switch_core_session_t *session, char *grammar, char *name)
 Load a grammar on a background speech detection handle.
switch_status_t switch_ivr_detect_speech_unload_grammar (switch_core_session_t *session, const char *name)
 Unload a grammar on a background speech detection handle.
switch_status_t switch_ivr_detect_speech_enable_grammar (switch_core_session_t *session, const char *name)
 Enable a grammar on a background speech detection handle.
switch_status_t switch_ivr_detect_speech_disable_grammar (switch_core_session_t *session, const char *name)
 Disable a grammar on a background speech detection handle.
switch_status_t switch_ivr_detect_speech_disable_all_grammars (switch_core_session_t *session)
 Disable all grammars on a background speech detection handle.
switch_status_t switch_ivr_set_param_detect_speech (switch_core_session_t *session, const char *name, const char *val)
switch_status_t switch_ivr_detect_speech_start_input_timers (switch_core_session_t *session)
 Start input timers on a background speech detection handle.
switch_status_t switch_ivr_record_session (switch_core_session_t *session, char *file, uint32_t limit, switch_file_handle_t *fh)
 Record a session to disk.
switch_status_t switch_ivr_eavesdrop_pop_eavesdropper (switch_core_session_t *session, switch_core_session_t **sessionp)
switch_status_t switch_ivr_eavesdrop_exec_all (switch_core_session_t *session, const char *app, const char *arg)
switch_status_t switch_ivr_eavesdrop_update_display (switch_core_session_t *session, const char *name, const char *number)
switch_status_t switch_ivr_eavesdrop_session (switch_core_session_t *session, const char *uuid, const char *require_group, switch_eavesdrop_flag_t flags)
 Eavesdrop on a another session.
switch_status_t switch_ivr_displace_session (switch_core_session_t *session, const char *file, uint32_t limit, const char *flags)
 displace the media for a session with the audio from a file
switch_status_t switch_ivr_stop_displace_session (switch_core_session_t *session, const char *file)
 Stop displacing a session.
switch_status_t switch_ivr_stop_record_session (switch_core_session_t *session, const char *file)
 Stop Recording a session.
switch_status_t switch_ivr_session_audio (switch_core_session_t *session, const char *cmd, const char *direction, int level)
switch_status_t switch_ivr_stop_session_audio (switch_core_session_t *session)
switch_status_t switch_ivr_inband_dtmf_session (switch_core_session_t *session)
 Start looking for DTMF inband.
switch_status_t switch_ivr_stop_inband_dtmf_session (switch_core_session_t *session)
 Stop looking for DTMF inband.
switch_status_t switch_ivr_inband_dtmf_generate_session (switch_core_session_t *session, switch_bool_t read_stream)
 Start generating DTMF inband.
switch_status_t switch_ivr_stop_inband_dtmf_generate_session (switch_core_session_t *session)
 Stop generating DTMF inband.
void switch_ivr_session_echo (switch_core_session_t *session, switch_input_args_t *args)
 
  • NEEDDESC -

switch_status_t switch_ivr_stop_tone_detect_session (switch_core_session_t *session)
 Stop looking for TONES.
switch_status_t switch_ivr_tone_detect_session (switch_core_session_t *session, const char *key, const char *tone_spec, const char *flags, time_t timeout, int hits, const char *app, const char *data, switch_tone_detect_callback_t callback)
 Start looking for TONES.
switch_status_t switch_ivr_play_file (switch_core_session_t *session, switch_file_handle_t *fh, const char *file, switch_input_args_t *args)
 play a file from the disk to the session
switch_status_t switch_ivr_wait_for_silence (switch_core_session_t *session, uint32_t thresh, uint32_t silence_hits, uint32_t listen_hits, uint32_t timeout_ms, const char *file)
switch_status_t switch_ivr_gentones (switch_core_session_t *session, const char *script, int32_t loops, switch_input_args_t *args)
switch_status_t switch_ivr_record_file (_In_ switch_core_session_t *session, _In_ switch_file_handle_t *fh, _In_z_ const char *file, _In_opt_ switch_input_args_t *args, _In_ uint32_t limit)
 record a file from the session to a file
switch_status_t switch_play_and_get_digits (switch_core_session_t *session, uint32_t min_digits, uint32_t max_digits, uint32_t max_tries, uint32_t timeout, const char *valid_terminators, const char *audio_file, const char *bad_input_audio_file, const char *var_name, char *digit_buffer, uint32_t digit_buffer_length, const char *digits_regex, uint32_t digit_timeout, const char *transfer_on_failure)
 Play a sound and gather digits with the number of retries specified if the user doesn't give digits in the set time.
switch_status_t switch_ivr_speak_text_handle (switch_core_session_t *session, switch_speech_handle_t *sh, switch_codec_t *codec, switch_timer_t *timer, char *text, switch_input_args_t *args)
void switch_ivr_clear_speech_cache (switch_core_session_t *session)
switch_status_t switch_ivr_speak_text (switch_core_session_t *session, const char *tts_name, const char *voice_name, char *text, switch_input_args_t *args)
 Speak given text with given tts engine.
switch_status_t switch_ivr_originate (switch_core_session_t *session, switch_core_session_t **bleg, switch_call_cause_t *cause, const char *bridgeto, uint32_t timelimit_sec, const switch_state_handler_table_t *table, const char *cid_name_override, const char *cid_num_override, switch_caller_profile_t *caller_profile_override, switch_event_t *ovars, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
 Make an outgoing call.
switch_status_t switch_ivr_enterprise_originate (switch_core_session_t *session, switch_core_session_t **bleg, switch_call_cause_t *cause, const char *bridgeto, uint32_t timelimit_sec, const switch_state_handler_table_t *table, const char *cid_name_override, const char *cid_num_override, switch_caller_profile_t *caller_profile_override, switch_event_t *ovars, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
void switch_ivr_bridge_display (switch_core_session_t *session, switch_core_session_t *peer_session)
switch_status_t switch_ivr_multi_threaded_bridge (_In_ switch_core_session_t *session, _In_ switch_core_session_t *peer_session, switch_input_callback_function_t dtmf_callback, void *session_data, void *peer_session_data)
 Bridge Audio from one session to another.
switch_status_t switch_ivr_signal_bridge (switch_core_session_t *session, switch_core_session_t *peer_session)
 Bridge Signalling from one session to another.
switch_status_t switch_ivr_session_transfer (_In_ switch_core_session_t *session, const char *extension, const char *dialplan, const char *context)
 Transfer an existing session to another location.
uint32_t switch_ivr_schedule_transfer (time_t runtime, const char *uuid, char *extension, char *dialplan, char *context)
 Transfer an existing session to another location in the future.
uint32_t switch_ivr_schedule_hangup (time_t runtime, const char *uuid, switch_call_cause_t cause, switch_bool_t bleg)
 Hangup an existing session in the future.
switch_status_t switch_ivr_uuid_bridge (const char *originator_uuid, const char *originatee_uuid)
 Bridge two existing sessions.
switch_status_t switch_ivr_media (const char *uuid, switch_media_flag_t flags)
 Signal a session to request direct media access to it's remote end.
switch_status_t switch_ivr_nomedia (const char *uuid, switch_media_flag_t flags)
 Signal a session to request indirect media allowing it to exchange media directly with another device.
switch_status_t switch_ivr_hold_uuid (const char *uuid, const char *message, switch_bool_t moh)
 Signal the session with a protocol specific hold message.
switch_status_t switch_ivr_unhold_uuid (const char *uuid)
 Signal the session with a protocol specific unhold message.
switch_status_t switch_ivr_hold (switch_core_session_t *session, const char *message, switch_bool_t moh)
 Signal the session with a protocol specific hold message.
switch_status_t switch_ivr_unhold (switch_core_session_t *session)
 Signal the session with a protocol specific unhold message.
uint32_t switch_ivr_schedule_broadcast (time_t runtime, const char *uuid, const char *path, switch_media_flag_t flags)
 Signal the session to broadcast audio in the future.
switch_status_t switch_ivr_broadcast (const char *uuid, const char *path, switch_media_flag_t flags)
 Signal the session to broadcast audio.
void switch_ivr_broadcast_in_thread (switch_core_session_t *session, const char *app, int flags)
switch_status_t switch_ivr_transfer_variable (switch_core_session_t *sessa, switch_core_session_t *sessb, char *var)
 Transfer variables from one session to another.
switch_status_t switch_ivr_digit_stream_parser_new (switch_memory_pool_t *pool, switch_ivr_digit_stream_parser_t **parser)
 Create a digit stream parser object.
switch_status_t switch_ivr_digit_stream_parser_destroy (switch_ivr_digit_stream_parser_t *parser)
 Destroy a digit stream parser object.
switch_status_t switch_ivr_digit_stream_new (switch_ivr_digit_stream_parser_t *parser, switch_ivr_digit_stream_t **stream)
 Create a new digit stream object.
switch_status_t switch_ivr_digit_stream_destroy (switch_ivr_digit_stream_t **stream)
 Destroys a digit stream object.
switch_status_t switch_ivr_digit_stream_parser_set_event (switch_ivr_digit_stream_parser_t *parser, char *digits, void *data)
 Set a digit string to action mapping.
switch_status_t switch_ivr_digit_stream_parser_del_event (switch_ivr_digit_stream_parser_t *parser, char *digits)
 Delete a string to action mapping.
void * switch_ivr_digit_stream_parser_feed (switch_ivr_digit_stream_parser_t *parser, switch_ivr_digit_stream_t *stream, char digit)
 Feed digits collected into the stream for event match testing.
switch_status_t switch_ivr_digit_stream_reset (switch_ivr_digit_stream_t *stream)
 Reset the collected digit stream to nothing.
switch_status_t switch_ivr_digit_stream_parser_set_terminator (switch_ivr_digit_stream_parser_t *parser, char digit)
 Set a digit string terminator.


Detailed Description

A group of core functions to do IVR related functions designed to be building blocks for a higher level IVR interface.

Typedef Documentation

typedef struct switch_ivr_digit_stream_parser switch_ivr_digit_stream_parser_t

Definition at line 650 of file switch_ivr.h.

typedef struct switch_ivr_digit_stream switch_ivr_digit_stream_t

Definition at line 652 of file switch_ivr.h.


Function Documentation

switch_status_t switch_ivr_activate_unicast ( switch_core_session_t session,
char *  local_ip,
switch_port_t  local_port,
char *  remote_ip,
switch_port_t  remote_port,
char *  transport,
char *  flags 
)

Definition at line 381 of file switch_ivr.c.

References switch_codec_implementation::actual_samples_per_second, CF_UNICAST, fail, switch_codec::implementation, switch_codec_implementation::microseconds_per_packet, SUF_NATIVE, SUF_READY, switch_assert, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_set_private(), SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_core_codec_init, switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_codec(), switch_core_session_strdup, SWITCH_LOG_CRIT, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, SWITCH_LOG_INFO, switch_log_printf(), switch_mutex_init(), SWITCH_MUTEX_NESTED, switch_set_flag, switch_set_flag_locked, switch_sockaddr_info_get(), switch_socket_bind(), switch_socket_create(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_test_flag, and SWITCH_UNSPEC.

Referenced by switch_ivr_parse_event().

00385 {
00386         switch_channel_t *channel = switch_core_session_get_channel(session);
00387         switch_unicast_conninfo_t *conninfo = switch_core_session_alloc(session, sizeof(*conninfo));
00388         switch_codec_t *read_codec;
00389 
00390         switch_assert(conninfo != NULL);
00391 
00392         conninfo->local_ip = switch_core_session_strdup(session, local_ip);
00393         conninfo->local_port = local_port;
00394 
00395         conninfo->remote_ip = switch_core_session_strdup(session, remote_ip);
00396         conninfo->remote_port = remote_port;
00397         conninfo->session = session;
00398 
00399         if (!strcasecmp(transport, "udp")) {
00400                 conninfo->type = AF_INET;
00401                 conninfo->transport = SOCK_DGRAM;
00402         } else if (!strcasecmp(transport, "tcp")) {
00403                 conninfo->type = AF_INET;
00404                 conninfo->transport = SOCK_STREAM;
00405         } else {
00406                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid transport %s\n", transport);
00407                 goto fail;
00408         }
00409 
00410         if (flags) {
00411                 if (strstr(flags, "native")) {
00412                         switch_set_flag(conninfo, SUF_NATIVE);
00413                 }
00414         }
00415 
00416         switch_mutex_init(&conninfo->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
00417 
00418         read_codec = switch_core_session_get_read_codec(session);
00419 
00420         if (!switch_test_flag(conninfo, SUF_NATIVE)) {
00421                 if (switch_core_codec_init(&conninfo->read_codec,
00422                                                                    "L16",
00423                                                                    NULL,
00424                                                                    read_codec->implementation->actual_samples_per_second,
00425                                                                    read_codec->implementation->microseconds_per_packet / 1000,
00426                                                                    1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
00427                                                                    NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
00428                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
00429                                                           "Raw Codec Activation Success L16@%uhz 1 channel %dms\n",
00430                                                           read_codec->implementation->actual_samples_per_second, read_codec->implementation->microseconds_per_packet / 1000);
00431                 } else {
00432                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n",
00433                                                           read_codec->implementation->actual_samples_per_second, read_codec->implementation->microseconds_per_packet / 1000);
00434                         goto fail;
00435                 }
00436         }
00437 
00438         conninfo->write_frame.data = conninfo->write_frame_data;
00439         conninfo->write_frame.buflen = sizeof(conninfo->write_frame_data);
00440         conninfo->write_frame.codec = switch_test_flag(conninfo, SUF_NATIVE) ? read_codec : &conninfo->read_codec;
00441 
00442         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "connect %s:%d->%s:%d\n",
00443                                           conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
00444 
00445         if (switch_sockaddr_info_get(&conninfo->local_addr,
00446                                                                  conninfo->local_ip, SWITCH_UNSPEC, conninfo->local_port, 0,
00447                                                                  switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
00448                 goto fail;
00449         }
00450 
00451         if (switch_sockaddr_info_get(&conninfo->remote_addr,
00452                                                                  conninfo->remote_ip, SWITCH_UNSPEC, conninfo->remote_port, 0,
00453                                                                  switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
00454                 goto fail;
00455         }
00456 
00457         if (switch_socket_create(&conninfo->socket, AF_INET, SOCK_DGRAM, 0, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
00458                 if (switch_socket_bind(conninfo->socket, conninfo->local_addr) != SWITCH_STATUS_SUCCESS) {
00459                         goto fail;
00460                 }
00461         } else {
00462                 goto fail;
00463         }
00464 
00465         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Created unicast connection %s:%d->%s:%d\n",
00466                                           conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
00467         switch_channel_set_private(channel, "unicast", conninfo);
00468         switch_channel_set_flag(channel, CF_UNICAST);
00469         switch_set_flag_locked(conninfo, SUF_READY);
00470         return SWITCH_STATUS_SUCCESS;
00471 
00472   fail:
00473 
00474         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure creating unicast connection %s:%d->%s:%d\n",
00475                                           conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
00476         return SWITCH_STATUS_FALSE;
00477 }

void switch_ivr_bridge_display ( switch_core_session_t session,
switch_core_session_t peer_session 
)

Definition at line 143 of file switch_ivr_bridge.c.

References send_display().

Referenced by audio_bridge_thread(), switch_ivr_signal_bridge(), and switch_ivr_uuid_bridge().

00144 {
00145 
00146         send_display(session, peer_session);
00147         send_display(peer_session, session);
00148 
00149 }

switch_status_t switch_ivr_broadcast ( const char *  uuid,
const char *  path,
switch_media_flag_t  flags 
)

Signal the session to broadcast audio.

Parameters:
uuid the uuid of the session to broadcast on
path the path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>"
flags flags to send to the request (SMF_ECHO_BRIDGED to send the broadcast to both sides of the call)
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4028 of file switch_ivr_async.c.

References CF_BROADCAST_DROP_MEDIA, CF_PROXY_MODE, SAF_MEDIA_TAP, SMF_ECHO_ALEG, SMF_ECHO_BLEG, SMF_EXEC_INLINE, SMF_HOLD_BLEG, SMF_LOOP, SMF_PRIORITY, SMF_REBRIDGE, switch_assert, switch_channel_get_variable, switch_channel_set_flag, switch_channel_test_flag(), switch_core_session_execute_application, switch_core_session_execute_application_get_flags(), switch_core_session_get_app_flags(), switch_core_session_get_channel(), switch_core_session_locate(), switch_core_session_queue_private_event(), switch_core_session_rwunlock(), switch_event_add_header(), switch_event_add_header_string(), SWITCH_EVENT_COMMAND, switch_event_create, switch_ivr_media(), switch_safe_free, SWITCH_SIGNAL_BOND_VARIABLE, SWITCH_STACK_BOTTOM, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by bcast_thread(), meta_on_dtmf(), switch_ivr_hold(), switch_ivr_parse_event(), switch_ivr_soft_hold(), and SWITCH_STANDARD_SCHED_FUNC().

04029 {
04030         switch_channel_t *channel;
04031         switch_core_session_t *session, *master;
04032         switch_event_t *event;
04033         switch_core_session_t *other_session = NULL;
04034         const char *other_uuid = NULL;
04035         char *app = "playback";
04036         char *cause = NULL;
04037         char *mypath;
04038         char *p;
04039         int app_flags = 0, nomedia = 0;
04040 
04041         switch_assert(path);
04042 
04043         if (!(master = session = switch_core_session_locate(uuid))) {
04044                 return SWITCH_STATUS_FALSE;
04045         }
04046 
04047         channel = switch_core_session_get_channel(session);
04048 
04049         mypath = strdup(path);
04050         assert(mypath);
04051 
04052         if ((p = strchr(mypath, ':')) && *(p + 1) == ':') {
04053                 app = mypath;
04054                 *p++ = '\0';
04055                 *p++ = '\0';
04056                 path = p;
04057         }
04058 
04059         if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
04060                 nomedia = 1;
04061                 switch_ivr_media(uuid, SMF_REBRIDGE);
04062         }
04063 
04064         if ((cause = strchr(app, '!'))) {
04065                 *cause++ = '\0';
04066                 if (!cause) {
04067                         cause = "normal_clearing";
04068                 }
04069         }
04070 
04071         if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
04072                 && (other_session = switch_core_session_locate(other_uuid))) {
04073                 if ((flags & SMF_EXEC_INLINE)) {
04074                         switch_core_session_execute_application_get_flags(other_session, app, path, &app_flags);
04075                         nomedia = 0;
04076                 } else {
04077                         switch_core_session_get_app_flags(app, &app_flags);
04078                         if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
04079                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
04080                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
04081                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path);
04082                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
04083 
04084                                 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);
04085 
04086                                 if ((flags & SMF_LOOP)) {
04087                                         switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1);
04088                                 }
04089 
04090                                 if ((flags & SMF_HOLD_BLEG)) {
04091                                         switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true");
04092                                 }
04093 
04094                                 switch_core_session_queue_private_event(other_session, &event, (flags & SMF_PRIORITY));
04095                         }
04096                 }
04097 
04098                 switch_core_session_rwunlock(other_session);
04099                 master = other_session;
04100                 other_session = NULL;
04101         }
04102 
04103         if ((app_flags & SAF_MEDIA_TAP)) {
04104                 nomedia = 0;
04105         }
04106 
04107         if ((flags & SMF_ECHO_ALEG)) {
04108                 if ((flags & SMF_EXEC_INLINE)) {
04109                         nomedia = 0;
04110                         switch_core_session_execute_application(session, app, path);
04111                 } else {
04112                         if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
04113                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
04114                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
04115                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path);
04116                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
04117                                 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);
04118 
04119                                 if ((flags & SMF_LOOP)) {
04120                                         switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1);
04121                                 }
04122                                 if ((flags & SMF_HOLD_BLEG)) {
04123                                         switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true");
04124                                 }
04125 
04126                                 switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY));
04127 
04128                                 if (nomedia)
04129                                         switch_channel_set_flag(channel, CF_BROADCAST_DROP_MEDIA);
04130                         }
04131                 }
04132                 master = session;
04133         }
04134 
04135         if (cause) {
04136                 if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
04137                         switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
04138                         switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", "hangup");
04139                         switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", cause);
04140                         switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
04141                         switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY));
04142                 }
04143         }
04144 
04145         switch_core_session_rwunlock(session);
04146         switch_safe_free(mypath);
04147 
04148         return SWITCH_STATUS_SUCCESS;
04149 }

void switch_ivr_broadcast_in_thread ( switch_core_session_t session,
const char *  app,
int  flags 
)

Definition at line 3081 of file switch_ivr_async.c.

References bcast_thread(), pool, switch_assert, switch_core_session_alloc, switch_core_session_get_pool(), switch_thread_create(), SWITCH_THREAD_STACKSIZE, switch_threadattr_create(), switch_threadattr_detach_set(), and switch_threadattr_stacksize_set().

Referenced by meta_on_dtmf().

03082 {
03083         switch_thread_t *thread;
03084         switch_threadattr_t *thd_attr = NULL;
03085         switch_memory_pool_t *pool;
03086         bch_t *bch;
03087 
03088         switch_assert(session);
03089 
03090         pool = switch_core_session_get_pool(session);
03091 
03092         bch = switch_core_session_alloc(session, sizeof(*bch));
03093         bch->session = session;
03094         bch->app = app;
03095         bch->flags = flags;
03096 
03097 
03098         switch_threadattr_create(&thd_attr, pool);
03099         switch_threadattr_detach_set(thd_attr, 1);
03100         switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
03101         switch_thread_create(&thread, thd_attr, bcast_thread, bch, pool);
03102 }

void switch_ivr_clear_speech_cache ( switch_core_session_t session  ) 

Definition at line 2377 of file switch_ivr_play_say.c.

References cached_speech_handle::codec, switch_timer::interval, cached_speech_handle::sh, switch_speech_handle::speech_interface, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, switch_channel_get_private(), switch_channel_set_private(), switch_core_codec_destroy(), switch_core_session_get_channel(), switch_core_speech_close(), switch_core_timer_destroy(), SWITCH_SPEECH_FLAG_NONE, and cached_speech_handle::timer.

Referenced by switch_core_session_perform_destroy(), and switch_ivr_speak_text().

02378 {
02379         cached_speech_handle_t *cache_obj = NULL;
02380         switch_channel_t *channel = switch_core_session_get_channel(session);
02381 
02382         if ((cache_obj = switch_channel_get_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME))) {
02383                 switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
02384                 if (cache_obj->timer.interval) {
02385                         switch_core_timer_destroy(&cache_obj->timer);
02386                 }
02387                 if (&cache_obj->sh && cache_obj->sh.speech_interface) {
02388                         switch_core_speech_close(&cache_obj->sh, &flags);
02389                 }
02390                 if (&cache_obj->codec) {
02391                         switch_core_codec_destroy(&cache_obj->codec);
02392                 }
02393                 switch_channel_set_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, NULL);
02394         }
02395 }

switch_status_t switch_ivr_collect_digits_callback ( switch_core_session_t session,
switch_input_args_t args,
uint32_t  digit_timeout,
uint32_t  abs_timeout 
)

Wait for DTMF digits calling a pluggable callback function when digits are collected.

Parameters:
session the session to read.
args arguements to pass for callbacks etc
timeout a timeout in milliseconds
Returns:
SWITCH_STATUS_SUCCESS to keep the collection moving.

Definition at line 1106 of file switch_ivr.c.

References CF_BREAK, CF_SERVICE, switch_dtmf_t::digit, switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_has_dtmf(), switch_channel_ready, switch_channel_test_flag(), switch_cond_next(), switch_core_session_dequeue_event(), switch_core_session_get_channel(), switch_core_session_read_frame(), switch_event_destroy(), SWITCH_FALSE, SWITCH_INPUT_TYPE_DTMF, SWITCH_INPUT_TYPE_EVENT, SWITCH_IO_FLAG_NONE, switch_ivr_dmachine_feed(), switch_ivr_dmachine_ping(), switch_ivr_parse_all_events(), switch_micro_time_now(), SWITCH_READ_ACCEPTABLE, SWITCH_STATUS_BREAK, SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, and SWITCH_STATUS_TIMEOUT.

Referenced by CoreSession::collectDigits(), enterprise_originate_ringback_thread(), fs_switch_ivr_collect_digits_callback(), and switch_ivr_soft_hold().

01108 {
01109         switch_channel_t *channel = switch_core_session_get_channel(session);
01110         switch_status_t status = SWITCH_STATUS_SUCCESS;
01111         switch_time_t abs_started = 0, digit_started = 0;
01112         uint32_t abs_elapsed = 0, digit_elapsed = 0;
01113 
01114         if (!args) {
01115                 return SWITCH_STATUS_GENERR;
01116         }
01117 
01118         if (abs_timeout) {
01119                 abs_started = switch_micro_time_now();
01120         }
01121         if (digit_timeout) {
01122                 digit_started = switch_micro_time_now();
01123         }
01124         while (switch_channel_ready(channel)) {
01125                 switch_frame_t *read_frame = NULL;
01126                 switch_event_t *event;
01127                 switch_dtmf_t dtmf = { 0 };
01128 
01129                 if (switch_channel_test_flag(channel, CF_BREAK)) {
01130                         switch_channel_clear_flag(channel, CF_BREAK);
01131                         status = SWITCH_STATUS_BREAK;
01132                         break;
01133                 }
01134 
01135                 if (abs_timeout) {
01136                         abs_elapsed = (uint32_t) ((switch_micro_time_now() - abs_started) / 1000);
01137                         if (abs_elapsed >= abs_timeout) {
01138                                 status = SWITCH_STATUS_TIMEOUT;
01139                                 break;
01140                         }
01141                 }
01142                 if (digit_timeout) {
01143                         digit_elapsed = (uint32_t) ((switch_micro_time_now() - digit_started) / 1000);
01144                         if (digit_elapsed >= digit_timeout) {
01145                                 status = SWITCH_STATUS_TIMEOUT;
01146                                 break;
01147                         }
01148                 }
01149 
01150 
01151                 switch_ivr_parse_all_events(session);
01152 
01153 
01154                 if (switch_channel_has_dtmf(channel)) {
01155                         if (!args->input_callback && !args->buf && !args->dmachine) {
01156                                 status = SWITCH_STATUS_BREAK;
01157                                 break;
01158                         }
01159                         switch_channel_dequeue_dtmf(channel, &dtmf);
01160 
01161                         if (args->dmachine) {
01162                                 char ds[2] = {dtmf.digit, '\0'};
01163                                 if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
01164                                         break;
01165                                 }
01166                         } 
01167 
01168                         if (args->input_callback) {
01169                                 status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
01170                         }
01171 
01172                         if (digit_timeout) {
01173                                 digit_started = switch_micro_time_now();
01174                         }
01175                 }
01176 
01177                 if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
01178                         status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
01179                         switch_event_destroy(&event);
01180                 }
01181 
01182                 if (status != SWITCH_STATUS_SUCCESS) {
01183                         break;
01184                 }
01185 
01186                 if (switch_channel_test_flag(channel, CF_SERVICE)) {
01187                         switch_cond_next();
01188                 } else {
01189                         status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
01190                 }
01191 
01192                 if (!SWITCH_READ_ACCEPTABLE(status)) {
01193                         break;
01194                 }
01195 
01196                 if (args && args->dmachine) {
01197                         if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
01198                                 break;
01199                         }
01200                 }
01201 
01202                 if (read_frame && args && (args->read_frame_callback)) {
01203                         if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
01204                                 break;
01205                         }
01206                 }
01207         }
01208 
01209         return status;
01210 }

switch_status_t switch_ivr_collect_digits_count ( switch_core_session_t session,
char *  buf,
switch_size_t  buflen,
switch_size_t  maxdigits,
const char *  terminators,
char *  terminator,
uint32_t  first_timeout,
uint32_t  digit_timeout,
uint32_t  abs_timeout 
)

Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up.

Parameters:
session the session to read.
buf strig to write to
buflen max size of buf
maxdigits max number of digits to read
terminators digits to end the collection
terminator actual digit that caused the collection to end (if any)
first_timeout timeout in ms
digit_timeout digit timeout in ms
abs_timeout abs timeout in ms
Returns:
SWITCH_STATUS_SUCCESS to keep the collection moving.

Definition at line 1212 of file switch_ivr.c.

References switch_frame::buflen, CF_SERVICE, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, switch_frame::samples, switch_codec_implementation::samples_per_second, switch_channel_dequeue_dtmf(), switch_channel_get_variable, switch_channel_has_dtmf(), switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_test_flag(), SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_cond_next(), 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_core_session_write_frame(), switch_generate_sln_silence(), SWITCH_IO_FLAG_NONE, switch_ivr_parse_all_events(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), switch_micro_time_now(), SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, switch_zmalloc, and zstr.

Referenced by fs_switch_ivr_collect_digits_count(), CoreSession::getDigits(), play_and_collect(), and switch_ivr_read().

01218 {
01219         switch_size_t i = 0, x = strlen(buf);
01220         switch_channel_t *channel = switch_core_session_get_channel(session);
01221         switch_status_t status = SWITCH_STATUS_FALSE;
01222         switch_time_t started = 0, digit_started = 0;
01223         uint32_t abs_elapsed = 0, digit_elapsed = 0;
01224         uint32_t eff_timeout = 0;
01225         switch_frame_t write_frame = { 0 };
01226         unsigned char *abuf = NULL;
01227         switch_codec_implementation_t imp = { 0 };
01228         switch_codec_t codec = { 0 };
01229         int sval = 0;
01230         const char *var;
01231 
01232         if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
01233                 switch_core_session_get_read_impl(session, &imp);
01234 
01235                 if (switch_core_codec_init(&codec,
01236                                                                    "L16",
01237                                                                    NULL,
01238                                                                    imp.samples_per_second,
01239                                                                    imp.microseconds_per_packet / 1000,
01240                                                                    imp.number_of_channels,
01241                                                                    SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
01242                                                                    switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
01243                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
01244                                                           imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
01245                         return SWITCH_STATUS_FALSE;
01246                 }
01247 
01248 
01249                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
01250                                                   imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
01251 
01252                 write_frame.codec = &codec;
01253                 switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE);
01254                 write_frame.data = abuf;
01255                 write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
01256                 write_frame.datalen = imp.decoded_bytes_per_packet;
01257                 write_frame.samples = write_frame.datalen / sizeof(int16_t);
01258         }
01259 
01260         if (terminator != NULL) {
01261                 *terminator = '\0';
01262         }
01263 
01264         if (!zstr(terminators)) {
01265                 for (i = 0; i < x; i++) {
01266                         if (strchr(terminators, buf[i]) && terminator != NULL) {
01267                                 *terminator = buf[i];
01268                                 buf[i] = '\0';
01269                                 return SWITCH_STATUS_SUCCESS;
01270                         }
01271                 }
01272         }
01273 
01274         if (abs_timeout) {
01275                 started = switch_micro_time_now();
01276         }
01277 
01278         if (digit_timeout && first_timeout) {
01279                 eff_timeout = first_timeout;
01280         } else if (digit_timeout && !first_timeout) {
01281                 first_timeout = eff_timeout = digit_timeout;
01282         } else if (first_timeout) {
01283                 digit_timeout = eff_timeout = first_timeout;
01284         }
01285 
01286 
01287         if (eff_timeout) {
01288                 digit_started = switch_micro_time_now();
01289         }
01290 
01291         while (switch_channel_ready(channel)) {
01292                 switch_frame_t *read_frame;
01293 
01294                 if (abs_timeout) {
01295                         abs_elapsed = (uint32_t) ((switch_micro_time_now() - started) / 1000);
01296                         if (abs_elapsed >= abs_timeout) {
01297                                 status = SWITCH_STATUS_TIMEOUT;
01298                                 break;
01299                         }
01300                 }
01301 
01302 
01303                 switch_ivr_parse_all_events(session);
01304 
01305 
01306 
01307                 if (eff_timeout) {
01308                         digit_elapsed = (uint32_t) ((switch_micro_time_now() - digit_started) / 1000);
01309 
01310                         if (digit_elapsed >= eff_timeout) {
01311                                 status = SWITCH_STATUS_TIMEOUT;
01312                                 break;
01313                         }
01314                 }
01315 
01316                 if (switch_channel_has_dtmf(channel)) {
01317                         switch_dtmf_t dtmf = { 0 };
01318                         switch_size_t y;
01319 
01320                         if (eff_timeout) {
01321                                 eff_timeout = digit_timeout;
01322                                 digit_started = switch_micro_time_now();
01323                         }
01324 
01325                         for (y = 0; y <= maxdigits; y++) {
01326                                 if (switch_channel_dequeue_dtmf(channel, &dtmf) != SWITCH_STATUS_SUCCESS) {
01327                                         break;
01328                                 }
01329 
01330                                 if (!zstr(terminators) && strchr(terminators, dtmf.digit) && terminator != NULL) {
01331                                         *terminator = dtmf.digit;
01332                                         return SWITCH_STATUS_SUCCESS;
01333                                 }
01334 
01335 
01336                                 buf[x++] = dtmf.digit;
01337                                 buf[x] = '\0';
01338 
01339                                 if (x >= buflen || x >= maxdigits) {
01340                                         return SWITCH_STATUS_SUCCESS;
01341                                 }
01342                         }
01343                 }
01344 
01345                 if (switch_channel_test_flag(channel, CF_SERVICE)) {
01346                         switch_cond_next();
01347                 } else {
01348                         status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
01349                         if (!SWITCH_READ_ACCEPTABLE(status)) {
01350                                 break;
01351                         }
01352 
01353                         if (write_frame.data) {
01354                                 switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, sval);
01355                                 switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
01356                         }
01357 
01358                 }
01359         }
01360 
01361         if (write_frame.codec) {
01362                 switch_core_codec_destroy(&codec);
01363         }
01364 
01365         switch_safe_free(abuf);
01366 
01367         return status;
01368 }

switch_status_t switch_ivr_deactivate_unicast ( switch_core_session_t session  ) 

Definition at line 352 of file switch_ivr.c.

References CF_UNICAST, switch_unicast_conninfo::read_codec, switch_unicast_conninfo::socket, SUF_READY, SUF_THREAD_RUNNING, switch_channel_clear_flag(), switch_channel_get_private(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_test_flag(), switch_clear_flag_locked, switch_core_codec_destroy(), switch_core_codec_ready(), switch_core_session_get_channel(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_SHUTDOWN_READWRITE, switch_socket_close(), switch_socket_shutdown(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_test_flag, and switch_yield.

Referenced by switch_core_session_perform_destroy(), switch_core_session_reset(), and switch_ivr_park().

00353 {
00354         switch_channel_t *channel = switch_core_session_get_channel(session);
00355         switch_unicast_conninfo_t *conninfo;
00356         int sanity = 0;
00357 
00358         if (!switch_channel_test_flag(channel, CF_UNICAST)) {
00359                 return SWITCH_STATUS_FALSE;
00360         }
00361 
00362         if ((conninfo = switch_channel_get_private(channel, "unicast"))) {
00363                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Shutting down unicast connection\n");
00364                 switch_clear_flag_locked(conninfo, SUF_READY);
00365                 switch_socket_shutdown(conninfo->socket, SWITCH_SHUTDOWN_READWRITE);
00366                 while (switch_test_flag(conninfo, SUF_THREAD_RUNNING)) {
00367                         switch_yield(10000);
00368                         if (++sanity >= 10000) {
00369                                 break;
00370                         }
00371                 }
00372                 if (switch_core_codec_ready(&conninfo->read_codec)) {
00373                         switch_core_codec_destroy(&conninfo->read_codec);
00374                 }
00375                 switch_socket_close(conninfo->socket);
00376         }
00377         switch_channel_clear_flag(channel, CF_UNICAST);
00378         return SWITCH_STATUS_SUCCESS;
00379 }

switch_status_t switch_ivr_detect_speech ( switch_core_session_t session,
const char *  mod_name,
const char *  grammar,
const char *  name,
const char *  dest,
switch_asr_handle_t ah 
)

Engage background Speech detection on a session.

Parameters:
session the session to attach
mod_name the module name of the ASR library
grammar the grammar text, URI, or local file name
name the grammar name
dest the destination address
ah an ASR handle to use (NULL to create one)
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3801 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, speech_thread_handle::ah, SMBF_NO_PAUSE, SMBF_READ_STREAM, speech_callback(), speech_on_dtmf(), SWITCH_ASR_FLAG_FIRE_EVENTS, SWITCH_ASR_FLAG_NONE, switch_channel_get_private(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), switch_core_asr_close(), switch_core_asr_load_grammar(), switch_core_asr_open(), switch_core_media_bug_add(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_ivr_stop_detect_speech(), SWITCH_LOG_DEBUG, switch_log_printf(), switch_set_flag, switch_snprintf(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, and switch_true().

Referenced by switch_ivr_play_and_detect_speech().

03804 {
03805         switch_channel_t *channel = switch_core_session_get_channel(session);
03806         switch_status_t status;
03807         switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
03808         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03809         switch_codec_implementation_t read_impl = { 0 };
03810         const char *p;
03811         char key[512] = "";
03812 
03813         switch_core_session_get_read_impl(session, &read_impl);
03814 
03815         switch_snprintf(key, sizeof(key), "%s/%s/%s/%s", mod_name, grammar, name, dest);
03816 
03817         if (!ah) {
03818                 if (!(ah = switch_core_session_alloc(session, sizeof(*ah)))) {
03819                         return SWITCH_STATUS_MEMERR;
03820                 }
03821         }
03822 
03823         if (sth) {
03824                 if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) {
03825                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
03826                         switch_ivr_stop_detect_speech(session);
03827                         return SWITCH_STATUS_FALSE;
03828                 }
03829 
03830                 if ((p = switch_channel_get_variable(channel, "fire_asr_events")) && switch_true(p)) {
03831                         switch_set_flag(sth->ah, SWITCH_ASR_FLAG_FIRE_EVENTS);
03832                 }
03833 
03834                 return SWITCH_STATUS_SUCCESS;
03835         }
03836 
03837         if ((status = switch_core_asr_open(ah,
03838                                                                            mod_name,
03839                                                                            "L16",
03840                                                                            read_impl.actual_samples_per_second, dest, &flags,
03841                                                                            switch_core_session_get_pool(session))) == SWITCH_STATUS_SUCCESS) {
03842 
03843                 if (switch_core_asr_load_grammar(ah, grammar, name) != SWITCH_STATUS_SUCCESS) {
03844                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
03845                         switch_core_asr_close(ah, &flags);
03846                         return SWITCH_STATUS_FALSE;
03847                 }
03848         } else {
03849                 return status;
03850         }
03851 
03852         sth = switch_core_session_alloc(session, sizeof(*sth));
03853         sth->pool = switch_core_session_get_pool(session);
03854         sth->session = session;
03855         sth->ah = ah;
03856 
03857         if ((p = switch_channel_get_variable(channel, "fire_asr_events")) && switch_true(p)) {
03858                 switch_set_flag(ah, SWITCH_ASR_FLAG_FIRE_EVENTS);
03859         }
03860 
03861         if ((status = switch_core_media_bug_add(session, "detect_speech", key,
03862                                                                                         speech_callback, sth, 0, SMBF_READ_STREAM | SMBF_NO_PAUSE, &sth->bug)) != SWITCH_STATUS_SUCCESS) {
03863                 switch_core_asr_close(ah, &flags);
03864                 return status;
03865         }
03866 
03867         if ((status = switch_core_event_hook_add_recv_dtmf(session, speech_on_dtmf)) != SWITCH_STATUS_SUCCESS) {
03868                 switch_ivr_stop_detect_speech(session);
03869                 return status;
03870         }
03871 
03872         switch_channel_set_private(channel, SWITCH_SPEECH_KEY, sth);
03873 
03874         return SWITCH_STATUS_SUCCESS;
03875 }

switch_status_t switch_ivr_detect_speech_disable_all_grammars ( switch_core_session_t session  ) 

Disable all grammars on a background speech detection handle.

Parameters:
session The session to change the grammar on
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3785 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), SWITCH_CHANNEL_SESSION_LOG, switch_core_asr_disable_all_grammars(), switch_core_session_get_channel(), switch_ivr_stop_detect_speech(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

03786 {
03787         switch_channel_t *channel = switch_core_session_get_channel(session);
03788         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03789         switch_status_t status;
03790 
03791         if (sth) {
03792                 if ((status = switch_core_asr_disable_all_grammars(sth->ah)) != SWITCH_STATUS_SUCCESS) {
03793                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error disabling all Grammars\n");
03794                         switch_ivr_stop_detect_speech(session);
03795                 }
03796                 return status;
03797         }
03798         return SWITCH_STATUS_FALSE;
03799 }

switch_status_t switch_ivr_detect_speech_disable_grammar ( switch_core_session_t session,
const char *  name 
)

Disable a grammar on a background speech detection handle.

Parameters:
session The session to change the grammar on
name the grammar name
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3769 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), SWITCH_CHANNEL_SESSION_LOG, switch_core_asr_disable_grammar(), switch_core_session_get_channel(), switch_ivr_stop_detect_speech(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

03770 {
03771         switch_channel_t *channel = switch_core_session_get_channel(session);
03772         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03773         switch_status_t status;
03774 
03775         if (sth) {
03776                 if ((status = switch_core_asr_disable_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
03777                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error disabling Grammar\n");
03778                         switch_ivr_stop_detect_speech(session);
03779                 }
03780                 return status;
03781         }
03782         return SWITCH_STATUS_FALSE;
03783 }

switch_status_t switch_ivr_detect_speech_enable_grammar ( switch_core_session_t session,
const char *  name 
)

Enable a grammar on a background speech detection handle.

Parameters:
session The session to change the grammar on
name the grammar name
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3753 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), SWITCH_CHANNEL_SESSION_LOG, switch_core_asr_enable_grammar(), switch_core_session_get_channel(), switch_ivr_stop_detect_speech(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

03754 {
03755         switch_channel_t *channel = switch_core_session_get_channel(session);
03756         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03757         switch_status_t status;
03758 
03759         if (sth) {
03760                 if ((status = switch_core_asr_enable_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
03761                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error enabling Grammar\n");
03762                         switch_ivr_stop_detect_speech(session);
03763                 }
03764                 return status;
03765         }
03766         return SWITCH_STATUS_FALSE;
03767 }

switch_status_t switch_ivr_detect_speech_load_grammar ( switch_core_session_t session,
char *  grammar,
char *  name 
)

Load a grammar on a background speech detection handle.

Parameters:
session The session to change the grammar on
grammar the grammar text, URI, or local file name
name the grammar name
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3696 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), SWITCH_CHANNEL_SESSION_LOG, switch_core_asr_load_grammar(), switch_core_session_get_channel(), switch_ivr_stop_detect_speech(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

03697 {
03698         switch_channel_t *channel = switch_core_session_get_channel(session);
03699         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03700         switch_status_t status;
03701 
03702         if (sth) {
03703                 if ((status = switch_core_asr_load_grammar(sth->ah, grammar, name)) != SWITCH_STATUS_SUCCESS) {
03704                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
03705                         switch_ivr_stop_detect_speech(session);
03706                 }
03707                 return status;
03708         }
03709         return SWITCH_STATUS_FALSE;
03710 }

switch_status_t switch_ivr_detect_speech_start_input_timers ( switch_core_session_t session  ) 

Start input timers on a background speech detection handle.

Parameters:
session The session to start the timers on
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3725 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), switch_core_asr_start_input_timers(), switch_core_session_get_channel(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_play_and_detect_speech().

03726 {
03727         switch_channel_t *channel = switch_core_session_get_channel(session);
03728         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03729 
03730         if (sth) {
03731                 switch_core_asr_start_input_timers(sth->ah);
03732                 return SWITCH_STATUS_SUCCESS;
03733         }
03734         return SWITCH_STATUS_FALSE;
03735 }

switch_status_t switch_ivr_detect_speech_unload_grammar ( switch_core_session_t session,
const char *  name 
)

Unload a grammar on a background speech detection handle.

Parameters:
session The session to change the grammar on
name the grammar name
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3737 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), SWITCH_CHANNEL_SESSION_LOG, switch_core_asr_unload_grammar(), switch_core_session_get_channel(), switch_ivr_stop_detect_speech(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

03738 {
03739         switch_channel_t *channel = switch_core_session_get_channel(session);
03740         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03741         switch_status_t status;
03742 
03743         if (sth) {
03744                 if ((status = switch_core_asr_unload_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
03745                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error unloading Grammar\n");
03746                         switch_ivr_stop_detect_speech(session);
03747                 }
03748                 return status;
03749         }
03750         return SWITCH_STATUS_FALSE;
03751 }

switch_status_t switch_ivr_digit_stream_destroy ( switch_ivr_digit_stream_t **  stream  ) 

Destroys a digit stream object.

Parameters:
stream a pointer to the stream object
Returns:
NULL if no match found or consumer data that was associated with a given digit string when matched

Definition at line 1873 of file switch_ivr.c.

References switch_safe_free, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

01874 {
01875         switch_status_t status = SWITCH_STATUS_FALSE;
01876 
01877         if (*stream) {
01878                 switch_safe_free((*stream)->digits);
01879                 free(*stream);
01880                 *stream = NULL;
01881                 status = SWITCH_STATUS_SUCCESS;
01882         }
01883 
01884         return status;
01885 }

switch_status_t switch_ivr_digit_stream_new ( switch_ivr_digit_stream_parser_t parser,
switch_ivr_digit_stream_t **  stream 
)

Create a new digit stream object.

Parameters:
parser a pointer to the parser object created by switch_ivr_digit_stream_parser_new
stream a pointer to the stream object pointer
Returns:
NULL if no match found or consumer data that was associated with a given digit string when matched

Definition at line 1857 of file switch_ivr.c.

References switch_assert, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_zmalloc.

01858 {
01859         switch_status_t status = SWITCH_STATUS_FALSE;
01860 
01861         /* if we have a parser object memory pool and a stream object pointer that is null */
01862         if (parser && stream && *stream == NULL) {
01863                 *stream = (switch_ivr_digit_stream_t *) malloc(sizeof(**stream));
01864                 switch_assert(*stream);
01865                 memset(*stream, 0, sizeof(**stream));
01866                 switch_zmalloc((*stream)->digits, parser->buflen + 1);
01867                 status = SWITCH_STATUS_SUCCESS;
01868         }
01869 
01870         return status;
01871 }

switch_status_t switch_ivr_digit_stream_parser_del_event ( switch_ivr_digit_stream_parser_t parser,
char *  digits 
)

Delete a string to action mapping.

Parameters:
parser a pointer to the parser object created by switch_ivr_digit_stream_parser_new
digits the digit string to be removed from the map
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1929 of file switch_ivr.c.

References SWITCH_CHANNEL_LOG, switch_core_hash_delete(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

01930 {
01931         switch_status_t status = SWITCH_STATUS_FALSE;
01932 
01933         if (parser != NULL && digits != NULL && *digits) {
01934                 status = switch_core_hash_delete(parser->hash, digits);
01935         }
01936 
01937         if (status != SWITCH_STATUS_SUCCESS) {
01938                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to del hash for '%s'\n", digits);
01939         }
01940 
01941         return status;
01942 }

switch_status_t switch_ivr_digit_stream_parser_destroy ( switch_ivr_digit_stream_parser_t parser  ) 

Destroy a digit stream parser object.

Parameters:
parser a pointer to the parser object
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1839 of file switch_ivr.c.

References switch_core_destroy_memory_pool, switch_core_hash_destroy(), and SWITCH_STATUS_FALSE.

01840 {
01841         switch_status_t status = SWITCH_STATUS_FALSE;
01842 
01843         if (parser != NULL) {
01844                 if (parser->hash != NULL) {
01845                         switch_core_hash_destroy(&parser->hash);
01846                         parser->hash = NULL;
01847                 }
01848                 /* free the memory pool if we created it */
01849                 if (parser->pool_auto_created && parser->pool != NULL) {
01850                         status = switch_core_destroy_memory_pool(&parser->pool);
01851                 }
01852         }
01853 
01854         return status;
01855 }

void* switch_ivr_digit_stream_parser_feed ( switch_ivr_digit_stream_parser_t parser,
switch_ivr_digit_stream_t stream,
char  digit 
)

Feed digits collected into the stream for event match testing.

Parameters:
parser a pointer to the parser object created by switch_ivr_digit_stream_parser_new
stream a stream to write data to
digit a digit to collect and test against the map of digit strings
Returns:
NULL if no match found or consumer data that was associated with a given digit string when matched

Definition at line 1944 of file switch_ivr.c.

References switch_assert, switch_core_hash_find(), and switch_micro_time_now().

01945 {
01946         void *result = NULL;
01947         switch_size_t len;
01948 
01949         switch_assert(parser);
01950         switch_assert(stream);
01951         switch_assert(stream->digits);
01952 
01953         len = strlen(stream->digits);
01954 
01955         /* handle new digit arrivals */
01956         if (digit) {
01957                 /* if it's not a terminator digit, add it to the collected digits */
01958                 if (digit != parser->terminator) {
01959                         /* if collected digits length >= the max length of the keys
01960                          * in the hash table, then left shift the digit string
01961                          */
01962                         if (len > 0 && parser->maxlen != 0 && len >= parser->maxlen) {
01963                                 char *src = stream->digits + 1;
01964                                 char *dst = stream->digits;
01965 
01966                                 while (*src) {
01967                                         *(dst++) = *(src++);
01968                                 }
01969                                 *dst = digit;
01970                         } else {
01971                                 *(stream->digits + (len++)) = digit;
01972                                 *(stream->digits + len) = '\0';
01973                                 stream->last_digit_time = switch_micro_time_now() / 1000;
01974                         }
01975                 }
01976         }
01977 
01978         /* don't allow collected digit string testing if there are varying sized keys until timeout */
01979         if (parser->maxlen - parser->minlen > 0 && (switch_micro_time_now() / 1000) - stream->last_digit_time < parser->digit_timeout_ms) {
01980                 len = 0;
01981         }
01982         /* if we have digits to test */
01983         if (len) {
01984                 result = switch_core_hash_find(parser->hash, stream->digits);
01985                 /* if we matched the digit string, or this digit is the terminator
01986                  * reset the collected digits for next digit string
01987                  */
01988                 if (result != NULL || parser->terminator == digit) {
01989                         *stream->digits = '\0';
01990                 }
01991         }
01992 
01993 
01994         return result;
01995 }

switch_status_t switch_ivr_digit_stream_parser_new ( switch_memory_pool_t pool,
switch_ivr_digit_stream_parser_t **  parser 
)

Create a digit stream parser object.

Parameters:
pool the pool to use for the new hash
parser a pointer to the object pointer
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1799 of file switch_ivr.c.

References SWITCH_CHANNEL_LOG, switch_core_alloc, switch_core_destroy_memory_pool, switch_core_hash_init, switch_core_new_memory_pool, SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, and SWITCH_STATUS_SUCCESS.

01800 {
01801         switch_status_t status = SWITCH_STATUS_FALSE;
01802 
01803         if (parser != NULL) {
01804                 int pool_auto_created = 0;
01805 
01806                 /* if the caller didn't provide a pool, make one */
01807                 if (pool == NULL) {
01808                         switch_core_new_memory_pool(&pool);
01809                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "created a memory pool\n");
01810                         if (pool != NULL) {
01811                                 pool_auto_created = 1;
01812                         }
01813                 }
01814                 /* if we have a pool, make a parser object */
01815                 if (pool != NULL) {
01816                         *parser = (switch_ivr_digit_stream_parser_t *) switch_core_alloc(pool, sizeof(switch_ivr_digit_stream_parser_t));
01817                 }
01818                 /* if we have parser object, initialize it for the caller */
01819                 if (pool && *parser != NULL) {
01820                         memset(*parser, 0, sizeof(switch_ivr_digit_stream_parser_t));
01821                         (*parser)->pool_auto_created = pool_auto_created;
01822                         (*parser)->pool = pool;
01823                         (*parser)->digit_timeout_ms = 1000;
01824                         switch_core_hash_init(&(*parser)->hash, (*parser)->pool);
01825 
01826                         status = SWITCH_STATUS_SUCCESS;
01827                 } else {
01828                         status = SWITCH_STATUS_MEMERR;
01829                         /* if we can't create a parser object,clean up the pool if we created it */
01830                         if (pool != NULL && pool_auto_created) {
01831                                 switch_core_destroy_memory_pool(&pool);
01832                         }
01833                 }
01834         }
01835 
01836         return status;
01837 }

switch_status_t switch_ivr_digit_stream_parser_set_event ( switch_ivr_digit_stream_parser_t parser,
char *  digits,
void *  data 
)

Set a digit string to action mapping.

Parameters:
parser a pointer to the parser object created by switch_ivr_digit_stream_parser_new
digits a string of digits to associate with an action
data consumer data attached to this digit string
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1887 of file switch_ivr.c.

References SWITCH_CHANNEL_LOG, switch_core_hash_insert(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

01888 {
01889         switch_status_t status = SWITCH_STATUS_FALSE;
01890 
01891         if (parser != NULL && digits != NULL && *digits && parser->hash != NULL) {
01892 
01893                 status = switch_core_hash_insert(parser->hash, digits, data);
01894                 if (status == SWITCH_STATUS_SUCCESS) {
01895                         switch_size_t len = strlen(digits);
01896 
01897                         /* if we don't have a terminator, then we have to try and
01898                          * figure out when a digit set is completed, therefore we
01899                          * keep track of the min and max digit lengths
01900                          */
01901 
01902                         if (len > parser->buflen) {
01903                                 parser->buflen = len;
01904                         }
01905 
01906                         if (parser->terminator == '\0') {
01907                                 if (len > parser->maxlen) {
01908                                         parser->maxlen = len;
01909                                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "max len %u\n", (uint32_t) parser->maxlen);
01910                                 }
01911                                 if (parser->minlen == 0 || len < parser->minlen) {
01912                                         parser->minlen = len;
01913                                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "min len %u\n", (uint32_t) parser->minlen);
01914                                 }
01915                         } else {
01916                                 /* since we have a terminator, reset min and max */
01917                                 parser->minlen = 0;
01918                                 parser->maxlen = 0;
01919                         }
01920                 }
01921         }
01922         if (status != SWITCH_STATUS_SUCCESS) {
01923                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to add hash for '%s'\n", digits);
01924         }
01925 
01926         return status;
01927 }

switch_status_t switch_ivr_digit_stream_parser_set_terminator ( switch_ivr_digit_stream_parser_t parser,
char  digit 
)

Set a digit string terminator.

Parameters:
parser a pointer to the parser object created by switch_ivr_digit_stream_parser_new
digit the terminator digit
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2010 of file switch_ivr.c.

References SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

02011 {
02012         switch_status_t status = SWITCH_STATUS_FALSE;
02013 
02014         if (parser != NULL) {
02015                 parser->terminator = digit;
02016                 /* since we have a terminator, reset min and max */
02017                 parser->minlen = 0;
02018                 parser->maxlen = 0;
02019                 status = SWITCH_STATUS_SUCCESS;
02020         }
02021 
02022         return status;
02023 }

switch_status_t switch_ivr_digit_stream_reset ( switch_ivr_digit_stream_t stream  ) 

Reset the collected digit stream to nothing.

Parameters:
stream a pointer to the parser stream object created by switch_ivr_digit_stream_new
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1997 of file switch_ivr.c.

References switch_assert, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

01998 {
01999         switch_status_t status = SWITCH_STATUS_FALSE;
02000         switch_assert(stream);
02001         switch_assert(stream->digits);
02002 
02003         *stream->digits = '\0';
02004         stream->last_digit_time = 0;
02005         status = SWITCH_STATUS_SUCCESS;
02006 
02007         return status;
02008 }

switch_status_t switch_ivr_displace_session ( switch_core_session_t session,
const char *  file,
uint32_t  limit,
const char *  flags 
)

displace the media for a session with the audio from a file

Parameters:
session the session to displace
file filename
limit time limit in ms
flags m (mux) l (loop) or r(read session instead of write session)
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 881 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, switch_directories::base_dir, switch_codec_implementation::iananame, switch_codec_implementation::number_of_channels, read_displace_callback(), SMBF_NO_PAUSE, SMBF_READ_REPLACE, SMBF_WRITE_REPLACE, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, switch_channel_get_private(), switch_channel_get_variable, switch_channel_hangup, switch_channel_media_up, switch_channel_pre_answer, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), switch_core_file_close(), switch_core_file_open, switch_core_media_bug_add(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_read_codec(), switch_core_session_get_read_impl(), switch_core_session_reset(), switch_core_session_sprintf(), switch_core_session_strdup, switch_epoch_time_now(), SWITCH_FILE_DATA_SHORT, SWITCH_FILE_FLAG_READ, switch_find_end_paren(), SWITCH_GLOBAL_dirs, switch_is_file_path(), SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_PATH_SEPARATOR, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, switch_str_nil, SWITCH_TRUE, SWITCH_URL_SEPARATOR, write_displace_callback(), and zstr.

00882 {
00883         switch_channel_t *channel = switch_core_session_get_channel(session);
00884         switch_media_bug_t *bug;
00885         switch_status_t status;
00886         time_t to = 0;
00887         char *ext;
00888         const char *prefix;
00889         displace_helper_t *dh;
00890         switch_codec_implementation_t read_impl = { 0 };
00891         switch_core_session_get_read_impl(session, &read_impl);
00892 
00893         if (zstr(file)) {
00894                 return SWITCH_STATUS_FALSE;
00895         }
00896 
00897         if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
00898                 return SWITCH_STATUS_FALSE;
00899         }
00900 
00901         if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
00902                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not displace session.  Media not enabled on channel\n");
00903                 return SWITCH_STATUS_FALSE;
00904         }
00905 
00906         if ((bug = switch_channel_get_private(channel, file))) {
00907                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only 1 of the same file per channel please!\n");
00908                 return SWITCH_STATUS_FALSE;
00909         }
00910 
00911         if (!(dh = switch_core_session_alloc(session, sizeof(*dh)))) {
00912                 return SWITCH_STATUS_MEMERR;
00913         }
00914 
00915         if (!(prefix = switch_channel_get_variable(channel, "sound_prefix"))) {
00916                 prefix = SWITCH_GLOBAL_dirs.base_dir;
00917         }
00918 
00919         if (!strstr(file, SWITCH_URL_SEPARATOR)) {
00920                 if (!switch_is_file_path(file)) {
00921                         char *tfile = NULL;
00922                         char *e;
00923 
00924                         if (*file == '[') {
00925                                 tfile = switch_core_session_strdup(session, file);
00926                                 if ((e = switch_find_end_paren(tfile, '[', ']'))) {
00927                                         *e = '\0';
00928                                         file = e + 1;
00929                                 } else {
00930                                         tfile = NULL;
00931                                 }
00932                         }
00933 
00934                         file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
00935                 }
00936                 if ((ext = strrchr(file, '.'))) {
00937                         ext++;
00938                 } else {
00939                         ext = read_impl.iananame;
00940                         file = switch_core_session_sprintf(session, "%s.%s", file, ext);
00941                 }
00942         }
00943 
00944         dh->fh.channels = read_impl.number_of_channels;
00945         dh->fh.samplerate = read_impl.actual_samples_per_second;
00946         dh->file = switch_core_session_strdup(session, file);
00947 
00948         if (switch_core_file_open(&dh->fh,
00949                                                           file,
00950                                                           read_impl.number_of_channels,
00951                                                           read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
00952                 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
00953                 switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
00954                 return SWITCH_STATUS_GENERR;
00955         }
00956 
00957         if (limit) {
00958                 to = switch_epoch_time_now(NULL) + limit;
00959         }
00960 
00961         if (flags && strchr(flags, 'm')) {
00962                 dh->mux++;
00963         }
00964 
00965         if (flags && strchr(flags, 'l')) {
00966                 dh->loop++;
00967         }
00968 
00969         if (flags && strchr(flags, 'r')) {
00970                 status = switch_core_media_bug_add(session, "displace", file,
00971                                                                                    read_displace_callback, dh, to, SMBF_WRITE_REPLACE | SMBF_READ_REPLACE | SMBF_NO_PAUSE, &bug);
00972         } else {
00973                 status = switch_core_media_bug_add(session, "displace", file,
00974                                                                                    write_displace_callback, dh, to, SMBF_WRITE_REPLACE | SMBF_READ_REPLACE | SMBF_NO_PAUSE, &bug);
00975         }
00976 
00977         if (status != SWITCH_STATUS_SUCCESS) {
00978                 switch_core_file_close(&dh->fh);
00979                 return status;
00980         }
00981 
00982         switch_channel_set_private(channel, file, bug);
00983 
00984         return SWITCH_STATUS_SUCCESS;
00985 }

switch_status_t switch_ivr_eavesdrop_exec_all ( switch_core_session_t session,
const char *  app,
const char *  arg 
)

Definition at line 1301 of file switch_ivr_async.c.

References exec_cb(), switch_core_media_bug_exec_all(), switch_core_session_alloc, and switch_core_session_strdup.

01302 {
01303         struct exec_cb_data *data = NULL;
01304 
01305         data = switch_core_session_alloc(session, sizeof(*data));
01306         data->var = switch_core_session_strdup(session, app);
01307         data->val = switch_core_session_strdup(session, arg);
01308         data->caller = session;
01309 
01310         return switch_core_media_bug_exec_all(session, "eavesdrop", exec_cb, data);
01311 }

switch_status_t switch_ivr_eavesdrop_pop_eavesdropper ( switch_core_session_t session,
switch_core_session_t **  sessionp 
)

Definition at line 1242 of file switch_ivr_async.c.

References eavesdrop_pvt::eavesdropper, SMBF_PRUNE, switch_core_media_bug_get_user_data(), switch_core_media_bug_pop(), switch_core_media_bug_set_flag(), switch_core_session_read_lock(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

01243 {
01244         switch_media_bug_t *bug;
01245         switch_status_t status = SWITCH_STATUS_FALSE;
01246 
01247         if (switch_core_media_bug_pop(session, "eavesdrop", &bug) == SWITCH_STATUS_SUCCESS) {
01248                 struct eavesdrop_pvt *ep = (struct eavesdrop_pvt *) switch_core_media_bug_get_user_data(bug);
01249 
01250                 if (ep && ep->eavesdropper && ep->eavesdropper != session) {
01251                         switch_core_session_read_lock(ep->eavesdropper);
01252                         *sessionp = ep->eavesdropper;
01253                         switch_core_media_bug_set_flag(bug, SMBF_PRUNE);
01254                         status = SWITCH_STATUS_SUCCESS;
01255                 }
01256         }
01257 
01258 
01259         return status;
01260 }

switch_status_t switch_ivr_eavesdrop_session ( switch_core_session_t session,
const char *  uuid,
const char *  require_group,
switch_eavesdrop_flag_t  flags 
)

Eavesdrop on a another session.

Parameters:
session our session
uuid the uuid of the session to spy on
require_group group name to use to limit by group
flags tweak read-mux, write-mux and dtmf
Returns:
SWITCH_STATUS_SUCESS if all is well

Definition at line 1335 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, buf, switch_frame::buflen, switch_caller_profile::callee_id_name, switch_caller_profile::callee_id_number, switch_caller_profile::caller_id_name, switch_caller_profile::caller_id_number, switch_frame::codec, eavesdrop_pvt::data, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, eavesdrop_callback(), ED_COPY_DISPLAY, ED_DTMF, ED_MUX_READ, ED_MUX_WRITE, switch_core_session_message::from, switch_codec::implementation, switch_core_session_message::message_id, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, switch_frame::rate, switch_frame::samples, SFF_CNG, SMBF_NO_PAUSE, SMBF_READ_PING, SMBF_READ_REPLACE, SMBF_READ_STREAM, SMBF_THREAD_LOCK, SMBF_WRITE_REPLACE, SMBF_WRITE_STREAM, switch_core_session_message::string_arg, switch_buffer_add_mutex(), switch_buffer_create_dynamic(), switch_buffer_destroy(), switch_buffer_inuse(), switch_buffer_lock(), switch_buffer_read(), switch_buffer_unlock(), switch_buffer_zero(), switch_buffer_zwrite(), switch_channel_dequeue_dtmf(), switch_channel_get_caller_profile(), switch_channel_get_variable, switch_channel_has_dtmf(), switch_channel_media_up, switch_channel_pre_answer, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_state_change_pending(), switch_channel_up_nosig, switch_clear_flag, SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_core_codec_destroy(), switch_core_codec_init, switch_core_media_bug_add(), switch_core_media_bug_remove(), switch_core_session_alloc, switch_core_session_dequeue_event(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_locate(), switch_core_session_read_frame(), switch_core_session_receive_message, switch_core_session_reset(), switch_core_session_rwunlock(), switch_core_session_set_read_codec(), switch_core_session_strdup, switch_core_session_write_frame(), switch_event_destroy(), switch_event_get_header, SWITCH_FALSE, SWITCH_IO_FLAG_NONE, switch_ivr_phrase_macro, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_MESSAGE_INDICATE_BRIDGE, SWITCH_MESSAGE_INDICATE_DISPLAY, SWITCH_MESSAGE_INDICATE_UNBRIDGE, switch_mutex_init(), SWITCH_MUTEX_NESTED, SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, switch_safe_free, switch_separate_string(), switch_set_flag, switch_snprintf(), SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_test_flag, SWITCH_TRUE, switch_yield, and zstr.

01337 {
01338         switch_core_session_t *tsession;
01339         switch_status_t status = SWITCH_STATUS_FALSE;
01340         switch_channel_t *channel = switch_core_session_get_channel(session);
01341         int codec_initialized = 0;
01342         const char *name, *num;
01343 
01344         if ((tsession = switch_core_session_locate(uuid))) {
01345                 struct eavesdrop_pvt *ep = NULL;
01346                 switch_media_bug_t *bug = NULL;
01347                 switch_channel_t *tchannel = switch_core_session_get_channel(tsession);
01348                 switch_frame_t *read_frame, write_frame = { 0 };
01349                 switch_codec_t codec = { 0 };
01350                 int16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE / 2];
01351                 uint32_t tlen;
01352                 const char *macro_name = "eavesdrop_announce";
01353                 const char *id_name = NULL;
01354                 switch_codec_implementation_t tread_impl = { 0 }, read_impl = { 0 };
01355                 switch_core_session_message_t msg = { 0 };
01356                 char cid_buf[1024] = "";
01357                 switch_caller_profile_t *cp = NULL;
01358                 uint32_t sanity = 600;
01359 
01360                 if (!switch_channel_media_up(channel)) {
01361                         goto end;
01362                 }
01363 
01364                 while(switch_channel_state_change_pending(tchannel) || !switch_channel_media_up(tchannel)) {
01365                         switch_yield(10000);
01366                         if (!--sanity) break;
01367                 }
01368 
01369                 if (!switch_channel_media_up(tchannel)) {
01370                         goto end;
01371                 }
01372 
01373                 switch_core_session_get_read_impl(tsession, &tread_impl);
01374                 switch_core_session_get_read_impl(session, &read_impl);
01375 
01376                 if ((id_name = switch_channel_get_variable(tchannel, "eavesdrop_announce_id"))) {
01377                         const char *tmp = switch_channel_get_variable(tchannel, "eavesdrop_annnounce_macro");
01378                         if (tmp) {
01379                                 macro_name = tmp;
01380                         }
01381 
01382                         switch_ivr_phrase_macro(session, macro_name, id_name, NULL, NULL);
01383                 }
01384 
01385 
01386                 if (!zstr(require_group)) {
01387                         int argc, i;
01388                         int ok = 0;
01389                         char *argv[10] = { 0 };
01390                         char *data;
01391 
01392                         const char *group_name = switch_channel_get_variable(tchannel, "eavesdrop_group");
01393                         /* If we don't have a group, then return */
01394                         if (!group_name) {
01395                                 status = SWITCH_STATUS_BREAK;
01396                                 goto end;
01397                         }
01398                         /* Separate the group */
01399                         data = strdup(group_name);
01400                         if ((argc = switch_separate_string(data, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
01401                                 for (i = 0; i < argc; i++) {
01402                                         /* If one of the group matches, then ok */
01403                                         if (argv[i] && !strcmp(argv[i], require_group)) {
01404                                                 ok = 1;
01405                                         }
01406                                 }
01407                         }
01408                         switch_safe_free(data);
01409                         /* If we didn't find any match, then end */
01410                         if (!ok) {
01411                                 status = SWITCH_STATUS_BREAK;
01412                                 goto end;
01413                         }
01414                 }
01415 
01416 
01417                 ep = switch_core_session_alloc(session, sizeof(*ep));
01418 
01419                 tlen = tread_impl.decoded_bytes_per_packet;
01420 
01421 
01422                 if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
01423                         goto end;
01424                 }
01425 
01426 
01427                 if (switch_core_codec_init(&codec,
01428                                                                    "L16",
01429                                                                    NULL,
01430                                                                    tread_impl.actual_samples_per_second,
01431                                                                    tread_impl.microseconds_per_packet / 1000,
01432                                                                    tread_impl.number_of_channels,
01433                                                                    SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
01434                                                                    NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
01435                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
01436                         switch_core_session_rwunlock(tsession);
01437                         goto end;
01438                 }
01439 
01440                 codec_initialized = 1;
01441 
01442                 switch_core_session_set_read_codec(session, &codec);
01443                 write_frame.codec = &codec;
01444                 write_frame.data = buf;
01445                 write_frame.buflen = sizeof(buf);
01446                 write_frame.rate = codec.implementation->actual_samples_per_second;
01447 
01448                 ep->eavesdropper = session;
01449                 ep->flags = flags;
01450                 switch_mutex_init(&ep->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
01451                 switch_buffer_create_dynamic(&ep->buffer, 2048, 2048, 8192);
01452                 switch_buffer_add_mutex(ep->buffer, ep->mutex);
01453 
01454                 switch_mutex_init(&ep->w_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
01455                 switch_buffer_create_dynamic(&ep->w_buffer, 2048, 2048, 8192);
01456                 switch_buffer_add_mutex(ep->w_buffer, ep->w_mutex);
01457 
01458                 switch_mutex_init(&ep->r_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
01459                 switch_buffer_create_dynamic(&ep->r_buffer, 2048, 2048, 8192);
01460                 switch_buffer_add_mutex(ep->r_buffer, ep->r_mutex);
01461 
01462 
01463                 if (switch_core_media_bug_add(tsession, "eavesdrop", uuid,
01464                                                                           eavesdrop_callback, ep, 0,
01465                                                                           SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_REPLACE | SMBF_WRITE_REPLACE | 
01466                                                                           SMBF_READ_PING | SMBF_THREAD_LOCK | SMBF_NO_PAUSE,
01467                                                                           &bug) != SWITCH_STATUS_SUCCESS) {
01468                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot attach bug\n");
01469                         goto end;
01470                 }
01471 
01472 
01473                 msg.from = __FILE__;
01474 
01475                 /* Tell the channel we are going to be in a bridge */
01476                 msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
01477                 switch_core_session_receive_message(session, &msg);
01478                 cp = switch_channel_get_caller_profile(tchannel);
01479                 name = cp->caller_id_name;
01480                 num = cp->caller_id_number;
01481 
01482                 if (flags & ED_COPY_DISPLAY) {
01483                         const char *tmp_name = NULL, *tmp_num = NULL;
01484                         name = cp->callee_id_name;
01485                         num = cp->callee_id_number;
01486                         
01487                         if (!((tmp_name = switch_channel_get_variable(tchannel, "last_sent_callee_id_name")) 
01488                                   && (tmp_num = switch_channel_get_variable(tchannel, "last_sent_callee_id_number")))) {
01489                                 
01490                                 tmp_name = switch_channel_get_variable(tchannel, "callee_id_name");
01491                                 tmp_num = switch_channel_get_variable(tchannel, "callee_id_number");
01492                         }
01493                         
01494                         if (tmp_name) name = tmp_name;
01495                         if (tmp_num) num = tmp_num;
01496                         
01497                 }
01498 
01499                 switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", name, num);
01500                 msg.string_arg = cid_buf;
01501                 msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
01502                 switch_core_session_receive_message(session, &msg);
01503 
01504                 while (switch_channel_up_nosig(tchannel) && switch_channel_ready(channel)) {
01505                         uint32_t len = sizeof(buf);
01506                         switch_event_t *event = NULL;
01507                         char *fcommand = NULL;
01508                         char db[2] = "";
01509 
01510                         status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
01511 
01512                         if (!SWITCH_READ_ACCEPTABLE(status)) {
01513                                 goto end_loop;
01514                         }
01515 
01516                         if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
01517                                 char *command = switch_event_get_header(event, "eavesdrop-command");
01518                                 if (command) {
01519                                         fcommand = switch_core_session_strdup(session, command);
01520                                 }
01521                                 switch_event_destroy(&event);
01522                         }
01523 
01524                         if ((flags & ED_DTMF) && switch_channel_has_dtmf(channel)) {
01525                                 switch_dtmf_t dtmf = { 0 };
01526                                 switch_channel_dequeue_dtmf(channel, &dtmf);
01527                                 db[0] = dtmf.digit;
01528                                 fcommand = db;
01529                         }
01530 
01531                         if (fcommand) {
01532                                 char *d;
01533                                 for (d = fcommand; *d; d++) {
01534                                         int z = 1;
01535 
01536                                         switch (*d) {
01537                                         case '1':
01538                                                 switch_set_flag(ep, ED_MUX_READ);
01539                                                 switch_clear_flag(ep, ED_MUX_WRITE);
01540                                                 break;
01541                                         case '2':
01542                                                 switch_set_flag(ep, ED_MUX_WRITE);
01543                                                 switch_clear_flag(ep, ED_MUX_READ);
01544                                                 break;
01545                                         case '3':
01546                                                 switch_set_flag(ep, ED_MUX_READ);
01547                                                 switch_set_flag(ep, ED_MUX_WRITE);
01548                                                 break;
01549                                         case '0':
01550                                                 switch_clear_flag(ep, ED_MUX_READ);
01551                                                 switch_clear_flag(ep, ED_MUX_WRITE);
01552                                                 break;
01553                                         case '*':
01554                                                 goto end_loop;
01555                                         default:
01556                                                 z = 0;
01557                                                 break;
01558 
01559                                         }
01560 
01561                                         if (z) {
01562                                                 if (ep->r_buffer) {
01563                                                         switch_buffer_lock(ep->r_buffer);
01564                                                         switch_buffer_zero(ep->r_buffer);
01565                                                         switch_buffer_unlock(ep->r_buffer);
01566                                                 }
01567 
01568                                                 if (ep->w_buffer) {
01569                                                         switch_buffer_lock(ep->w_buffer);
01570                                                         switch_buffer_zero(ep->w_buffer);
01571                                                         switch_buffer_unlock(ep->w_buffer);
01572                                                 }
01573                                         }
01574                                 }
01575                         }
01576 
01577                         if (!switch_test_flag(read_frame, SFF_CNG)) {
01578                                 switch_buffer_lock(ep->r_buffer);
01579                                 switch_buffer_zwrite(ep->r_buffer, read_frame->data, read_frame->datalen);
01580                                 switch_buffer_unlock(ep->r_buffer);
01581 
01582                                 switch_buffer_lock(ep->w_buffer);
01583                                 switch_buffer_zwrite(ep->w_buffer, read_frame->data, read_frame->datalen);
01584                                 switch_buffer_unlock(ep->w_buffer);
01585                         }
01586 
01587                         if (len > tlen) {
01588                                 len = tlen;
01589                         }
01590 
01591                         if (switch_buffer_inuse(ep->buffer) >= len) {
01592                                 switch_buffer_lock(ep->buffer);
01593                                 while (switch_buffer_inuse(ep->buffer) >= len) {
01594                                         write_frame.datalen = (uint32_t) switch_buffer_read(ep->buffer, buf, len);
01595                                         write_frame.samples = write_frame.datalen / 2;
01596 
01597                                         if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
01598                                                 break;
01599                                         }
01600                                 }
01601                                 switch_buffer_unlock(ep->buffer);
01602                         }
01603 
01604                 }
01605 
01606           end_loop:
01607 
01608                 /* Tell the channel we are no longer going to be in a bridge */
01609                 msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
01610                 switch_core_session_receive_message(session, &msg);
01611 
01612 
01613 
01614           end:
01615 
01616                 if (codec_initialized)
01617                         switch_core_codec_destroy(&codec);
01618 
01619                 if (bug) {
01620                         switch_core_media_bug_remove(tsession, &bug);
01621                 }
01622 
01623                 if (ep) {
01624                         if (ep->buffer) {
01625                                 switch_buffer_destroy(&ep->buffer);
01626                         }
01627 
01628                         if (ep->r_buffer) {
01629                                 switch_buffer_destroy(&ep->r_buffer);
01630                         }
01631 
01632                         if (ep->w_buffer) {
01633                                 switch_buffer_destroy(&ep->w_buffer);
01634                         }
01635                 }
01636 
01637                 switch_core_session_rwunlock(tsession);
01638                 status = SWITCH_STATUS_SUCCESS;
01639 
01640                 switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
01641         }
01642 
01643         return status;
01644 }

switch_status_t switch_ivr_eavesdrop_update_display ( switch_core_session_t session,
const char *  name,
const char *  number 
)

Definition at line 1314 of file switch_ivr_async.c.

References display_exec_cb(), switch_channel_clear_app_flag_key(), switch_channel_set_app_flag_key(), switch_channel_test_app_flag_key(), switch_core_media_bug_exec_all(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_strdup, and SWITCH_STATUS_FALSE.

01315 {
01316         struct exec_cb_data *data = NULL;
01317         switch_channel_t *channel = switch_core_session_get_channel(session);
01318         switch_status_t status = SWITCH_STATUS_FALSE;
01319 
01320         data = switch_core_session_alloc(session, sizeof(*data));
01321         data->var = switch_core_session_strdup(session, name);
01322         data->val = switch_core_session_strdup(session, number);
01323         data->caller = session;
01324 
01325         if (!switch_channel_test_app_flag_key("EAVESDROP", channel, 1)) {
01326                 switch_channel_set_app_flag_key("EAVESDROP", channel, 1);
01327                 status = switch_core_media_bug_exec_all(session, "eavesdrop", display_exec_cb, data);
01328                 switch_channel_clear_app_flag_key("EAVESDROP", channel, 1);
01329         }
01330 
01331         return status;
01332 }

switch_status_t switch_ivr_enterprise_originate ( switch_core_session_t session,
switch_core_session_t **  bleg,
switch_call_cause_t cause,
const char *  bridgeto,
uint32_t  timelimit_sec,
const switch_state_handler_table_t table,
const char *  cid_name_override,
const char *  cid_num_override,
switch_caller_profile_t caller_profile_override,
switch_event_t ovars,
switch_originate_flag_t  flags,
switch_call_cause_t cancel_cause 
)

Definition at line 1375 of file switch_ivr_originate.c.

References enterprise_originate_handle_t::bleg, enterprise_originate_handle_t::cause, CF_ANSWERED, CF_NOT_READY, CF_PROXY_MEDIA, CF_PROXY_MODE, enterprise_originate_handle_t::done, enterprise_originate_ringback_thread(), enterprise_originate_thread(), MAX_PEERS, mutex, enterprise_originate_handle_t::mutex, switch_event_header::name, switch_event_header::next, enterprise_originate_handle_t::ovars, pool, ent_originate_ringback::ringback_data, running, ent_originate_ringback::running, ent_originate_ringback::session, enterprise_originate_handle_t::status, switch_caller_profile_dup(), SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, SWITCH_CAUSE_LOSE_RACE, switch_channel_clear_flag(), switch_channel_get_caller_profile(), switch_channel_get_variable, switch_channel_media_ready, switch_channel_pre_answer, switch_channel_process_export(), switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_test_flag(), switch_core_destroy_memory_pool, switch_core_new_memory_pool, switch_core_session_get_channel(), switch_core_session_get_uuid(), switch_core_strdup, SWITCH_ENT_ORIGINATE_DELIM, switch_event_add_header_string(), SWITCH_EVENT_CHANNEL_DATA, switch_event_create_brackets(), switch_event_create_plain(), switch_event_destroy(), switch_event_dup(), SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE, switch_goto_status, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), switch_mutex_init(), switch_mutex_lock(), SWITCH_MUTEX_NESTED, switch_mutex_unlock(), switch_separate_string_string(), SWITCH_STACK_BOTTOM, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, switch_thread_create(), switch_thread_join(), SWITCH_THREAD_STACKSIZE, switch_threadattr_create(), switch_threadattr_stacksize_set(), switch_yield, thread, ent_originate_ringback::thread, enterprise_originate_handle_t::thread, switch_event_header::value, and zstr.

Referenced by switch_ivr_originate().

01386 {
01387         int x_argc = 0;
01388         char *x_argv[MAX_PEERS] = { 0 };
01389         enterprise_originate_handle_t *hp = NULL, handles[MAX_PEERS] = { {0} };
01390         int i;
01391         switch_caller_profile_t *cp = NULL;
01392         switch_channel_t *channel = NULL;
01393         char *data;
01394         switch_status_t status = SWITCH_STATUS_FALSE;
01395         switch_threadattr_t *thd_attr = NULL;
01396         int running = 0, over = 0;
01397         switch_status_t tstatus = SWITCH_STATUS_FALSE;
01398         switch_memory_pool_t *pool;
01399         switch_event_header_t *hi = NULL;
01400         struct ent_originate_ringback rb_data = { 0 };
01401         const char *ringback_data = NULL;
01402         switch_event_t *var_event = NULL;
01403 
01404         switch_core_new_memory_pool(&pool);
01405 
01406         if (zstr(bridgeto)) {
01407                 *cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
01408                 switch_goto_status(SWITCH_STATUS_FALSE, end);
01409         }
01410 
01411         data = switch_core_strdup(pool, bridgeto);
01412 
01413         if (session) {
01414                 switch_caller_profile_t *cpp = NULL;
01415                 channel = switch_core_session_get_channel(session);
01416                 if ((cpp = switch_channel_get_caller_profile(channel))) {
01417                         cp = switch_caller_profile_dup(pool, cpp);
01418                 }
01419         }
01420 
01421         if (ovars) {
01422                 var_event = ovars;
01423         } else {
01424                 if (switch_event_create_plain(&var_event, SWITCH_EVENT_CHANNEL_DATA) != SWITCH_STATUS_SUCCESS) {
01425                         abort();
01426                 }
01427         }
01428 
01429         if (session) {
01430                 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ent_originate_aleg_uuid", switch_core_session_get_uuid(session));
01431         }
01432         
01433         if (channel) {
01434                 const char *cid;
01435 
01436                 switch_channel_process_export(channel, NULL, var_event, SWITCH_EXPORT_VARS_VARIABLE);
01437 
01438                 if ((cid = switch_channel_get_variable(channel, "effective_caller_id_name"))) {
01439                         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_name", cid);
01440                 }
01441 
01442                 if ((cid = switch_channel_get_variable(channel, "effective_caller_id_number"))) {
01443                         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_number", cid);
01444                 }
01445         }
01446 
01447         /* strip leading spaces */
01448         while (data && *data && *data == ' ') {
01449                 data++;
01450         }
01451 
01452         /* extract channel variables, allowing multiple sets of braces */
01453         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing ultra-global variables\n");
01454         while (*data == '<') {
01455                 char *parsed = NULL;
01456 
01457                 if (switch_event_create_brackets(data, '<', '>', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
01458                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
01459                         switch_goto_status(SWITCH_STATUS_GENERR, done);
01460                 }
01461 
01462                 data = parsed;
01463         }
01464 
01465         /* strip leading spaces (again) */
01466         while (data && *data && *data == ' ') {
01467                 data++;
01468         }
01469 
01470         if (ovars && ovars != var_event) {
01471                 for (hi = ovars->headers; hi; hi = hi->next) {
01472                         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, hi->name, hi->value);
01473                 }
01474         }
01475 
01476         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
01477 
01478         if (!(x_argc = switch_separate_string_string(data, SWITCH_ENT_ORIGINATE_DELIM, x_argv, MAX_PEERS))) {
01479                 *cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
01480                 switch_goto_status(SWITCH_STATUS_FALSE, end);
01481         }
01482 
01483         switch_threadattr_create(&thd_attr, pool);
01484         switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
01485 
01486         for (i = 0; i < x_argc; i++) {
01487                 handles[i].session = session;
01488                 handles[i].bleg = NULL;
01489                 handles[i].cause = 0;
01490                 handles[i].cancel_cause = 0;
01491                 handles[i].bridgeto = x_argv[i];
01492                 handles[i].timelimit_sec = timelimit_sec;
01493                 handles[i].table = table;
01494                 handles[i].cid_name_override = cid_name_override;
01495                 handles[i].cid_num_override = cid_num_override;
01496                 handles[i].caller_profile_override = cp;
01497                 switch_event_dup(&handles[i].ovars, var_event);
01498                 handles[i].flags = flags;
01499                 switch_mutex_init(&handles[i].mutex, SWITCH_MUTEX_NESTED, pool);
01500                 switch_mutex_lock(handles[i].mutex);
01501                 switch_thread_create(&handles[i].thread, thd_attr, enterprise_originate_thread, &handles[i], pool);
01502         }
01503 
01504         if (channel && !switch_channel_test_flag(channel, CF_PROXY_MODE) && !switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
01505                 if (switch_channel_test_flag(channel, CF_ANSWERED)) {
01506                         ringback_data = switch_channel_get_variable(channel, "transfer_ringback");
01507                 }
01508 
01509                 if (!ringback_data) {
01510                         ringback_data = switch_channel_get_variable(channel, "ringback");
01511                 }
01512 
01513                 if (ringback_data || switch_channel_media_ready(channel)) {
01514                         rb_data.ringback_data = ringback_data;
01515                         rb_data.session = session;
01516                         rb_data.running = 1;
01517                         if (!switch_channel_media_ready(channel)) {
01518                                 if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
01519                                         goto done;
01520                                 }
01521                         }
01522                         switch_thread_create(&rb_data.thread, thd_attr, enterprise_originate_ringback_thread, &rb_data, pool);
01523                 }
01524         }
01525 
01526 
01527         for (;;) {
01528                 running = 0;
01529                 over = 0;
01530 
01531                 if (channel && !switch_channel_ready(channel)) {
01532                         break;
01533                 }
01534 
01535                 if (cancel_cause && *cancel_cause > 0) {
01536                         break;
01537                 }
01538 
01539                 for (i = 0; i < x_argc; i++) {
01540 
01541 
01542                         if (handles[i].done == 0) {
01543                                 running++;
01544                         } else if (handles[i].done == 1) {
01545                                 if (handles[i].status == SWITCH_STATUS_SUCCESS) {
01546                                         handles[i].done = 2;
01547                                         hp = &handles[i];
01548                                         goto done;
01549                                 } else {
01550                                         handles[i].done = -1;
01551                                 }
01552                         } else {
01553                                 over++;
01554                         }
01555 
01556                         switch_yield(10000);
01557                 }
01558 
01559                 if (!running || over == x_argc) {
01560                         break;
01561                 }
01562         }
01563 
01564 
01565   done:
01566 
01567         if (hp) {
01568                 *cause = hp->cause;
01569                 status = hp->status;
01570                 *bleg = hp->bleg;
01571                 switch_mutex_unlock(hp->mutex);
01572                 switch_thread_join(&tstatus, hp->thread);
01573                 switch_event_destroy(&hp->ovars);
01574         }
01575 
01576         for (i = 0; i < x_argc; i++) {
01577                 if (hp == &handles[i]) {
01578                         continue;
01579                 }
01580 
01581                 if (cancel_cause && *cancel_cause > 0) {
01582                         handles[i].cancel_cause = *cancel_cause;
01583                 } else {
01584                         handles[i].cancel_cause = SWITCH_CAUSE_LOSE_RACE;
01585                 }
01586         }
01587 
01588         for (i = 0; i < x_argc; i++) {
01589                 if (hp == &handles[i]) {
01590                         continue;
01591                 }
01592                 switch_mutex_unlock(handles[i].mutex);
01593                 switch_thread_join(&tstatus, handles[i].thread);
01594                 switch_event_destroy(&handles[i].ovars);
01595         }
01596 
01597 
01598         if (channel && rb_data.thread) {
01599                 switch_channel_set_flag(channel, CF_NOT_READY);
01600                 switch_thread_join(&tstatus, rb_data.thread);
01601                 switch_channel_clear_flag(channel, CF_NOT_READY);
01602         }
01603 
01604 
01605   end:
01606 
01607         if (var_event && var_event != ovars) {
01608                 switch_event_destroy(&var_event);
01609         }
01610 
01611         switch_core_destroy_memory_pool(&pool);
01612 
01613         return status;
01614 
01615 }

switch_status_t switch_ivr_generate_json_cdr ( switch_core_session_t session,
cJSON **  json_cdr,
switch_bool_t  urlencode 
)

Generate an JSON CDR report.

Parameters:
session the session to get the data from.
json_cdr pointer to the json object
Returns:
SWITCH_STATUS_SUCCESS if successful
Note:
on success the json object must be freed

Definition at line 2523 of file switch_ivr.c.

References switch_channel_timetable::answered, switch_app_log::app, switch_caller_application::application_data, switch_caller_application::application_name, switch_caller_extension::applications, switch_app_log::arg, switch_caller_profile::caller_extension, switch_caller_extension::children, cJSON_AddItemToObject(), cJSON_CreateObject(), cJSON_CreateString(), switch_channel_timetable::created, switch_caller_extension::current_application, switch_caller_profile::dialplan, switch_caller_extension::extension_name, switch_caller_extension::extension_number, switch_channel_timetable::hungup, switch_app_log::next, switch_caller_application::next, switch_caller_profile::next, switch_caller_profile::originatee_caller_profile, switch_caller_profile::originator_caller_profile, switch_channel_timetable::profile_created, switch_caller_profile::profile_index, switch_channel_timetable::progress, switch_channel_timetable::progress_media, switch_channel_timetable::resurrected, SWITCH_CALL_DIRECTION_OUTBOUND, switch_channel_direction(), switch_channel_get_caller_profile(), switch_channel_get_cap_string(), switch_channel_get_flag_string(), switch_channel_get_state(), switch_channel_state_name(), switch_core_session_get_app_log(), switch_core_session_get_channel(), switch_ivr_set_json_chan_vars(), switch_ivr_set_json_profile_data(), switch_snprintf(), SWITCH_STATUS_SUCCESS, switch_str_nil, SWITCH_TIME_T_FMT, switch_caller_profile::times, switch_channel_timetable::transferred, and zstr.

Referenced by switch_ivr_multi_threaded_bridge().

02524 {
02525         cJSON *cdr = cJSON_CreateObject();
02526         switch_channel_t *channel = switch_core_session_get_channel(session);
02527         switch_caller_profile_t *caller_profile;
02528         cJSON *variables, *j_main_cp, *j_caller_profile, *j_caller_extension, *j_times,
02529                 *j_application, *j_callflow, *j_inner_extension, *j_apps, *j_o, *j_channel_data;
02530         switch_app_log_t *app_log;
02531         char tmp[512], *f;
02532         
02533         j_channel_data = cJSON_CreateObject();
02534 
02535         cJSON_AddItemToObject(cdr, "channel_data", j_channel_data);
02536 
02537         cJSON_AddItemToObject(j_channel_data, "state", cJSON_CreateString((char *) switch_channel_state_name(switch_channel_get_state(channel))));
02538         cJSON_AddItemToObject(j_channel_data, "direction", cJSON_CreateString(switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"));
02539 
02540         switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel));
02541         cJSON_AddItemToObject(j_channel_data, "state_number", cJSON_CreateString((char *) tmp));
02542         
02543         if ((f = switch_channel_get_flag_string(channel))) {
02544                 cJSON_AddItemToObject(j_channel_data, "flags", cJSON_CreateString((char *) f));
02545                 free(f);
02546         }
02547 
02548         if ((f = switch_channel_get_cap_string(channel))) {
02549                 cJSON_AddItemToObject(j_channel_data, "caps", cJSON_CreateString((char *) f));
02550                 free(f);
02551         }
02552 
02553         variables = cJSON_CreateObject();
02554         cJSON_AddItemToObject(cdr, "variables", variables);
02555 
02556         switch_ivr_set_json_chan_vars(variables, channel, urlencode);
02557 
02558 
02559         if ((app_log = switch_core_session_get_app_log(session))) {
02560                 switch_app_log_t *ap;
02561 
02562                 j_apps = cJSON_CreateObject();
02563 
02564                 cJSON_AddItemToObject(cdr, "app_log", j_apps);
02565 
02566                 for (ap = app_log; ap; ap = ap->next) {
02567                         j_application = cJSON_CreateObject();
02568 
02569                         cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->app));
02570                         cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(ap->arg));
02571 
02572                         cJSON_AddItemToObject(j_apps, "application", j_application);
02573                 }
02574         }
02575 
02576 
02577         caller_profile = switch_channel_get_caller_profile(channel);
02578 
02579         while (caller_profile) {
02580 
02581                 j_callflow = cJSON_CreateObject();
02582 
02583                 cJSON_AddItemToObject(cdr, "callflow", j_callflow);
02584 
02585                 if (!zstr(caller_profile->dialplan)) {
02586                         cJSON_AddItemToObject(j_callflow, "dialplan", cJSON_CreateString((char *)caller_profile->dialplan));
02587                 }
02588 
02589                 if (!zstr(caller_profile->profile_index)) {
02590                         cJSON_AddItemToObject(j_callflow, "profile_index", cJSON_CreateString((char *)caller_profile->profile_index));
02591                 }
02592 
02593                 if (caller_profile->caller_extension) {
02594                         switch_caller_application_t *ap;
02595 
02596                         j_caller_extension = cJSON_CreateObject();
02597 
02598                         cJSON_AddItemToObject(j_callflow, "extension", j_caller_extension);
02599 
02600                         cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(caller_profile->caller_extension->extension_name));
02601                         cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(caller_profile->caller_extension->extension_number));
02602 
02603                         if (caller_profile->caller_extension->current_application) {
02604                                 cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(caller_profile->caller_extension->current_application->application_name));
02605                         }
02606 
02607                         for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
02608                                 j_application = cJSON_CreateObject();
02609 
02610                                 cJSON_AddItemToObject(j_caller_extension, "application", j_application);
02611 
02612                                 if (ap == caller_profile->caller_extension->current_application) {
02613                                         cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true"));
02614                                 }
02615                                 cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name));
02616                                 cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)));
02617                         }
02618 
02619                         if (caller_profile->caller_extension->children) {
02620                                 switch_caller_profile_t *cp = NULL;
02621                                 for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {
02622 
02623                                         if (!cp->caller_extension) {
02624                                                 continue;
02625                                         }
02626 
02627                                         j_inner_extension = cJSON_CreateObject();
02628                                         cJSON_AddItemToObject(j_caller_extension, "sub_extensions", j_inner_extension);
02629 
02630                                         j_caller_extension = cJSON_CreateObject();
02631                                         cJSON_AddItemToObject(j_inner_extension, "extension", j_caller_extension);
02632 
02633                                         cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(cp->caller_extension->extension_name));
02634                                         cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(cp->caller_extension->extension_number));
02635 
02636                                         cJSON_AddItemToObject(j_caller_extension, "dialplan", cJSON_CreateString((char *)cp->dialplan));
02637 
02638                                         if (cp->caller_extension->current_application) {
02639                                                 cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(cp->caller_extension->current_application->application_name));
02640                                         }
02641 
02642                                         for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
02643                                                 j_application = cJSON_CreateObject();
02644                                                 cJSON_AddItemToObject(j_caller_extension, "application", j_application);
02645 
02646                                                 if (ap == cp->caller_extension->current_application) {
02647                                                         cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true"));
02648                                                 }
02649                                                 cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name));
02650                                                 cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)));
02651                                         }
02652                                 }
02653                         }
02654                 }
02655 
02656                 j_main_cp = cJSON_CreateObject();
02657                 cJSON_AddItemToObject(j_callflow, "caller_profile", j_main_cp);
02658 
02659                 switch_ivr_set_json_profile_data(j_main_cp, caller_profile);
02660 
02661                 if (caller_profile->originator_caller_profile) {
02662                         switch_caller_profile_t *cp = NULL;
02663 
02664                         j_o = cJSON_CreateObject();
02665                         cJSON_AddItemToObject(j_main_cp, "originator", j_o);
02666 
02667                         for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
02668                                 j_caller_profile = cJSON_CreateObject();
02669                                 cJSON_AddItemToObject(j_o, "originator_caller_profile", j_caller_profile);
02670 
02671                                 switch_ivr_set_json_profile_data(j_caller_profile, cp);
02672                         }
02673                 }
02674 
02675                 if (caller_profile->originatee_caller_profile) {
02676                         switch_caller_profile_t *cp = NULL;
02677 
02678                         j_o = cJSON_CreateObject();
02679                         cJSON_AddItemToObject(j_main_cp, "originatee", j_o);
02680 
02681                         for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {
02682                                 j_caller_profile = cJSON_CreateObject();
02683                                 cJSON_AddItemToObject(j_o, "originatee_caller_profile", j_caller_profile);
02684                                 switch_ivr_set_json_profile_data(j_caller_profile, cp);
02685                         }
02686                 }
02687 
02688                 if (caller_profile->times) {
02689 
02690                         j_times = cJSON_CreateObject();
02691                         cJSON_AddItemToObject(j_callflow, "times", j_times);
02692 
02693                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
02694                         cJSON_AddItemToObject(j_times, "created_time", cJSON_CreateString(tmp));
02695 
02696                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
02697                         cJSON_AddItemToObject(j_times, "profile_created_time", cJSON_CreateString(tmp));
02698 
02699                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
02700                         cJSON_AddItemToObject(j_times, "progress_time", cJSON_CreateString(tmp));
02701 
02702                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
02703                         cJSON_AddItemToObject(j_times, "progress_media_time", cJSON_CreateString(tmp));
02704 
02705                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
02706                         cJSON_AddItemToObject(j_times, "answered_time", cJSON_CreateString(tmp));
02707 
02708                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
02709                         cJSON_AddItemToObject(j_times, "hangup_time", cJSON_CreateString(tmp));
02710 
02711                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
02712                         cJSON_AddItemToObject(j_times, "resurrect_time", cJSON_CreateString(tmp));
02713 
02714                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->transferred);
02715                         cJSON_AddItemToObject(j_times, "transfer_time", cJSON_CreateString(tmp));
02716 
02717                 }
02718 
02719                 caller_profile = caller_profile->next;
02720         }
02721 
02722         *json_cdr = cdr;
02723 
02724         return SWITCH_STATUS_SUCCESS;
02725         
02726 }

switch_status_t switch_ivr_generate_xml_cdr ( switch_core_session_t session,
switch_xml_t xml_cdr 
)

Generate an XML CDR report.

Parameters:
session the session to get the data from.
xml_cdr pointer to the xml_record
Returns:
SWITCH_STATUS_SUCCESS if successful
Note:
on success the xml object must be freed

Definition at line 2174 of file switch_ivr.c.

References switch_channel_timetable::answered, switch_app_log::app, switch_caller_application::application_data, switch_caller_application::application_name, switch_caller_extension::applications, switch_app_log::arg, switch_channel_timetable::bridged, switch_caller_profile::caller_extension, switch_caller_extension::children, switch_caller_profile::clone_of, switch_channel_timetable::created, switch_caller_extension::current_application, switch_caller_profile::dialplan, switch_caller_extension::extension_name, switch_caller_extension::extension_number, switch_channel_timetable::hold_accum, switch_channel_timetable::hungup, switch_channel_timetable::last_hold, switch_app_log::next, switch_caller_application::next, switch_caller_profile::next, switch_caller_profile::originatee_caller_profile, switch_caller_profile::origination_caller_profile, switch_caller_profile::originator_caller_profile, switch_channel_timetable::profile_created, switch_caller_profile::profile_index, switch_channel_timetable::progress, switch_channel_timetable::progress_media, switch_channel_timetable::resurrected, switch_app_log::stamp, SWITCH_CALL_DIRECTION_OUTBOUND, switch_channel_direction(), switch_channel_get_caller_profile(), switch_channel_get_cap_string(), switch_channel_get_flag_string(), switch_channel_get_state(), switch_channel_state_name(), switch_core_session_get_app_log(), switch_core_session_get_channel(), switch_ivr_set_xml_chan_vars(), switch_ivr_set_xml_profile_data(), switch_snprintf(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, SWITCH_TIME_T_FMT, switch_xml_add_child_d, switch_xml_free(), switch_xml_new(), switch_xml_set_attr_d, switch_xml_set_attr_d_buf, switch_xml_set_txt_d, switch_caller_profile::times, switch_channel_timetable::transferred, switch_caller_profile::uuid_str, and zstr.

Referenced by CoreSession::getXMLCDR(), switch_core_session_reporting_state(), and switch_ivr_multi_threaded_bridge().

02175 {
02176         switch_channel_t *channel = switch_core_session_get_channel(session);
02177         switch_caller_profile_t *caller_profile;
02178         switch_xml_t variables, cdr, x_main_cp, x_caller_profile, x_caller_extension, x_times, time_tag,
02179                 x_application, x_callflow, x_inner_extension, x_apps, x_o, x_channel_data, x_field;
02180         switch_app_log_t *app_log;
02181         char tmp[512], *f;
02182         int cdr_off = 0, v_off = 0, cd_off = 0;
02183 
02184         if (*xml_cdr) {
02185                 cdr = *xml_cdr;
02186         } else {
02187                 if (!(cdr = switch_xml_new("cdr"))) {
02188                         return SWITCH_STATUS_SUCCESS;
02189                 }
02190         }
02191 
02192         if (!(x_channel_data = switch_xml_add_child_d(cdr, "channel_data", cdr_off++))) {
02193                 goto error;
02194         }
02195 
02196         x_field = switch_xml_add_child_d(x_channel_data, "state", cd_off++);
02197         switch_xml_set_txt_d(x_field, switch_channel_state_name(switch_channel_get_state(channel)));
02198 
02199         x_field = switch_xml_add_child_d(x_channel_data, "direction", cd_off++);
02200         switch_xml_set_txt_d(x_field, switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
02201 
02202         x_field = switch_xml_add_child_d(x_channel_data, "state_number", cd_off++);
02203         switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel));
02204         switch_xml_set_txt_d(x_field, tmp);
02205 
02206         if ((f = switch_channel_get_flag_string(channel))) {
02207                 x_field = switch_xml_add_child_d(x_channel_data, "flags", cd_off++);
02208                 switch_xml_set_txt_d(x_field, f);
02209                 free(f);
02210         }
02211 
02212         if ((f = switch_channel_get_cap_string(channel))) {
02213                 x_field = switch_xml_add_child_d(x_channel_data, "caps", cd_off++);
02214                 switch_xml_set_txt_d(x_field, f);
02215                 free(f);
02216         }
02217 
02218 
02219         if (!(variables = switch_xml_add_child_d(cdr, "variables", cdr_off++))) {
02220                 goto error;
02221         }
02222 
02223         switch_ivr_set_xml_chan_vars(variables, channel, v_off);
02224 
02225 
02226         if ((app_log = switch_core_session_get_app_log(session))) {
02227                 int app_off = 0;
02228                 switch_app_log_t *ap;
02229 
02230                 if (!(x_apps = switch_xml_add_child_d(cdr, "app_log", cdr_off++))) {
02231                         goto error;
02232                 }
02233                 for (ap = app_log; ap; ap = ap->next) {
02234                         char tmp[128];
02235 
02236                         if (!(x_application = switch_xml_add_child_d(x_apps, "application", app_off++))) {
02237                                 goto error;
02238                         }
02239 
02240                         switch_xml_set_attr_d(x_application, "app_name", ap->app);
02241                         switch_xml_set_attr_d(x_application, "app_data", ap->arg);
02242 
02243                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, ap->stamp);
02244                         switch_xml_set_attr_d_buf(x_application, "app_stamp", tmp);
02245                 }
02246         }
02247 
02248 
02249         caller_profile = switch_channel_get_caller_profile(channel);
02250 
02251         while (caller_profile) {
02252                 int cf_off = 0;
02253                 int cp_off = 0;
02254 
02255                 if (!(x_callflow = switch_xml_add_child_d(cdr, "callflow", cdr_off++))) {
02256                         goto error;
02257                 }
02258 
02259                 if (!zstr(caller_profile->dialplan)) {
02260                         switch_xml_set_attr_d(x_callflow, "dialplan", caller_profile->dialplan);
02261                 }
02262 
02263                 if (!zstr(caller_profile->uuid_str)) {
02264                         switch_xml_set_attr_d(x_callflow, "unique-id", caller_profile->uuid_str);
02265                 }
02266 
02267                 if (!zstr(caller_profile->clone_of)) {
02268                         switch_xml_set_attr_d(x_callflow, "clone-of", caller_profile->clone_of);
02269                 }
02270 
02271                 if (!zstr(caller_profile->profile_index)) {
02272                         switch_xml_set_attr_d(x_callflow, "profile_index", caller_profile->profile_index);
02273                 }
02274 
02275                 if (caller_profile->caller_extension) {
02276                         switch_caller_application_t *ap;
02277                         int app_off = 0;
02278 
02279                         if (!(x_caller_extension = switch_xml_add_child_d(x_callflow, "extension", cf_off++))) {
02280                                 goto error;
02281                         }
02282 
02283                         switch_xml_set_attr_d(x_caller_extension, "name", caller_profile->caller_extension->extension_name);
02284                         switch_xml_set_attr_d(x_caller_extension, "number", caller_profile->caller_extension->extension_number);
02285                         if (caller_profile->caller_extension->current_application) {
02286                                 switch_xml_set_attr_d(x_caller_extension, "current_app", caller_profile->caller_extension->current_application->application_name);
02287                         }
02288 
02289                         for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
02290                                 if (!(x_application = switch_xml_add_child_d(x_caller_extension, "application", app_off++))) {
02291                                         goto error;
02292                                 }
02293                                 if (ap == caller_profile->caller_extension->current_application) {
02294                                         switch_xml_set_attr_d(x_application, "last_executed", "true");
02295                                 }
02296                                 switch_xml_set_attr_d(x_application, "app_name", ap->application_name);
02297                                 switch_xml_set_attr_d(x_application, "app_data", ap->application_data);
02298                         }
02299 
02300                         if (caller_profile->caller_extension->children) {
02301                                 switch_caller_profile_t *cp = NULL;
02302                                 int i_off = 0, i_app_off = 0;
02303                                 for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {
02304 
02305                                         if (!cp->caller_extension) {
02306                                                 continue;
02307                                         }
02308                                         if (!(x_inner_extension = switch_xml_add_child_d(x_caller_extension, "sub_extensions", app_off++))) {
02309                                                 goto error;
02310                                         }
02311 
02312                                         if (!(x_caller_extension = switch_xml_add_child_d(x_inner_extension, "extension", i_off++))) {
02313                                                 goto error;
02314                                         }
02315                                         switch_xml_set_attr_d(x_caller_extension, "name", cp->caller_extension->extension_name);
02316                                         switch_xml_set_attr_d(x_caller_extension, "number", cp->caller_extension->extension_number);
02317                                         switch_xml_set_attr_d(x_caller_extension, "dialplan", cp->dialplan);
02318                                         if (cp->caller_extension->current_application) {
02319                                                 switch_xml_set_attr_d(x_caller_extension, "current_app", cp->caller_extension->current_application->application_name);
02320                                         }
02321 
02322                                         for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
02323                                                 if (!(x_application = switch_xml_add_child_d(x_caller_extension, "application", i_app_off++))) {
02324                                                         goto error;
02325                                                 }
02326                                                 if (ap == cp->caller_extension->current_application) {
02327                                                         switch_xml_set_attr_d(x_application, "last_executed", "true");
02328                                                 }
02329                                                 switch_xml_set_attr_d(x_application, "app_name", ap->application_name);
02330                                                 switch_xml_set_attr_d(x_application, "app_data", ap->application_data);
02331                                         }
02332                                 }
02333                         }
02334                 }
02335 
02336                 if (!(x_main_cp = switch_xml_add_child_d(x_callflow, "caller_profile", cf_off++))) {
02337                         goto error;
02338                 }
02339 
02340                 cp_off += switch_ivr_set_xml_profile_data(x_main_cp, caller_profile, 0);
02341 
02342                 if (caller_profile->origination_caller_profile) {
02343                         switch_caller_profile_t *cp = NULL;
02344                         int off = 0;
02345                         if (!(x_o = switch_xml_add_child_d(x_main_cp, "origination", cp_off++))) {
02346                                 goto error;
02347                         }
02348 
02349                         for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) {
02350                                 if (!(x_caller_profile = switch_xml_add_child_d(x_o, "origination_caller_profile", off++))) {
02351                                         goto error;
02352                                 }
02353                                 switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
02354                         }
02355                 }
02356 
02357                 if (caller_profile->originator_caller_profile) {
02358                         switch_caller_profile_t *cp = NULL;
02359                         int off = 0;
02360                         if (!(x_o = switch_xml_add_child_d(x_main_cp, "originator", cp_off++))) {
02361                                 goto error;
02362                         }
02363 
02364                         for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
02365                                 if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originator_caller_profile", off++))) {
02366                                         goto error;
02367                                 }
02368                                 switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
02369                         }
02370                 }
02371 
02372                 if (caller_profile->originatee_caller_profile) {
02373                         switch_caller_profile_t *cp = NULL;
02374                         int off = 0;
02375                         if (!(x_o = switch_xml_add_child_d(x_main_cp, "originatee", cp_off++))) {
02376                                 goto error;
02377                         }
02378                         for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {
02379                                 if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originatee_caller_profile", off++))) {
02380                                         goto error;
02381                                 }
02382                                 switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
02383                         }
02384                 }
02385 
02386                 if (caller_profile->times) {
02387                         int t_off = 0;
02388                         if (!(x_times = switch_xml_add_child_d(x_callflow, "times", cf_off++))) {
02389                                 goto error;
02390                         }
02391                         if (!(time_tag = switch_xml_add_child_d(x_times, "created_time", t_off++))) {
02392                                 goto error;
02393                         }
02394                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
02395                         switch_xml_set_txt_d(time_tag, tmp);
02396 
02397                         if (!(time_tag = switch_xml_add_child_d(x_times, "profile_created_time", t_off++))) {
02398                                 goto error;
02399                         }
02400                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
02401                         switch_xml_set_txt_d(time_tag, tmp);
02402 
02403                         if (!(time_tag = switch_xml_add_child_d(x_times, "progress_time", t_off++))) {
02404                                 goto error;
02405                         }
02406                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
02407                         switch_xml_set_txt_d(time_tag, tmp);
02408 
02409 
02410                         if (!(time_tag = switch_xml_add_child_d(x_times, "progress_media_time", t_off++))) {
02411                                 goto error;
02412                         }
02413                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
02414                         switch_xml_set_txt_d(time_tag, tmp);
02415 
02416                         if (!(time_tag = switch_xml_add_child_d(x_times, "answered_time", t_off++))) {
02417                                 goto error;
02418                         }
02419                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
02420                         switch_xml_set_txt_d(time_tag, tmp);
02421 
02422                         if (!(time_tag = switch_xml_add_child_d(x_times, "bridged_time", t_off++))) {
02423                                 goto error;
02424                         }
02425                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
02426                         switch_xml_set_txt_d(time_tag, tmp);
02427 
02428                         if (!(time_tag = switch_xml_add_child_d(x_times, "last_hold_time", t_off++))) {
02429                                 goto error;
02430                         }
02431                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->last_hold);
02432                         switch_xml_set_txt_d(time_tag, tmp);
02433                         
02434                         if (!(time_tag = switch_xml_add_child_d(x_times, "hold_accum_time", t_off++))) {
02435                                 goto error;
02436                         }
02437                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum);
02438                         switch_xml_set_txt_d(time_tag, tmp);
02439 
02440                         if (!(time_tag = switch_xml_add_child_d(x_times, "hangup_time", t_off++))) {
02441                                 goto error;
02442                         }
02443                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
02444                         switch_xml_set_txt_d(time_tag, tmp);
02445 
02446                         if (!(time_tag = switch_xml_add_child_d(x_times, "resurrect_time", t_off++))) {
02447                                 goto error;
02448                         }
02449                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
02450                         switch_xml_set_txt_d(time_tag, tmp);
02451 
02452                         if (!(time_tag = switch_xml_add_child_d(x_times, "transfer_time", t_off++))) {
02453                                 goto error;
02454                         }
02455                         switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->transferred);
02456                         switch_xml_set_txt_d(time_tag, tmp);
02457                 }
02458 
02459                 caller_profile = caller_profile->next;
02460         }
02461 
02462         *xml_cdr = cdr;
02463 
02464         return SWITCH_STATUS_SUCCESS;
02465 
02466   error:
02467 
02468         if (cdr) {
02469                 switch_xml_free(cdr);
02470         }
02471 
02472         return SWITCH_STATUS_FALSE;
02473 }

switch_status_t switch_ivr_gentones ( switch_core_session_t session,
const char *  script,
int32_t  loops,
switch_input_args_t args 
)

Definition at line 817 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, switch_frame::buflen, CF_BREAK, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, switch_codec_implementation::microseconds_per_packet, switch_frame::samples, switch_buffer_create_dynamic(), switch_buffer_destroy(), switch_buffer_read_loop(), switch_buffer_set_loops(), switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_has_dtmf(), switch_channel_pre_answer, switch_channel_ready, switch_channel_test_flag(), SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_core_codec_destroy(), switch_core_codec_init, switch_core_session_dequeue_event(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_read_frame(), switch_core_session_write_frame(), switch_event_destroy(), SWITCH_FALSE, SWITCH_INPUT_TYPE_DTMF, SWITCH_INPUT_TYPE_EVENT, SWITCH_IO_FLAG_NONE, switch_ivr_dmachine_feed(), switch_ivr_dmachine_ping(), switch_ivr_parse_all_events(), SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, teletone_destroy_session(), teletone_handler(), teletone_init_session(), and teletone_run().

Referenced by enterprise_originate_ringback_thread().

00818 {
00819         teletone_generation_session_t ts;
00820         switch_dtmf_t dtmf = { 0 };
00821         switch_buffer_t *audio_buffer;
00822         switch_frame_t *read_frame = NULL;
00823         switch_codec_t write_codec = { 0 };
00824         switch_frame_t write_frame = { 0 };
00825         switch_byte_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
00826         switch_channel_t *channel = switch_core_session_get_channel(session);
00827         switch_codec_implementation_t read_impl = { 0 };
00828         switch_core_session_get_read_impl(session, &read_impl);
00829 
00830         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
00831                 return SWITCH_STATUS_FALSE;
00832         }
00833 
00834         if (switch_core_codec_init(&write_codec,
00835                                                            "L16",
00836                                                            NULL,
00837                                                            read_impl.actual_samples_per_second,
00838                                                            read_impl.microseconds_per_packet / 1000,
00839                                                            1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
00840                                                            NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
00841 
00842                 return SWITCH_STATUS_FALSE;
00843         }
00844         memset(&ts, 0, sizeof(ts));
00845         write_frame.codec = &write_codec;
00846         write_frame.data = data;
00847         write_frame.buflen = sizeof(data);
00848 
00849         switch_buffer_create_dynamic(&audio_buffer, 512, 1024, 0);
00850         teletone_init_session(&ts, 0, teletone_handler, audio_buffer);
00851         ts.rate = read_impl.actual_samples_per_second;
00852         ts.channels = 1;
00853         teletone_run(&ts, script);
00854 
00855         if (loops) {
00856                 switch_buffer_set_loops(audio_buffer, loops);
00857         }
00858 
00859         for (;;) {
00860                 switch_status_t status;
00861 
00862                 if (!switch_channel_ready(channel)) {
00863                         status = SWITCH_STATUS_FALSE;
00864                         break;
00865                 }
00866 
00867                 if (switch_channel_test_flag(channel, CF_BREAK)) {
00868                         switch_channel_clear_flag(channel, CF_BREAK);
00869                         status = SWITCH_STATUS_BREAK;
00870                         break;
00871                 }
00872 
00873                 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
00874 
00875                 if (!SWITCH_READ_ACCEPTABLE(status)) {
00876                         break;
00877                 }
00878 
00879                 if (args && args->dmachine) {
00880                         if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
00881                                 break;
00882                         }
00883                 }
00884 
00885                 if (args && (args->read_frame_callback)) {
00886                         if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
00887                                 break;
00888                         }
00889                 }
00890 
00891                 switch_ivr_parse_all_events(session);
00892 
00893                 if (args) {
00894                         /*
00895                            dtmf handler function you can hook up to be executed when a digit is dialed during gentones 
00896                            if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
00897                          */
00898                         if (switch_channel_has_dtmf(channel)) {
00899                                 if (!args->input_callback && !args->buf && !args->dmachine) {
00900                                         status = SWITCH_STATUS_BREAK;
00901                                         break;
00902                                 }
00903                                 switch_channel_dequeue_dtmf(channel, &dtmf);
00904 
00905                                 if (args->dmachine) {
00906                                         char ds[2] = {dtmf.digit, '\0'};
00907                                         if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
00908                                                 break;
00909                                         }
00910                                 } 
00911 
00912                                 if (args->input_callback) {
00913                                         status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
00914                                 } else if (args->buf) {
00915                                         *((char *) args->buf) = dtmf.digit;
00916                                         status = SWITCH_STATUS_BREAK;
00917                                 }
00918                         }
00919 
00920                         if (args->input_callback) {
00921                                 switch_event_t *event;
00922                                 
00923                                 if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
00924                                         status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
00925                                         switch_event_destroy(&event);
00926                                 }
00927                         }
00928 
00929                         if (status != SWITCH_STATUS_SUCCESS) {
00930                                 break;
00931                         }
00932                 }
00933 
00934                 if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(audio_buffer, write_frame.data, read_impl.decoded_bytes_per_packet)) <= 0) {
00935                         break;
00936                 }
00937 
00938                 write_frame.samples = write_frame.datalen / 2;
00939 
00940                 if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
00941                         break;
00942                 }
00943         }
00944 
00945         switch_core_codec_destroy(&write_codec);
00946         switch_buffer_destroy(&audio_buffer);
00947         teletone_destroy_session(&ts);
00948 
00949         return SWITCH_STATUS_SUCCESS;
00950 }

switch_status_t switch_ivr_hold ( switch_core_session_t session,
const char *  message,
switch_bool_t  moh 
)

Signal the session with a protocol specific hold message.

Parameters:
session the session to hold
message optional message
moh play music-on-hold
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1370 of file switch_ivr.c.

References CF_HOLD, CF_SUSPEND, switch_core_session_message::from, switch_core_session_message::message_id, SMF_ECHO_ALEG, SMF_LOOP, switch_core_session_message::string_arg, switch_channel_get_hold_music(), switch_channel_get_variable, switch_channel_set_flag, switch_core_session_get_channel(), switch_core_session_receive_message, switch_ivr_broadcast(), SWITCH_MESSAGE_INDICATE_HOLD, SWITCH_SIGNAL_BOND_VARIABLE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_hold_uuid().

01371 {
01372         switch_core_session_message_t msg = { 0 };
01373         switch_channel_t *channel = switch_core_session_get_channel(session);
01374         const char *stream;
01375         const char *other_uuid;
01376 
01377         msg.message_id = SWITCH_MESSAGE_INDICATE_HOLD;
01378         msg.string_arg = message;
01379         msg.from = __FILE__;
01380 
01381         switch_channel_set_flag(channel, CF_HOLD);
01382         switch_channel_set_flag(channel, CF_SUSPEND);
01383 
01384         switch_core_session_receive_message(session, &msg);
01385 
01386         if (moh && (stream = switch_channel_get_hold_music(channel))) {
01387                 if ((other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
01388                         switch_ivr_broadcast(other_uuid, stream, SMF_ECHO_ALEG | SMF_LOOP);
01389                 }
01390         }
01391 
01392 
01393         return SWITCH_STATUS_SUCCESS;
01394 }

switch_status_t switch_ivr_hold_uuid ( const char *  uuid,
const char *  message,
switch_bool_t  moh 
)

Signal the session with a protocol specific hold message.

Parameters:
uuid the uuid of the session to hold
message optional message
moh play music-on-hold
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1396 of file switch_ivr.c.

References switch_core_session_locate(), switch_core_session_rwunlock(), switch_ivr_hold(), and SWITCH_STATUS_SUCCESS.

01397 {
01398         switch_core_session_t *session;
01399 
01400         if ((session = switch_core_session_locate(uuid))) {
01401                 switch_ivr_hold(session, message, moh);
01402                 switch_core_session_rwunlock(session);
01403         }
01404 
01405         return SWITCH_STATUS_SUCCESS;
01406 }

switch_status_t switch_ivr_inband_dtmf_generate_session ( switch_core_session_t session,
switch_bool_t  read_stream 
)

Start generating DTMF inband.

Parameters:
session the session to generate on
read_stream true to use the session we are reading from, false for the session we are writing to.
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2641 of file switch_ivr_async.c.

References inband_dtmf_generate_callback(), SMBF_NO_PAUSE, SMBF_READ_REPLACE, SMBF_WRITE_REPLACE, switch_channel_media_up, switch_channel_pre_answer, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), switch_core_media_bug_add(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_read_codec(), SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, and SWITCH_STATUS_SUCCESS.

02642 {
02643         switch_channel_t *channel = switch_core_session_get_channel(session);
02644         switch_media_bug_t *bug;
02645         switch_status_t status;
02646         switch_inband_dtmf_generate_t *pvt;
02647 
02648         if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
02649                 return SWITCH_STATUS_FALSE;
02650         }
02651 
02652         if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
02653                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not install inband dtmf generate.  Media not enabled on channel\n");
02654                 return status;
02655         }
02656 
02657         if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
02658                 return SWITCH_STATUS_MEMERR;
02659         }
02660 
02661         pvt->session = session;
02662         pvt->read = !!read_stream;
02663 
02664         if ((status = switch_core_media_bug_add(session, "inband_dtmf_generate", NULL,
02665                                                                                         inband_dtmf_generate_callback, pvt, 0,
02666                                                                                         SMBF_NO_PAUSE | (pvt->read ? SMBF_READ_REPLACE : SMBF_WRITE_REPLACE) , &bug)) != SWITCH_STATUS_SUCCESS) {
02667                 return status;
02668         }
02669 
02670         switch_channel_set_private(channel, "dtmf_generate", bug);
02671 
02672         return SWITCH_STATUS_SUCCESS;
02673 }

switch_status_t switch_ivr_inband_dtmf_session ( switch_core_session_t session  ) 

Start looking for DTMF inband.

Parameters:
session the session to start looking
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2406 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, inband_dtmf_callback(), SMBF_NO_PAUSE, SMBF_READ_REPLACE, switch_channel_pre_answer, switch_channel_set_private(), switch_core_media_bug_add(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_read_impl(), SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, and teletone_dtmf_detect_init().

02407 {
02408         switch_channel_t *channel = switch_core_session_get_channel(session);
02409         switch_media_bug_t *bug;
02410         switch_status_t status;
02411         switch_inband_dtmf_t *pvt;
02412         switch_codec_implementation_t read_impl = { 0 };
02413 
02414         switch_core_session_get_read_impl(session, &read_impl);
02415 
02416         if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
02417                 return SWITCH_STATUS_MEMERR;
02418         }
02419 
02420         teletone_dtmf_detect_init(&pvt->dtmf_detect, read_impl.actual_samples_per_second);
02421 
02422         pvt->session = session;
02423 
02424 
02425         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
02426                 return SWITCH_STATUS_FALSE;
02427         }
02428 
02429         if ((status = switch_core_media_bug_add(session, "inband_dtmf", NULL,
02430                                                                                         inband_dtmf_callback, pvt, 0, SMBF_READ_REPLACE | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) {
02431                 return status;
02432         }
02433 
02434         switch_channel_set_private(channel, "dtmf", bug);
02435 
02436         return SWITCH_STATUS_SUCCESS;
02437 }

switch_status_t switch_ivr_media ( const char *  uuid,
switch_media_flag_t  flags 
)

Signal a session to request direct media access to it's remote end.

Parameters:
uuid the uuid of the session to request
flags flags to influence behaviour (SMF_REBRIDGE to rebridge the call in media mode)
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1447 of file switch_ivr.c.

References CF_BRIDGE_ORIGINATOR, CF_BRIDGED, CF_EARLY_MEDIA, CF_MEDIA_ACK, CF_MEDIA_SET, CF_PROXY_MODE, CF_REQ_MEDIA, switch_core_session_message::from, switch_core_session_message::message_id, SMF_IMMEDIATE, SMF_REBRIDGE, switch_assert, switch_channel_clear_state_handler(), switch_channel_get_name(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_test_flag(), switch_channel_wait_for_flag(), switch_core_session_get_channel(), switch_core_session_locate(), switch_core_session_read_frame(), switch_core_session_receive_message, switch_core_session_rwunlock(), SWITCH_FALSE, SWITCH_IO_FLAG_NONE, switch_ivr_uuid_bridge(), SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS, SWITCH_MESSAGE_INDICATE_MEDIA, SWITCH_SIGNAL_BRIDGE_VARIABLE, SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_yield.

Referenced by cleanup_proxy_mode_b(), switch_core_session_execute_application_get_flags(), switch_core_standard_on_routing(), switch_ivr_broadcast(), switch_ivr_originate(), and switch_ivr_session_transfer().

01448 {
01449         const char *other_uuid = NULL;
01450         switch_channel_t *channel, *other_channel = NULL;
01451         switch_core_session_t *session, *other_session;
01452         switch_core_session_message_t msg = { 0 };
01453         switch_status_t status = SWITCH_STATUS_GENERR;
01454         uint8_t swap = 0;
01455         switch_frame_t *read_frame = NULL;
01456 
01457         msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA;
01458         msg.from = __FILE__;
01459 
01460         if ((session = switch_core_session_locate(uuid))) {
01461                 channel = switch_core_session_get_channel(session);
01462 
01463                 if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
01464                         swap = 1;
01465                 }
01466 
01467                 if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
01468                         status = SWITCH_STATUS_SUCCESS;
01469 
01470                         /* If we had early media in bypass mode before, it is no longer relevant */
01471                         if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
01472                                 switch_core_session_message_t msg2 = { 0 };
01473 
01474                                 msg2.message_id = SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS;
01475                                 msg2.from = __FILE__;
01476                                 switch_core_session_receive_message(session, &msg2);
01477                         }
01478 
01479                         if (switch_core_session_receive_message(session, &msg) != SWITCH_STATUS_SUCCESS) {
01480                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't re-establsh media on %s\n", switch_channel_get_name(channel));
01481                                 switch_core_session_rwunlock(session);
01482                                 return SWITCH_STATUS_GENERR;
01483                         }
01484 
01485                         if ((flags & SMF_IMMEDIATE)) {
01486                                 switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 250, NULL);
01487                                 switch_yield(250000);
01488                         } else {
01489                                 switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
01490                                 switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
01491                                 switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
01492                                 switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
01493                         }
01494 
01495                         if ((flags & SMF_REBRIDGE)
01496                                 && (other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE))
01497                                 && (other_session = switch_core_session_locate(other_uuid))) {
01498                                 other_channel = switch_core_session_get_channel(other_session);
01499                                 switch_assert(other_channel != NULL);
01500                                 switch_core_session_receive_message(other_session, &msg);
01501                                 switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
01502                                 switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
01503                                 switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
01504                                 switch_core_session_read_frame(other_session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
01505                                 switch_channel_clear_state_handler(other_channel, NULL);
01506                                 switch_core_session_rwunlock(other_session);
01507                         }
01508                         if (other_channel) {
01509                                 switch_channel_clear_state_handler(channel, NULL);
01510                         }
01511                 }
01512 
01513                 switch_core_session_rwunlock(session);
01514 
01515                 if (other_channel) {
01516                         if (swap) {
01517                                 switch_ivr_uuid_bridge(other_uuid, uuid);
01518                         } else {
01519                                 switch_ivr_uuid_bridge(uuid, other_uuid);
01520                         }
01521                         switch_channel_wait_for_flag(channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
01522                         switch_channel_wait_for_flag(other_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
01523                 }
01524         }
01525 
01526         return status;
01527 }

switch_status_t switch_ivr_multi_threaded_bridge ( _In_ switch_core_session_t session,
_In_ switch_core_session_t peer_session,
switch_input_callback_function_t  dtmf_callback,
void *  session_data,
void *  peer_session_data 
)

Bridge Audio from one session to another.

Parameters:
session one session
peer_session the other session
dtmf_callback a callback for messages and dtmf
session_data data to pass to the DTMF callback for session
peer_session_data data to pass to the DTMF callback for peer_session
Returns:
SWITCH_STATUS_SUCCESS if all is well

Referenced by bridge(), fs_switch_ivr_originate(), and uuid_bridge_on_soft_execute().

switch_status_t switch_ivr_nomedia ( const char *  uuid,
switch_media_flag_t  flags 
)

Signal a session to request indirect media allowing it to exchange media directly with another device.

Parameters:
uuid the uuid of the session to request
flags flags to influence behaviour (SMF_REBRIDGE to rebridge the call in no_media mode)
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1529 of file switch_ivr.c.

References CF_BRIDGE_ORIGINATOR, CF_MEDIA_ACK, CF_MEDIA_SET, CF_PROXY_MODE, CF_REDIRECT, CF_REQ_MEDIA, CF_RESET, CS_HIBERNATE, CS_PARK, switch_core_session_message::from, switch_core_session_message::message_id, SMF_FORCE, SMF_REBRIDGE, SWITCH_BRIDGE_VARIABLE, switch_channel_get_variable, switch_channel_set_flag, switch_channel_set_state, switch_channel_test_flag(), switch_channel_wait_for_flag(), switch_channel_wait_for_state(), switch_core_session_get_channel(), switch_core_session_in_thread(), switch_core_session_locate(), switch_core_session_receive_message, switch_core_session_rwunlock(), SWITCH_FALSE, switch_ivr_signal_bridge(), SWITCH_MESSAGE_INDICATE_NOMEDIA, SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_yield.

Referenced by audio_bridge_thread(), and switch_ivr_parse_event().

01530 {
01531         const char *other_uuid;
01532         switch_channel_t *channel, *other_channel = NULL;
01533         switch_core_session_t *session, *other_session = NULL;
01534         switch_core_session_message_t msg = { 0 };
01535         switch_status_t status = SWITCH_STATUS_GENERR;
01536         uint8_t swap = 0;
01537 
01538         msg.message_id = SWITCH_MESSAGE_INDICATE_NOMEDIA;
01539         msg.from = __FILE__;
01540 
01541         if ((session = switch_core_session_locate(uuid))) {
01542                 status = SWITCH_STATUS_SUCCESS;
01543                 channel = switch_core_session_get_channel(session);
01544 
01545                 if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
01546                         swap = 1;
01547                 }
01548 
01549                 switch_channel_set_flag(channel, CF_REDIRECT);
01550                 switch_channel_set_flag(channel, CF_RESET);
01551 
01552                 if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_PROXY_MODE)) {
01553                         if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
01554                                 (other_session = switch_core_session_locate(other_uuid))) {
01555                                 other_channel = switch_core_session_get_channel(other_session);
01556 
01557                                 switch_channel_set_flag(other_channel, CF_RESET);
01558                                 switch_channel_set_flag(other_channel, CF_REDIRECT);
01559 
01560                                 if (!switch_core_session_in_thread(session)) {
01561                                         switch_channel_set_state(channel, CS_PARK);
01562                                 }
01563                                 switch_channel_set_state(other_channel, CS_PARK);
01564                                 if (switch_core_session_in_thread(session)) {
01565                                         switch_yield(100000);
01566                                 } else {
01567                                         switch_channel_wait_for_state(other_channel, channel, CS_PARK);
01568                                 }
01569                                 switch_core_session_receive_message(other_session, &msg);
01570                                 switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
01571                                 //switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
01572                                 switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
01573                         }
01574 
01575                         switch_core_session_receive_message(session, &msg);
01576 
01577                         if (other_channel) {
01578                                 if (!switch_core_session_in_thread(session)) {
01579                                         switch_channel_wait_for_state(channel, NULL, CS_PARK);
01580                                         switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
01581                                         switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
01582                                         switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
01583                                 }
01584 
01585                                 if (swap) {
01586                                         switch_ivr_signal_bridge(other_session, session);
01587                                 } else {
01588                                         switch_ivr_signal_bridge(session, other_session);
01589                                 }
01590 
01591                                 if (switch_core_session_in_thread(session)) {
01592                     switch_yield(100000);
01593                 } else {
01594                                         switch_channel_wait_for_state(other_channel, channel, CS_HIBERNATE);
01595                                 }
01596 
01597                                 if (!switch_core_session_in_thread(session)) {
01598                                         switch_channel_wait_for_state(channel, other_channel, CS_HIBERNATE);
01599                                 }
01600                                 switch_core_session_rwunlock(other_session);
01601                         }
01602                 }
01603                 switch_core_session_rwunlock(session);
01604         }
01605 
01606         return status;
01607 }

switch_status_t switch_ivr_originate ( switch_core_session_t session,
switch_core_session_t **  bleg,
switch_call_cause_t cause,
const char *  bridgeto,
uint32_t  timelimit_sec,
const switch_state_handler_table_t table,
const char *  cid_name_override,
const char *  cid_num_override,
switch_caller_profile_t caller_profile_override,
switch_event_t ovars,
switch_originate_flag_t  flags,
switch_call_cause_t cancel_cause 
)

Make an outgoing call.

Parameters:
session originating session
bleg B leg session
cause a pointer to hold call cause
bridgeto the desired remote callstring
timelimit_sec timeout in seconds for outgoing call
table optional state handler table to install on the channel
cid_name_override override the caller id name
cid_num_override override the caller id number
caller_profile_override override the entire calling caller profile
ovars variables to be set on the outgoing channel
flags flags to pass
Returns:
SWITCH_STATUS_SUCCESS if bleg is a running session.
Note:
bleg will be read locked which must be unlocked with switch_core_session_rwunlock() before losing scope

Definition at line 1748 of file switch_ivr_originate.c.

References originate_global_t::bridge_early_media, buf, switch_frame::buflen, originate_global_t::caller_profile_override, CF_ANSWERED, CF_EARLY_MEDIA, CF_ORIGINATOR, CF_PROXY_MEDIA, CF_PROXY_MODE, originate_global_t::check_vars, switch_frame::data, originate_global_t::early_ok, originate_global_t::error_file, originate_global_t::file, switch_core_session_message::from, originate_global_t::idx, IDX_NADA, MAX_PEERS, switch_core_session_message::message_id, switch_event_header::name, switch_event_header::next, early_state::oglobals, early_state::originate_status, originate_global_t::pool, originate_global_t::ringback_ok, originate_global_t::session, SMF_NONE, SOF_NONE, SWITCH_B_SDP_VARIABLE, SWITCH_BYPASS_MEDIA_VARIABLE, SWITCH_CALL_TIMEOUT_VARIABLE, switch_caller_profile_dup(), SWITCH_CAUSE_NONE, switch_channel_answer, switch_channel_clear_flag(), switch_channel_get_caller_profile(), switch_channel_get_name(), switch_channel_get_variable, switch_channel_process_export(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_set_variable, switch_channel_test_flag(), switch_channel_variable_first(), switch_core_get_variable(), switch_core_new_memory_pool, switch_core_session_get_channel(), switch_core_session_get_read_impl(), switch_core_session_get_uuid(), switch_core_session_receive_message, SWITCH_ENT_ORIGINATE_DELIM, SWITCH_EVENT_CHANNEL_DATA, switch_event_create_brackets(), switch_event_create_plain(), switch_event_get_header, SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE, switch_goto_status, switch_ivr_enterprise_originate(), switch_ivr_media(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS, SWITCH_PROXY_MEDIA_VARIABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, switch_snprintf(), SWITCH_STATUS_GENERR, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, switch_stristr(), SWITCH_TRUE, switch_true(), switch_zmalloc, and zstr.

Referenced by CoreSession::CoreSession(), enterprise_originate_thread(), fs_switch_ivr_originate(), and CoreSession::originate().

01758 {
01759         originate_status_t originate_status[MAX_PEERS] = { {0} };
01760         switch_originate_flag_t dftflags = SOF_NONE, myflags = dftflags;
01761         char *pipe_names[MAX_PEERS] = { 0 };
01762         char *data = NULL;
01763         switch_status_t status = SWITCH_STATUS_SUCCESS;
01764         switch_channel_t *caller_channel = NULL;
01765         char *peer_names[MAX_PEERS] = { 0 };
01766         switch_core_session_t *new_session = NULL, *peer_session;
01767         switch_caller_profile_t *new_profile = NULL, *caller_caller_profile;
01768         char *chan_type = NULL, *chan_data;
01769         switch_channel_t *peer_channel = NULL;
01770         ringback_t ringback = { 0 };
01771         time_t start;
01772         switch_frame_t *read_frame = NULL;
01773         int r = 0, i, and_argc = 0, or_argc = 0;
01774         int32_t sleep_ms = 1000, try = 0, retries = 1;
01775         switch_codec_t write_codec = { 0 };
01776         switch_frame_t write_frame = { 0 };
01777         char *odata, *var;
01778         switch_call_cause_t reason = SWITCH_CAUSE_NONE;
01779         switch_call_cause_t force_reason = SWITCH_CAUSE_NONE;
01780         uint8_t to = 0;
01781         char *var_val;
01782         const char *ringback_data = NULL;
01783         switch_event_t *var_event = NULL;
01784         int8_t fail_on_single_reject = 0;
01785         char *fail_on_single_reject_var = NULL;
01786         char *loop_data = NULL;
01787         uint32_t progress_timelimit_sec = 0;
01788         const char *cid_tmp, *lc;
01789         originate_global_t oglobals = { 0 };
01790         int cdr_total = 0;
01791         int local_clobber = 0;
01792         const char *cancel_key = NULL;
01793         const char *holding = NULL;
01794         const char *soft_holding = NULL;
01795         early_state_t early_state = { 0 };
01796         int read_packet = 0;
01797         int check_reject = 1;
01798         switch_codec_implementation_t read_impl = { 0 };
01799         
01800         if (strstr(bridgeto, SWITCH_ENT_ORIGINATE_DELIM)) {
01801                 return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override,
01802                                                                                            caller_profile_override, ovars, flags, cancel_cause);
01803         }
01804 
01805         oglobals.check_vars = SWITCH_TRUE;
01806         oglobals.ringback_ok = 1;
01807         oglobals.bridge_early_media = -1;
01808         oglobals.file = NULL;
01809         oglobals.error_file = NULL;
01810         switch_core_new_memory_pool(&oglobals.pool);
01811 
01812         if (caller_profile_override) {
01813                 oglobals.caller_profile_override = switch_caller_profile_dup(oglobals.pool, caller_profile_override);
01814         } else if (session) {
01815                 switch_caller_profile_t *cp = switch_channel_get_caller_profile(switch_core_session_get_channel(session));
01816 
01817                 if (cp) {
01818                         oglobals.caller_profile_override = switch_caller_profile_dup(oglobals.pool, cp);
01819                 }
01820         }
01821 
01822         if (session) {
01823                 const char *to_var, *bypass_media = NULL, *proxy_media = NULL;
01824                 caller_channel = switch_core_session_get_channel(session);
01825                 switch_channel_set_flag(caller_channel, CF_ORIGINATOR);
01826                 oglobals.session = session;
01827 
01828                 switch_core_session_get_read_impl(session, &read_impl);
01829 
01830                 if ((to_var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
01831                         timelimit_sec = atoi(to_var);
01832                 }
01833 
01834                 proxy_media = switch_channel_get_variable(caller_channel, SWITCH_PROXY_MEDIA_VARIABLE);
01835                 bypass_media = switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_VARIABLE);
01836 
01837                 if (!zstr(proxy_media)) {
01838                         if (switch_true(proxy_media)) {
01839                                 switch_channel_set_flag(caller_channel, CF_PROXY_MEDIA);
01840                         } else if (switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
01841                                 switch_channel_clear_flag(caller_channel, CF_PROXY_MEDIA);
01842                         }
01843                 }
01844 
01845                 if (bypass_media && switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
01846                         switch_core_session_message_t msg = { 0 };
01847 
01848                         msg.message_id = SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS;
01849                         msg.from = __FILE__;
01850                         switch_core_session_receive_message(session, &msg);
01851                 }
01852 
01853 
01854                 if (!zstr(bypass_media) && !switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
01855                         if (switch_true(bypass_media)) {
01856                                 switch_channel_set_flag(caller_channel, CF_PROXY_MODE);
01857                         } else if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
01858                                 if (!switch_channel_test_flag(caller_channel, CF_ANSWERED) && switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
01859                                         switch_channel_set_variable(caller_channel, SWITCH_B_SDP_VARIABLE, NULL);
01860                                         switch_channel_answer(caller_channel);
01861                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, 
01862                                                                           "Must answer channel %s due to SIP PARADOX\n", switch_channel_get_name(caller_channel));
01863                                 }
01864                                 switch_channel_set_variable(caller_channel, SWITCH_B_SDP_VARIABLE, NULL);
01865                                 switch_ivr_media(switch_core_session_get_uuid(session), SMF_NONE);
01866                         }
01867                 }
01868                 
01869                 if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
01870                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
01871                                                           "Channel is already up, delaying proxy mode 'till both legs are answered.\n");
01872                         switch_channel_set_variable(caller_channel, "bypass_media_after_bridge", "true");
01873                         switch_channel_set_variable(caller_channel, SWITCH_BYPASS_MEDIA_VARIABLE, NULL);
01874                         switch_channel_clear_flag(caller_channel, CF_PROXY_MODE);
01875                 }
01876         }
01877 
01878         if (timelimit_sec <= 0) {
01879                 timelimit_sec = 60;
01880         }
01881 
01882 
01883         oglobals.idx = IDX_NADA;
01884         oglobals.early_ok = 1;
01885 
01886         *bleg = NULL;
01887 
01888         switch_zmalloc(write_frame.data, SWITCH_RECOMMENDED_BUFFER_SIZE);
01889         write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
01890 
01891         odata = strdup(bridgeto);
01892 
01893         if (!odata) {
01894                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error!\n");
01895                 status = SWITCH_STATUS_MEMERR;
01896                 goto done;
01897         }
01898 
01899         data = odata;
01900 
01901 
01902         /* Some channel are created from an originating channel and some aren't so not all outgoing calls have a way to get params
01903            so we will normalize dialstring params and channel variables (when there is an originator) into an event that we 
01904            will use as a pseudo hash to consult for params as needed.
01905          */
01906 
01907         if (ovars) {
01908                 var_event = ovars;
01909         } else {
01910                 if (switch_event_create_plain(&var_event, SWITCH_EVENT_CHANNEL_DATA) != SWITCH_STATUS_SUCCESS) {
01911                         abort();
01912                 }
01913         }
01914 
01915         if (caller_channel) {
01916                 switch_channel_process_export(caller_channel, NULL, var_event, SWITCH_EXPORT_VARS_VARIABLE);
01917         }
01918 
01919         /* strip leading spaces */
01920         while (data && *data && *data == ' ') {
01921                 data++;
01922         }
01923 
01924         if ((ovars && switch_true(switch_event_get_header(ovars,"origination_nested_vars"))) || 
01925                 (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "origination_nested_vars"))) 
01926                 || switch_true(switch_core_get_variable("origination_nested_vars")) || switch_stristr("origination_nested_vars=true", data)) {
01927                 oglobals.check_vars = SWITCH_FALSE;
01928         }
01929 
01930 
01931         /* extract channel variables, allowing multiple sets of braces */
01932         if (*data == '<') {
01933                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing ultra-global variables\n");
01934                 while (*data == '<') {
01935                         char *parsed = NULL;
01936 
01937                         if (switch_event_create_brackets(data, '<', '>', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
01938                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
01939                                 switch_goto_status(SWITCH_STATUS_GENERR, done);
01940                         }
01941                         
01942                         data = parsed;
01943                 }
01944         }
01945 
01946         /* extract channel variables, allowing multiple sets of braces */
01947         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing global variables\n");
01948         while (*data == '{') {
01949                 char *parsed = NULL;
01950 
01951                 if (switch_event_create_brackets(data, '{', '}', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
01952                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
01953                         switch_goto_status(SWITCH_STATUS_GENERR, done);
01954                 }
01955 
01956                 data = parsed;
01957         }
01958 
01959         
01960         /* strip leading spaces (again) */
01961         while (data && *data && *data == ' ') {
01962                 data++;
01963         }
01964 
01965         if (zstr(data)) {
01966                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "No origination URL specified!\n");
01967                 status = SWITCH_STATUS_GENERR;
01968                 goto done;
01969         }
01970 
01971 
01972         if (oglobals.session) {
01973                 switch_event_header_t *hi;
01974                 const char *cdr_total_var;
01975                 const char *cdr_var;
01976 
01977                 if ((cdr_var = switch_channel_get_variable(caller_channel, "failed_xml_cdr_prefix"))) {
01978                         char buf[128] = "";
01979                         switch_snprintf(buf, sizeof(buf), "%s_total", cdr_var);
01980                         if ((cdr_total_var = switch_channel_get_variable(caller_channel, buf))) {
01981                                 int tmp = atoi(cdr_total_var);
01982                                 if (tmp > 0) {
01983                                         cdr_total = tmp;
01984                                 }
01985                         }
01986                 }
01987 
01988 
01989                 /* Copy all the missing applicable channel variables from A-leg into the event */
01990                 if ((hi = switch_channel_variable_first(caller_channel))) {
01991                         for (; hi; hi = hi->next) {
01992                                 int ok = 0;
01993                                 if (!strcasecmp((char *) hi->name, "group_confirm_key")) {
01994                                         ok = 1;
01995                                 } else if (!strcasecmp((char *) hi->name, "group_confirm_file")) {
01996                                         ok = 1;
01997                                 } else if (!strcasecmp((char *) hi->name, "group_confirm_read_timeout")) {
01998                                         ok = 1;
01999                                 } else if (!strcasecmp((char *) hi->name, "group_confirm_cancel_timeout")) {
02000                                         ok = 1;
02001                                 } else if (!strcasecmp((char *) hi->name, "forked_dial")) {
02002                                         ok = 1;
02003                                 } else if (!strcasecmp((char *) hi->name, "fail_on_single_reject")) {
02004                                         ok = 1;
02005                                 } else if (!strcasecmp((char *) hi->name, "ignore_early_media")) {
02006                                         ok = 1;
02007                                 } else if (!strcasecmp((char *) hi->name, "bridge_early_media")) {
02008                                         ok = 1;
02009                                 } else if (!strcasecmp((char *) hi->name, "originate_continue_on_timeout")) {
02010                                         ok = 1;
02011                                 } else if (!strcasecmp((char *) hi->name, "ignore_ring_ready")) {
02012                                         ok = 1;
02013                                 } else if (!strcasecmp((char *) hi->name, "monitor_early_media_ring")) {
02014                                         ok = 1;
02015                                 } else if (!strcasecmp((char *) hi->name, "monitor_early_media_ring_total")) {
02016                                         ok = 1;
02017                                 } else if (!strcasecmp((char *) hi->name, "monitor_early_media_fail")) {
02018                                         ok = 1;
02019                                 } else if (!strcasecmp((char *) hi->name, "return_ring_ready")) {
02020                                         ok = 1;
02021                                 } else if (!strcasecmp((char *) hi->name, "ring_ready")) {
02022                                         ok = 1;
02023                                 } else if (!strcasecmp((char *) hi->name, "instant_ringback")) {
02024                                         ok = 1;
02025                                 } else if (!strcasecmp((char *) hi->name, "progress_timeout")) {
02026                                         ok = 1;
02027                                 } else if (!strcasecmp((char *) hi->name, "language")) {
02028                                         ok = 1;
02029                                 }
02030 
02031                                 if (ok && !switch_event_get_header(var_event, hi->name)) {
02032                                         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, (char *) hi->name, (char *) hi->value);
02033                                 }
02034                         }
02035                         switch_channel_variable_last(caller_channel);
02036                 }
02037                 /*
02038                    if ((hi = switch_channel_variable_first(caller_channel))) {
02039                    for (; hi; hi = switch_hash_next(hi)) {
02040                    switch_hash_this(hi, &vvar, NULL, &vval);
02041                    if (vvar && vval) {
02042                    switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, (void *) vvar, (char *) vval);
02043                    }
02044                    }
02045                    switch_channel_variable_last(caller_channel);
02046                    }
02047                  */
02048         }
02049 
02050         if (caller_channel) {           /* ringback is only useful when there is an originator */
02051                 ringback_data = NULL;
02052                 cancel_key = switch_channel_get_variable(caller_channel, "origination_cancel_key");
02053 
02054                 if (switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
02055                         ringback_data = switch_channel_get_variable(caller_channel, "transfer_ringback");
02056                 }
02057 
02058                 if (!ringback_data) {
02059                         ringback_data = switch_channel_get_variable(caller_channel, "ringback");
02060                 }
02061 
02062                 switch_channel_set_variable(caller_channel, "originate_disposition", "failure");
02063                 switch_channel_set_variable(caller_channel, "DIALSTATUS", "INVALIDARGS");
02064 
02065                 if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
02066                         ringback_data = NULL;
02067                 } else if (zstr(ringback_data)) {
02068                         const char *vvar;
02069 
02070                         if ((vvar = switch_channel_get_variable(caller_channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE))) {
02071                                 int sval = atoi(vvar);
02072 
02073                                 if (sval) {
02074                                         ringback_data = switch_core_session_sprintf(oglobals.session, "silence:%d", sval);
02075                                 }
02076 
02077                         }
02078                 }
02079         }
02080 #if 0
02081         /* changing behaviour ignore_early_media=true must also be explicitly set for previous behaviour */
02082         if (ringback_data) {
02083                 oglobals.early_ok = 0;
02084         }
02085 #endif
02086 
02087         if (switch_true(switch_event_get_header(var_event, "group_confirm_cancel_timeout"))) {
02088                 oglobals.cancel_timeout = -1;
02089         }
02090 
02091         if ((var = switch_event_get_header(var_event, "group_confirm_key"))) {
02092                 switch_copy_string(oglobals.key, var, sizeof(oglobals.key));
02093                 if ((var = switch_event_get_header(var_event, "group_confirm_file"))) {
02094                         oglobals.file = strdup(var);
02095                 }
02096                 if ((var = switch_event_get_header(var_event, "group_confirm_error_file"))) {
02097                         oglobals.error_file = strdup(var);
02098                 }
02099                 if ((var = switch_event_get_header(var_event, "group_confirm_read_timeout"))) {
02100                         int tmp = atoi(var);
02101 
02102                         if (tmp >= 0) {
02103                                 oglobals.confirm_timeout = tmp;
02104                         }
02105 
02106                 }
02107         }
02108         /* When using the AND operator, the fail_on_single_reject flag may be set in order to indicate that a single
02109            rejections should terminate the attempt rather than a timeout, answer, or rejection by all. 
02110            If the value is set to 'true' any fail cause will end the attempt otherwise it can contain a comma (,) separated
02111            list of cause names which should be considered fatal
02112          */
02113         if ((var = switch_event_get_header(var_event, "fail_on_single_reject"))) {
02114                 fail_on_single_reject_var = strdup(var);
02115                 if (switch_true(var)) {
02116                         fail_on_single_reject = 1;
02117                 } else {
02118                         fail_on_single_reject = -1;
02119                 }
02120         }
02121 
02122         if ((!zstr(oglobals.file)) && (!strcmp(oglobals.file, "undef"))) {
02123                 switch_safe_free(oglobals.file);
02124                 oglobals.file = NULL;
02125         }
02126         if ((!zstr(oglobals.error_file)) && (!strcmp(oglobals.error_file, "undef"))) {
02127                 switch_safe_free(oglobals.error_file);
02128                 oglobals.error_file = NULL;
02129         }
02130 
02131         if ((var_val = switch_event_get_header(var_event, "bridge_early_media"))) {
02132                 if (switch_true(var_val)) {
02133                         oglobals.early_ok = 0;
02134                         oglobals.ignore_early_media = 3;
02135                 }
02136         }
02137 
02138         if ((var_val = switch_event_get_header(var_event, "ignore_early_media"))) {
02139                 if (switch_true(var_val)) {
02140                         oglobals.early_ok = 0;
02141                         oglobals.ignore_early_media = 1;
02142                 } else if (!strcmp(var_val, "ring_ready")) {
02143                         oglobals.early_ok = 0;
02144                         oglobals.ignore_early_media = 2;
02145                 }
02146         }
02147 
02148         if ((var_val = switch_event_get_header(var_event, "originate_continue_on_timeout")) && switch_true(var_val)) {
02149                 oglobals.continue_on_timeout = 1;
02150         }
02151 
02152         if ((var_val = switch_event_get_header(var_event, "ignore_ring_ready")) && switch_true(var_val)) {
02153                 oglobals.ignore_ring_ready = 1;
02154         }
02155 
02156         if ((var_val = switch_event_get_header(var_event, "monitor_early_media_ring"))) {
02157                 oglobals.early_ok = 0;
02158                 oglobals.monitor_early_media_ring = 1;
02159         }
02160 
02161         if ((var_val = switch_event_get_header(var_event, "monitor_early_media_fail"))) {
02162                 oglobals.early_ok = 0;
02163                 oglobals.monitor_early_media_fail = 1;
02164         }
02165 
02166         if ((var_val = switch_event_get_header(var_event, "return_ring_ready")) && switch_true(var_val)) {
02167                 oglobals.return_ring_ready = 1;
02168         }
02169 
02170         if ((var_val = switch_event_get_header(var_event, "ring_ready")) && switch_true(var_val)) {
02171                 oglobals.ring_ready = 1;
02172         }
02173 
02174         if ((var_val = switch_event_get_header(var_event, "instant_ringback")) && switch_true(var_val)) {
02175                 oglobals.instant_ringback = 1;
02176         }
02177 
02178         if ((var_val = switch_event_get_header(var_event, "originate_timeout"))) {
02179                 int tmp = atoi(var_val);
02180                 if (tmp > 0) {
02181                         timelimit_sec = (uint32_t) tmp;
02182                 }
02183         }
02184 
02185         if ((var_val = switch_event_get_header(var_event, "progress_timeout"))) {
02186                 int tmp = atoi(var_val);
02187                 if (tmp > 0) {
02188                         progress_timelimit_sec = (uint32_t) tmp;
02189                 }
02190         }
02191 
02192         if ((var_val = switch_event_get_header(var_event, "originate_retries")) && switch_true(var_val)) {
02193                 int32_t tmp;
02194                 tmp = atoi(var_val);
02195                 if (tmp > 0 && tmp < 101) {
02196                         retries = tmp;
02197                 } else {
02198                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
02199                                                           "Invalid originate_retries setting of %d ignored, value must be between 1 and 100\n", tmp);
02200                 }
02201         }
02202 
02203         if ((var_val = switch_event_get_header(var_event, "originate_retry_sleep_ms")) && switch_true(var_val)) {
02204                 int32_t tmp;
02205                 tmp = atoi(var_val);
02206                 if (tmp >= 500 && tmp <= 60000) {
02207                         sleep_ms = tmp;
02208                 } else {
02209                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
02210                                                           "Invalid originate_retry_sleep_ms setting of %d ignored, value must be between 500 and 60000\n", tmp);
02211                 }
02212         }
02213 
02214         if ((cid_tmp = switch_event_get_header(var_event, "origination_caller_id_name"))) {
02215                 cid_name_override = cid_tmp;
02216         }
02217 
02218         if (cid_name_override) {
02219                 if (!cid_tmp) {
02220                         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_name", cid_name_override);
02221                 }
02222         } else {
02223                 cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
02224         }
02225 
02226         if ((cid_tmp = switch_event_get_header(var_event, "origination_caller_id_number"))) {
02227                 cid_num_override = cid_tmp;
02228         }
02229 
02230         if (cid_num_override) {
02231                 if (!cid_tmp) {
02232                         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_number", cid_num_override);
02233                 }
02234         } else {
02235                 cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
02236         }
02237 
02238         if (flags & SOF_NO_LIMITS) {
02239                 dftflags |= SOF_NO_LIMITS;
02240         }
02241 
02242         if (cid_num_override) {
02243                 dftflags |= SOF_NO_EFFECTIVE_CID_NUM;
02244         }
02245         
02246         if (cid_name_override) {
02247                 dftflags |= SOF_NO_EFFECTIVE_CID_NAME;
02248         }
02249 
02250         if (!progress_timelimit_sec) {
02251                 progress_timelimit_sec = timelimit_sec;
02252         }
02253 
02254         for (try = 0; try < retries; try++) {
02255                 switch_safe_free(loop_data);
02256                 loop_data = strdup(data);
02257                 switch_assert(loop_data);
02258                 or_argc = switch_separate_string(loop_data, '|', pipe_names, (sizeof(pipe_names) / sizeof(pipe_names[0])));
02259 
02260                 if ((flags & SOF_NOBLOCK) && or_argc > 1) {
02261                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Only calling the first element in the list in this mode.\n");
02262                         or_argc = 1;
02263                 }
02264 
02265                 for (r = 0; r < or_argc; r++) {
02266                         char *p, *end = NULL;
02267                         int q = 0, alt = 0;
02268 
02269                         check_reject = 1;
02270 
02271                         oglobals.hups = 0;
02272 
02273                         reason = SWITCH_CAUSE_NONE;
02274                         memset(peer_names, 0, sizeof(peer_names));
02275                         peer_session = NULL;
02276                         memset(originate_status, 0, sizeof(originate_status));
02277                         new_profile = NULL;
02278                         new_session = NULL;
02279                         chan_type = NULL;
02280                         chan_data = NULL;
02281                         peer_channel = NULL;
02282                         start = 0;
02283                         read_frame = NULL;
02284                         oglobals.ringback_ok = 1;
02285                         var = NULL;
02286                         to = 0;
02287                         oglobals.sent_ring = 0;
02288                         oglobals.progress = 0;
02289                         myflags = dftflags;
02290                         
02291 
02292                         if (try > 0) {
02293                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Originate attempt %d/%d in %d ms\n", try + 1, retries,
02294                                                                   sleep_ms);
02295                                 if (caller_channel) {
02296                                         switch_ivr_sleep(oglobals.session, sleep_ms, SWITCH_TRUE, NULL);
02297                                         if (!switch_channel_ready(caller_channel)) {
02298                                                 status = SWITCH_STATUS_FALSE;
02299                                                 goto done;
02300                                         }
02301                                 } else {
02302                                         switch_yield(sleep_ms * 1000);
02303                                 }
02304                         }
02305                         
02306                         p = pipe_names[r];
02307                         
02308                         while (p && *p) {
02309                                 if (*p == '[') {
02310                                         end = switch_find_end_paren(p, '[', ']');
02311                                         if (*(p+1) == '^' && *(p + 2) == '^') {
02312                                                 alt = 1;
02313                                         } else {
02314                                                 alt = 0;
02315                                         }
02316                                         q = 0;
02317                                 }
02318                                 
02319                                 if (*p == '\'') {
02320                                         q = !q;
02321                                 }
02322 
02323                                 if (end && p < end && *p == ',') {
02324                                         
02325                                         if (q || alt) {
02326                                                 *p = QUOTED_ESC_COMMA;
02327                                         } else {
02328                                                 *p = UNQUOTED_ESC_COMMA;
02329                                         }
02330                                 }
02331 
02332                                 if (p == end) {
02333                                         end = switch_strchr_strict(p, '[', " ");
02334                                 }
02335 
02336                                 p++;
02337                         }
02338 
02339                         and_argc = switch_separate_string(pipe_names[r], ',', peer_names, (sizeof(peer_names) / sizeof(peer_names[0])));
02340 
02341                         if ((flags & SOF_NOBLOCK) && and_argc > 1) {
02342                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Only calling the first element in the list in this mode.\n");
02343                                 and_argc = 1;
02344                         }
02345 
02346                         for (i = 0; i < and_argc; i++) {
02347                                 const char *current_variable;
02348                                 switch_event_t *local_var_event = NULL, *originate_var_event = NULL, *event = NULL;
02349 
02350                                 end = NULL;
02351                                 
02352                                 chan_type = peer_names[i];
02353                                 
02354 
02355                                 /* strip leading spaces */
02356                                 while (chan_type && *chan_type && *chan_type == ' ') {
02357                                         chan_type++;
02358                                 }
02359                                 
02360                                 /* extract channel variables, allowing multiple sets of braces */
02361                                 
02362                                 if (*chan_type == '[') {
02363                                         switch_event_create_plain(&local_var_event, SWITCH_EVENT_CHANNEL_DATA);
02364                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing session specific variables\n");
02365                                 }
02366 
02367                                 while (*chan_type == '[') {
02368                                         char *parsed = NULL;
02369                                         
02370                                         for (p = chan_type; p && *p && *p != ']'; p++) {
02371                                                 if (*p == QUOTED_ESC_COMMA) {
02372                                                         *p = ',';
02373                                                 }
02374                                         }                                       
02375                                         
02376                                         if (switch_event_create_brackets(chan_type, '[', ']', UNQUOTED_ESC_COMMA, 
02377                                                                                                          &local_var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
02378                                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
02379                                                 switch_goto_status(SWITCH_STATUS_GENERR, done);
02380                                         }
02381                                         
02382                                         chan_type = parsed;
02383                                 }
02384                                 
02385                                 
02386                                 /* strip leading spaces (again) */
02387                                 while (chan_type && *chan_type && *chan_type == ' ') {
02388                                         chan_type++;
02389                                 }
02390                                 
02391                                 if ((chan_data = strchr(chan_type, '/')) != 0) {
02392                                         *chan_data = '\0';
02393                                         chan_data++;
02394                                 }
02395 
02396                                 if (oglobals.session) {
02397                                         if (!switch_channel_ready(caller_channel)) {
02398                                                 status = SWITCH_STATUS_FALSE;
02399                                                 goto done;
02400                                         }
02401                                         
02402                                         if ((caller_caller_profile = oglobals.caller_profile_override)) {
02403                                                 new_profile = switch_caller_profile_dup(oglobals.pool, caller_caller_profile);
02404                                         } else {
02405                                                 new_profile = switch_caller_profile_new(oglobals.pool,
02406                                                                                                                                 NULL,
02407                                                                                                                                 NULL,
02408                                                                                                                                 cid_name_override, cid_num_override, NULL, NULL, NULL, NULL, __FILE__, NULL, chan_data);
02409                                         }
02410 
02411                                         new_profile->uuid = SWITCH_BLANK_STRING;
02412                                         new_profile->chan_name = SWITCH_BLANK_STRING;
02413                                         new_profile->destination_number = switch_core_strdup(new_profile->pool, chan_data);
02414 
02415                                         if (cid_name_override) {
02416                                                 new_profile->caller_id_name = switch_core_strdup(new_profile->pool, cid_name_override);
02417                                         }
02418                                         if (cid_num_override) {
02419                                                 new_profile->caller_id_number = switch_core_strdup(new_profile->pool, cid_num_override);
02420                                         }
02421                                 } else {
02422                                         if (oglobals.caller_profile_override) {
02423                                                 new_profile = switch_caller_profile_dup(oglobals.pool, oglobals.caller_profile_override);
02424                                                 new_profile->destination_number = switch_core_strdup(new_profile->pool, switch_str_nil(chan_data));
02425                                                 new_profile->uuid = SWITCH_BLANK_STRING;
02426                                                 new_profile->chan_name = SWITCH_BLANK_STRING;
02427                                         } else {
02428                                                 if (!cid_name_override) {
02429                                                         cid_name_override = SWITCH_DEFAULT_CLID_NAME;
02430                                                 }
02431                                                 if (!cid_num_override) {
02432                                                         cid_num_override = "0000000000";
02433                                                 }
02434 
02435                                                 new_profile = switch_caller_profile_new(oglobals.pool,
02436                                                                                                                                 NULL,
02437                                                                                                                                 NULL,
02438                                                                                                                                 cid_name_override, cid_num_override, NULL, NULL, NULL, NULL, __FILE__, NULL, chan_data);
02439                                         }
02440                                 }
02441 
02442                                 if (zstr(new_profile->destination_number)) {
02443                                         new_profile->destination_number = switch_core_strdup(new_profile->pool, "service");
02444                                 }
02445 
02446                                 new_profile->callee_id_name = switch_core_strdup(new_profile->pool, "Outbound Call");
02447                                 new_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(new_profile->pool, new_profile->destination_number));
02448 
02449                                 originate_status[i].caller_profile = NULL;
02450                                 originate_status[i].peer_channel = NULL;
02451                                 originate_status[i].peer_session = NULL;
02452                                 new_session = NULL;
02453 
02454                                 if (and_argc > 1 || or_argc > 1) {
02455                                         myflags |= SOF_FORKED_DIAL;
02456                                 } 
02457                                 
02458                                 if (var_event) {
02459                                         const char *vvar;
02460                                         if ((vvar = switch_event_get_header(var_event, "forked_dial")) && switch_true(vvar)) {
02461                                                 myflags |= SOF_FORKED_DIAL;
02462                                         }
02463                                         if ((vvar = switch_event_get_header(var_event, "no_throttle_limits")) && switch_true(vvar)) {
02464                                                 myflags |= SOF_NO_LIMITS;
02465                                         }
02466                                 }
02467 
02468                                 
02469                                 /* Valid in both {} and [] with [] taking precedence */
02470 
02471                                 /* make a special var event with mixture of the {} and the [] vars to pass down as global vars to the outgoing channel 
02472                                    so if something like the user channel does another originate our options will be passed down properly
02473                                  */
02474                                 
02475                                 switch_event_dup(&originate_var_event, var_event);
02476 
02477                                 if (local_var_event) {
02478                                         switch_event_merge(originate_var_event, local_var_event);
02479                                 }
02480 
02481                                 if ((current_variable = switch_event_get_header(originate_var_event, "origination_caller_id_number"))) {
02482                                         new_profile->caller_id_number = switch_core_strdup(new_profile->pool, current_variable);
02483                                         myflags |= SOF_NO_EFFECTIVE_CID_NUM;
02484                                 }
02485 
02486                                 if ((current_variable = switch_event_get_header(originate_var_event, "origination_caller_id_name"))) {
02487                                         new_profile->caller_id_name = switch_core_strdup(new_profile->pool, current_variable);
02488                                         myflags |= SOF_NO_EFFECTIVE_CID_NAME;
02489                                 }
02490 
02491                                 if ((current_variable = switch_event_get_header(originate_var_event, "origination_privacy"))) {
02492                                         new_profile->flags = SWITCH_CPF_NONE;
02493 
02494                                         if (switch_stristr("screen", current_variable)) {
02495                                                 switch_set_flag(new_profile, SWITCH_CPF_SCREEN);
02496                                         }
02497 
02498                                         if (switch_stristr("hide_name", current_variable)) {
02499                                                 switch_set_flag(new_profile, SWITCH_CPF_HIDE_NAME);
02500                                         }
02501 
02502                                         if (switch_stristr("hide_number", current_variable)) {
02503                                                 switch_set_flag(new_profile, SWITCH_CPF_HIDE_NUMBER);
02504                                         }
02505                                 }
02506                                 
02507                                 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "originate_early_media", oglobals.early_ok ? "true" : "false");
02508 
02509 
02510                                 if (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "push_channel_name"))) {
02511                                         char *new_name = switch_core_session_sprintf(session, "%s__B", switch_channel_get_name(caller_channel));
02512                                         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_channel_name", new_name);
02513                                         new_name = switch_core_session_sprintf(session, "_%s", switch_channel_get_name(caller_channel));
02514                                         switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "sip_h_X-FS-Channel-Name", new_name);
02515                                 }
02516                                 
02517                                 
02518                                 reason = switch_core_session_outgoing_channel(oglobals.session, originate_var_event, chan_type,
02519                                                                                                                           new_profile, &new_session, NULL, myflags, cancel_cause);
02520 
02521                                 switch_event_destroy(&originate_var_event);
02522 
02523                                 if (reason != SWITCH_CAUSE_SUCCESS) {
02524                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Cannot create outgoing channel of type [%s] cause: [%s]\n",
02525                                                                           chan_type, switch_channel_cause2str(reason));
02526                                         if (local_var_event) switch_event_destroy(&local_var_event);
02527                                         
02528                                         if (fail_on_single_reject_var) {
02529                                                 const char *cause_str = switch_channel_cause2str(reason);
02530                                                 int neg = *fail_on_single_reject_var == '!';
02531                                                 int pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
02532 
02533                                                 if (neg) {
02534                                                         pos = !pos;
02535                                                 }
02536 
02537                                                 check_reject = 0;
02538 
02539                                                 if (fail_on_single_reject == 1 || pos) {
02540                                                         force_reason = reason;
02541                                                         status = SWITCH_STATUS_FALSE;
02542                                                         goto outer_for;
02543                                                 }
02544                                         }
02545                                         continue;
02546                                 }
02547 
02548                                 if (switch_core_session_read_lock(new_session) != SWITCH_STATUS_SUCCESS) {
02549                                         status = SWITCH_STATUS_FALSE;
02550                                         if (local_var_event) switch_event_destroy(&local_var_event);
02551                                         goto done;
02552                                 }
02553 
02554                                 originate_status[i].peer_channel = switch_core_session_get_channel(new_session);
02555                                 originate_status[i].caller_profile = switch_channel_get_caller_profile(originate_status[i].peer_channel);
02556                                 originate_status[i].peer_session = new_session;
02557 
02558                                 switch_channel_set_flag(originate_status[i].peer_channel, CF_ORIGINATING);
02559                                 
02560                                 if (caller_channel) {
02561                                         switch_channel_set_variable(originate_status[i].peer_channel, "call_uuid", switch_channel_get_variable(caller_channel, "call_uuid"));
02562                                 }
02563                                 
02564 
02565                                 if ((lc = switch_event_get_header(var_event, "local_var_clobber"))) {
02566                                         local_clobber = switch_true(lc);
02567                                 }
02568 
02569                                 if (local_clobber) {
02570                                         if (var_event) {
02571                                                 switch_event_header_t *header;
02572                                                 /* install the vars from the {} params */
02573                                                 for (header = var_event->headers; header; header = header->next) {
02574                                                         switch_channel_set_variable_var_check(originate_status[i].peer_channel, header->name, header->value, oglobals.check_vars);
02575                                                 }
02576                                         }
02577                                 }
02578 
02579                                 /* copy local originate vars to the channel */
02580                                 if (local_var_event) {
02581                                         switch_event_header_t *header;
02582                                         for (header = local_var_event->headers; header; header = header->next) {
02583                                                 switch_channel_set_variable_var_check(originate_status[i].peer_channel, header->name, header->value, oglobals.check_vars);
02584                                         }
02585                                         switch_event_destroy(&local_var_event);
02586                                 }
02587 
02588                                 if (!local_clobber) {
02589                                         if (var_event) {
02590                                                 switch_event_header_t *header;
02591                                                 /* install the vars from the {} params */
02592                                                 for (header = var_event->headers; header; header = header->next) {
02593                                                         switch_channel_set_variable_var_check(originate_status[i].peer_channel, header->name, header->value, oglobals.check_vars);
02594                                                 }
02595                                         }
02596                                 }
02597 
02598                                 switch_event_create(&event, SWITCH_EVENT_CHANNEL_ORIGINATE);
02599                                 switch_assert(event);
02600                                 switch_channel_event_set_data(originate_status[i].peer_channel, event);
02601                                 switch_event_fire(&event);
02602 
02603                                 if (originate_status[i].peer_channel) {
02604                                         const char *vvar;
02605 
02606                                         if (switch_true(switch_channel_get_variable(originate_status[i].peer_channel, "leg_required"))) {
02607                                                 originate_status[i].tagged = 1;
02608                                         }
02609                                         
02610                                         if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "origination_channel_name"))) {
02611                                                 switch_channel_set_name(originate_status[i].peer_channel, vvar);
02612                                         }
02613 
02614                                         if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "origination_callee_id_name"))) {
02615                                                 switch_channel_set_profile_var(originate_status[i].peer_channel, "callee_id_name", vvar);
02616                                         }
02617 
02618                                         if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "origination_callee_id_number"))) {
02619                                                 switch_channel_set_profile_var(originate_status[i].peer_channel, "callee_id_number", vvar);
02620                                         }
02621 
02622                                         if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "leg_timeout"))) {
02623                                                 int val = atoi(vvar);
02624                                                 
02625                                                 if (val > 0) {
02626                                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg timeout to %d\n",
02627                                                                                           switch_channel_get_name(originate_status[i].peer_channel), val);
02628                                                         originate_status[i].per_channel_timelimit_sec = (uint32_t) val;
02629                                                 }
02630                                         }
02631                                         
02632                                         if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "leg_progress_timeout"))) {
02633                                                 int val = atoi(vvar);
02634                                                 if (val > 0) {
02635                                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg progress timeout to %d\n",
02636                                                                                           switch_channel_get_name(originate_status[i].peer_channel), val);
02637                                                         originate_status[i].per_channel_progress_timelimit_sec = (uint32_t) val;
02638                                                 }
02639                                         }
02640 
02641                                         if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "leg_delay_start"))) {
02642                                                 int val = atoi(vvar);
02643                                                 if (val > 0) {
02644                                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg delay start to %d\n",
02645                                                                                           switch_channel_get_name(originate_status[i].peer_channel), val);
02646                                                         originate_status[i].per_channel_delay_start = (uint32_t) val;
02647 
02648                                                         if (originate_status[i].per_channel_progress_timelimit_sec != 0) {
02649                                                                 originate_status[i].per_channel_progress_timelimit_sec += originate_status[i].per_channel_delay_start;
02650                                                         }
02651 
02652                                                         if (originate_status[i].per_channel_timelimit_sec != 0) {
02653                                                                 originate_status[i].per_channel_timelimit_sec += originate_status[i].per_channel_delay_start;
02654                                                         }
02655                                                 }
02656                                         }
02657 
02658                                         if (session) {
02659                                                 switch_channel_set_variable(originate_status[i].peer_channel, "originating_leg_uuid", switch_core_session_get_uuid(session));
02660                                         }
02661 
02662                                         switch_channel_execute_on(originate_status[i].peer_channel, SWITCH_CHANNEL_EXECUTE_ON_ORIGINATE_VARIABLE);
02663                                         switch_channel_api_on(originate_status[i].peer_channel, SWITCH_CHANNEL_API_ON_ORIGINATE_VARIABLE);
02664                                 }
02665                                 
02666                                 if (table) {
02667                                         switch_channel_add_state_handler(originate_status[i].peer_channel, table);
02668                                 }
02669                                 
02670                                 if (oglobals.monitor_early_media_ring || oglobals.monitor_early_media_fail) {
02671                                         switch_channel_set_flag(originate_status[i].peer_channel, CF_CONSUME_ON_ORIGINATE);
02672                                 }
02673 
02674                                 switch_channel_add_state_handler(originate_status[i].peer_channel, &originate_state_handlers);
02675 
02676                                 if ((flags & SOF_NOBLOCK) && originate_status[i].peer_session) {
02677                                         status = SWITCH_STATUS_SUCCESS;
02678                                         *bleg = originate_status[i].peer_session;
02679                                         *cause = SWITCH_CAUSE_SUCCESS;
02680                                         goto outer_for;
02681                                 }
02682                                 
02683                                 if (!switch_core_session_running(originate_status[i].peer_session)) {
02684                                         if (originate_status[i].per_channel_delay_start) {
02685                                                 switch_channel_set_flag(originate_status[i].peer_channel, CF_BLOCK_STATE);
02686                                         }
02687                                         switch_core_session_thread_launch(originate_status[i].peer_session);
02688                                 }
02689                         }
02690 
02691                         switch_epoch_time_now(&start);
02692 
02693                         for (;;) {
02694                                 uint32_t valid_channels = 0;
02695                                 for (i = 0; i < and_argc; i++) {
02696                                         int state;
02697                                         time_t elapsed;
02698 
02699                                         if (!originate_status[i].peer_channel) {
02700                                                 continue;
02701                                         }
02702 
02703                                         state = switch_channel_get_state(originate_status[i].peer_channel);
02704 
02705                                         if (state < CS_HANGUP) {
02706                                                 valid_channels++;
02707                                         } else {
02708                                                 continue;
02709                                         }
02710 
02711                                         if (state >= CS_ROUTING) {
02712                                                 goto endfor1;
02713                                         }
02714 
02715                                         if (caller_channel && !switch_channel_ready(caller_channel)) {
02716                                                 goto notready;
02717                                         }
02718 
02719                                         elapsed = switch_epoch_time_now(NULL) - start;
02720 
02721                                         if (elapsed > (time_t) timelimit_sec) {
02722                                                 to++;
02723                                                 oglobals.idx = IDX_TIMEOUT;
02724                                                 goto notready;
02725                                         }
02726 
02727                                         if (!oglobals.sent_ring && !oglobals.ignore_ring_ready &&
02728                                                 !oglobals.progress && (progress_timelimit_sec && elapsed > (time_t) progress_timelimit_sec)) {
02729                                                 to++;
02730                                                 oglobals.idx = IDX_TIMEOUT;
02731                                                 if (force_reason == SWITCH_CAUSE_NONE) {
02732                                                         force_reason = SWITCH_CAUSE_PROGRESS_TIMEOUT;
02733                                                 }
02734                                                 goto notready;
02735                                         }
02736 
02737                                         switch_cond_next();
02738                                 }
02739 
02740                                 check_per_channel_timeouts(&oglobals, originate_status, and_argc, start, &force_reason);
02741 
02742 
02743                                 if (valid_channels == 0) {
02744                                         status = SWITCH_STATUS_GENERR;
02745                                         goto done;
02746                                 }
02747 
02748                         }
02749 
02750                   endfor1:
02751 
02752                         if (caller_channel) {
02753                                 if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) ||
02754                                         switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) || switch_channel_test_flag(caller_channel, CF_DISABLE_RINGBACK)) {
02755                                         ringback_data = NULL;
02756                                 }
02757                         }
02758 
02759 
02760 #if 0
02761                         /* changing behaviour ignore_early_media=true must also be explicitly set for previous behaviour */
02762                         if (ringback_data) {
02763                                 oglobals.early_ok = 0;
02764                         }
02765 #endif
02766 
02767                         if (ringback_data) {
02768                                 oglobals.sending_ringback = 1;
02769                         } else {
02770                                 oglobals.ringback_ok = 0;
02771                         }
02772 
02773                         if (caller_channel) {
02774                                 soft_holding = switch_channel_get_variable(caller_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
02775                         }
02776 
02777                         while ((!caller_channel || switch_channel_ready(caller_channel) || switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) &&
02778                                    check_channel_status(&oglobals, originate_status, and_argc)) {
02779                                 time_t elapsed = switch_epoch_time_now(NULL) - start;
02780                                 
02781                                 read_packet = 0;
02782 
02783                                 if (cancel_cause && *cancel_cause > 0) {
02784                                         if (force_reason == SWITCH_CAUSE_NONE) {
02785                                                 force_reason = *cancel_cause;
02786                                         }
02787                                         oglobals.idx = IDX_CANCEL;
02788                                         goto notready;
02789                                 }
02790 
02791                                 check_per_channel_timeouts(&oglobals, originate_status, and_argc, start, &force_reason);
02792 
02793                                 if (oglobals.session) {
02794                                         switch_ivr_parse_all_events(oglobals.session);
02795                                 }
02796 
02797                                 if (!oglobals.sent_ring && !oglobals.progress && (progress_timelimit_sec && elapsed > (time_t) progress_timelimit_sec)) {
02798                                         oglobals.idx = IDX_TIMEOUT;
02799                                         if (force_reason == SWITCH_CAUSE_NONE) {
02800                                                 force_reason = SWITCH_CAUSE_PROGRESS_TIMEOUT;
02801                                         }
02802                                         goto notready;
02803                                 }
02804                                 
02805                                 if ((to = (uint8_t) (elapsed >= (time_t) timelimit_sec)) || (fail_on_single_reject && oglobals.hups)) {
02806                                         int ok = 0;
02807 
02808                                         if (fail_on_single_reject_var) {
02809                                                 if (!switch_true(fail_on_single_reject_var)) {
02810                                                         ok = 1;
02811 
02812                                                         for (i = 0; i < and_argc; i++) {
02813                                                                 switch_channel_t *pchannel;
02814                                                                 const char *cause_str;
02815                                                                 
02816                                                                 if (!originate_status[i].peer_session) {
02817                                                                         continue;
02818                                                                 }
02819                                                                 pchannel = switch_core_session_get_channel(originate_status[i].peer_session);
02820 
02821                                                                 if (switch_channel_down_nosig(pchannel)) {
02822                                                                         int neg, pos;
02823                                                                         cause_str = switch_channel_cause2str(switch_channel_get_cause(pchannel));
02824                                                                         neg = *fail_on_single_reject_var == '!';
02825                                                                         pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
02826 
02827                                                                         if (neg) {
02828                                                                                 pos = !pos;
02829                                                                         }
02830                                                                         
02831                                                                         if (pos) {
02832                                                                                 ok = 0;
02833                                                                                 break;
02834                                                                         }
02835                                                                 }
02836                                                         }
02837                                                 }
02838                                         }
02839                                         if (!ok) {
02840                                                 oglobals.idx = IDX_TIMEOUT;
02841                                                 goto notready;
02842                                         }
02843                                 }
02844 
02845                                 /* read from the channel while we wait if the audio is up on it */
02846                                 if (oglobals.session &&
02847                                         !switch_channel_test_flag(caller_channel, CF_PROXY_MODE) &&
02848                                         !switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) &&
02849                                         !switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE) &&
02850                                         (oglobals.ringback_ok
02851                                          || (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)))) {
02852 
02853                                         switch_status_t tstatus = SWITCH_STATUS_SUCCESS;
02854                                         int silence = 0;
02855 
02856                                         if (caller_channel && cancel_key) {
02857                                                 if (switch_channel_has_dtmf(caller_channel)) {
02858                                                         switch_dtmf_t dtmf = { 0, 0 };
02859                                                         if (switch_channel_dequeue_dtmf(caller_channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
02860                                                                 if (dtmf.digit == *cancel_key) {
02861                                                                         oglobals.idx = IDX_KEY_CANCEL;
02862                                                                         goto notready;
02863                                                                 }
02864                                                         }
02865                                                 }
02866                                         }
02867 
02868                                         if (switch_channel_media_ready(caller_channel)) {
02869                                                 tstatus = switch_core_session_read_frame(oglobals.session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
02870                                                 if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
02871                                                         if (soft_holding) {
02872                                                                 switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
02873                                                         }
02874 
02875                                                         if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
02876                                                                 goto do_continue;
02877                                                         }
02878                                                         break;
02879                                                 }
02880 
02881                                                 read_packet++;
02882                                         } else {
02883                                                 read_frame = NULL;
02884                                         }
02885 
02886 
02887                                         if (oglobals.ringback_ok && (oglobals.ring_ready || oglobals.instant_ringback ||
02888                                                                                                  oglobals.sending_ringback > 1 || oglobals.bridge_early_media > -1)) {
02889                                                 if (oglobals.ringback_ok == 1) {
02890                                                         switch_status_t rst;
02891                                                         
02892                                                         rst = setup_ringback(&oglobals, originate_status, and_argc, ringback_data, &ringback, &write_frame, &write_codec);
02893                                                         
02894                                                         if (oglobals.bridge_early_media > -1) {
02895                                                                 switch_threadattr_t *thd_attr = NULL;
02896                                                                 switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
02897                                                                 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
02898                                                                 early_state.oglobals = &oglobals;
02899                                                                 early_state.originate_status = originate_status;
02900                                                                 early_state.ready = 1;
02901                                                                 early_state.ringback = &ringback;
02902                                                                 switch_mutex_init(&early_state.mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
02903                                                                 switch_buffer_create_dynamic(&early_state.buffer, 1024, 1024, 0);
02904                                                                 switch_thread_create(&oglobals.ethread, thd_attr, early_thread_run, &early_state, switch_core_session_get_pool(session));
02905                                                         }
02906 
02907 
02908                                                         switch (rst) {
02909                                                         case SWITCH_STATUS_SUCCESS:
02910                                                                 oglobals.ringback_ok++;
02911                                                                 break;
02912                                                         case SWITCH_STATUS_FALSE:
02913                                                                 goto notready;
02914                                                                 break;
02915                                                         case SWITCH_STATUS_BREAK:
02916                                                                 goto done;
02917                                                                 break;
02918                                                         default:
02919                                                                 ringback_data = NULL;
02920                                                                 oglobals.ringback_ok = 0;
02921                                                                 oglobals.sending_ringback = 0;
02922                                                                 break;
02923                                                         }
02924 
02925                                                         goto do_continue;
02926                                                 }
02927 
02928                                                 if (oglobals.bridge_early_media > -1) {                                                 
02929                                                         write_frame.datalen = 0;
02930                                                         switch_mutex_lock(early_state.mutex);
02931                                                         if (ringback.asis) {
02932                                                                 uint16_t mlen;
02933                                                                 switch_size_t buflen = switch_buffer_inuse(early_state.buffer);
02934                                                                 if (buflen > sizeof(uint16_t)) {
02935                                                                         switch_buffer_peek(early_state.buffer, &mlen, sizeof(uint16_t));
02936                                                                         if (buflen >= (mlen + sizeof(uint16_t))) {
02937                                                                                 switch_buffer_toss(early_state.buffer, sizeof(uint16_t));
02938                                                                                 write_frame.datalen = switch_buffer_read(early_state.buffer, write_frame.data, mlen);
02939                                                                         }
02940                                                                 }
02941                                                         } else {
02942                                                                 if (switch_buffer_inuse(early_state.buffer) >= write_frame.codec->implementation->decoded_bytes_per_packet) {
02943                                                                         write_frame.datalen = switch_buffer_read(early_state.buffer, write_frame.data,
02944                                                                                                                                                          write_frame.codec->implementation->decoded_bytes_per_packet);
02945                                                                 }
02946                                                         }
02947                                                         switch_mutex_unlock(early_state.mutex);
02948                                                 } else if (ringback.fh) {
02949                                                         switch_size_t mlen, olen;
02950                                                         unsigned int pos = 0;
02951 
02952                                                         if (ringback.asis) {
02953                                                                 mlen = write_frame.codec->implementation->encoded_bytes_per_packet;
02954                                                         } else {
02955                                                                 mlen = write_frame.codec->implementation->samples_per_packet;
02956                                                         }
02957 
02958                                                         olen = mlen;
02959 
02960                                                         //if (ringback.fh->resampler && ringback.fh->resampler->rfactor > 1) {
02961                                                         //olen = (switch_size_t) (olen * ringback.fh->resampler->rfactor);
02962                                                         //}
02963 
02964                                                         switch_core_file_read(ringback.fh, write_frame.data, &olen);
02965 
02966                                                         if (olen == 0) {
02967                                                                 olen = mlen;
02968                                                                 ringback.fh->speed = 0;
02969                                                                 switch_core_file_seek(ringback.fh, &pos, 0, SEEK_SET);
02970                                                                 switch_core_file_read(ringback.fh, write_frame.data, &olen);
02971                                                                 if (olen == 0) {
02972                                                                         break;
02973                                                                 }
02974                                                         }
02975                                                         write_frame.datalen = (uint32_t) (ringback.asis ? olen : olen * 2);
02976                                                 } else if (ringback.audio_buffer) {
02977                                                         if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(ringback.audio_buffer,
02978                                                                                                                                                                                   write_frame.data,
02979                                                                                                                                                                                   write_frame.codec->implementation->decoded_bytes_per_packet)) <=
02980                                                                 0) {
02981 
02982                                                                 if (soft_holding) {
02983                                                                         switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
02984                                                                         goto do_continue;
02985                                                                 }
02986 
02987                                                                 break;
02988                                                         }
02989                                                 } else if (ringback.silence) {
02990                                                         silence = ringback.silence;
02991                                                 }
02992                                         } else {
02993                                                 silence = 600;
02994                                         }
02995 
02996                                         if ((ringback.fh || silence || ringback.audio_buffer || oglobals.bridge_early_media > -1) && write_frame.codec && write_frame.datalen) {
02997                                                 if (silence) {
02998                                                         write_frame.datalen = read_impl.decoded_bytes_per_packet;
02999                                                         switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, silence);
03000                                                 }
03001 
03002                                                 if (switch_core_session_write_frame(oglobals.session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
03003                                                         if (soft_holding) {
03004                                                                 switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
03005                                                         }
03006                                                         if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
03007                                                                 goto do_continue;
03008                                                         }
03009                                                         break;
03010                                                 }
03011                                         }
03012 
03013                                 } 
03014 
03015                         do_continue:
03016 
03017                                 if (!read_packet) {
03018                                         switch_cond_next();
03019                                 }
03020                         }
03021 
03022                   notready:
03023 
03024                         if (caller_channel) {
03025                                 holding = switch_channel_get_variable(caller_channel, SWITCH_HOLDING_UUID_VARIABLE);
03026                                 switch_channel_set_variable(caller_channel, SWITCH_HOLDING_UUID_VARIABLE, NULL);
03027 
03028                                 if (soft_holding && switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
03029                                         holding = soft_holding;
03030                                         soft_holding = NULL;
03031                                         switch_channel_set_variable(caller_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL);
03032                                 }
03033                         }
03034 
03035                         if (caller_channel && !switch_channel_ready(caller_channel) && !switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
03036                                 oglobals.idx = IDX_CANCEL;
03037                         }
03038 
03039                         if (oglobals.session && (ringback_data || !(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) ||
03040                                                                                                                 switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)))) {
03041                                 switch_core_session_reset(oglobals.session, SWITCH_FALSE, SWITCH_TRUE);
03042                         }
03043 
03044                         if (holding) {
03045                                 if (oglobals.idx > IDX_NADA) {
03046                                         peer_session = originate_status[oglobals.idx].peer_session;
03047                                         peer_channel = originate_status[oglobals.idx].peer_channel;
03048                                         originate_status[oglobals.idx].peer_channel = NULL;
03049                                 } else if (and_argc == 1) {
03050                                         peer_session = originate_status[0].peer_session;
03051                                         peer_channel = originate_status[0].peer_channel;
03052                                         originate_status[0].peer_channel = NULL;
03053                                 } else {
03054                                         for (i = 0; i < and_argc; i++) {
03055                                                 if (!peer_eligible(originate_status[i].peer_channel)) {
03056                                                         continue;
03057                                                 }
03058                                                 if (switch_channel_media_ready(originate_status[i].peer_channel)) {
03059                                                         peer_session = originate_status[i].peer_session;
03060                                                         peer_channel = originate_status[i].peer_channel;
03061                                                         originate_status[i].peer_channel = NULL;
03062                                                         goto end_search;
03063                                                 }
03064                                         }
03065                                         for (i = 0; i < and_argc; i++) {
03066                                                 if (!peer_eligible(originate_status[i].peer_channel)) {
03067                                                         continue;
03068                                                 }
03069                                                 if (switch_channel_up_nosig(originate_status[i].peer_channel)) {
03070                                                         peer_session = originate_status[i].peer_session;
03071                                                         peer_channel = originate_status[i].peer_channel;
03072                                                         originate_status[i].peer_channel = NULL;
03073                                                         break;
03074                                                 }
03075                                         }
03076                                 }
03077 
03078                           end_search:
03079 
03080                                 if (peer_channel && switch_channel_down_nosig(peer_channel)) {
03081                                         switch_core_session_rwunlock(peer_session);
03082                                         peer_session = NULL;
03083                                         peer_channel = NULL;
03084 
03085                                 }
03086 
03087                                 if (oglobals.idx == IDX_TIMEOUT || to || oglobals.idx == IDX_KEY_CANCEL || oglobals.idx == IDX_CANCEL ||
03088                                         (!peer_session && oglobals.idx == IDX_NADA)) {
03089                                         const char *dest = NULL;
03090                                         const char *context = NULL;
03091                                         const char *dialplan = NULL;
03092                                         switch_core_session_t *holding_session;
03093 
03094                                         if (caller_channel) {
03095                                                 if (zstr(context)) {
03096                                                         context = switch_channel_get_variable(caller_channel, "context");
03097                                                 }
03098                                                 if (zstr(dialplan)) {
03099                                                         dialplan = switch_channel_get_variable(caller_channel, "dialplan");
03100                                                 }
03101                                         }
03102 
03103                                         if (zstr(context)) {
03104                                                 context = "default";
03105                                         }
03106 
03107                                         if (zstr(context)) {
03108                                                 dialplan = "XML";
03109                                         }
03110 
03111                                         if ((holding_session = switch_core_session_locate(holding))) {
03112                                                 switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
03113                                                 switch_status_t mstatus = SWITCH_STATUS_FALSE;
03114 
03115                                                 if (caller_channel) {
03116                                                         if ((mstatus = switch_channel_caller_extension_masquerade(caller_channel, holding_channel, 0)) == SWITCH_STATUS_SUCCESS) {
03117                                                                 switch_channel_restart(holding_channel);
03118                                                         }
03119                                                 }
03120 
03121                                                 if (mstatus != SWITCH_STATUS_SUCCESS) {
03122                                                         if (peer_channel) {
03123                                                                 dest = switch_channel_get_variable(peer_channel, "destination_number");
03124                                                                 context = switch_channel_get_variable(peer_channel, "context");
03125                                                                 dialplan = switch_channel_get_variable(peer_channel, "dialplan");
03126                                                         } else if (caller_channel) {
03127                                                                 dest = switch_channel_get_variable(caller_channel, "destination_number");
03128                                                         }
03129                                                         if (dest) {
03130                                                                 switch_ivr_session_transfer(holding_session, dest, dialplan, context);
03131                                                         }
03132                                                 }
03133 
03134                                                 switch_core_session_rwunlock(holding_session);
03135                                                 holding = NULL;
03136                                                 holding_session = NULL;
03137                                         }
03138 
03139                                         if (peer_channel) {
03140                                                 switch_channel_hangup(peer_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
03141                                                 switch_core_session_rwunlock(peer_session);
03142                                         }
03143                                         if (force_reason == SWITCH_CAUSE_NONE) {
03144                                                 force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
03145                                         }
03146                                 } else if (zstr(soft_holding)) {
03147 
03148                                         if (peer_channel && switch_channel_ready(peer_channel)) {
03149                                                 switch_core_session_t *holding_session;
03150 
03151                                                 if (force_reason == SWITCH_CAUSE_NONE) {
03152                                                         force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
03153                                                 }
03154 
03155                                                 if ((holding_session = switch_core_session_locate(holding))) {
03156                                                         switch_channel_set_variable(switch_core_session_get_channel(holding_session), SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
03157                                                         switch_core_session_rwunlock(holding_session);
03158                                                 }
03159                                                 switch_channel_set_flag(peer_channel, CF_LAZY_ATTENDED_TRANSFER);
03160                                                 switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(peer_session));
03161                                                 holding = NULL;
03162                                                 oglobals.idx = IDX_NADA;
03163                                                 if (caller_channel && switch_channel_up_nosig(caller_channel) && !switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
03164                                                         switch_channel_hangup(caller_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
03165                                                 }
03166                                                 caller_channel = NULL;
03167                                                 oglobals.session = NULL;
03168                                                 session = NULL;
03169                                                 switch_core_session_rwunlock(peer_session);
03170                                         } else {
03171                                                 switch_core_session_t *holding_session;
03172 
03173                                                 if ((holding_session = switch_core_session_locate(holding))) {
03174                                                         switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
03175 
03176                                                         if (caller_channel && switch_channel_ready(caller_channel)) {
03177                                                                 switch_channel_set_variable(holding_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
03178                                                                 switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(session));
03179                                                                 holding = NULL;
03180                                                         } else {
03181                                                                 switch_channel_hangup(holding_channel, SWITCH_CAUSE_NORMAL_UNSPECIFIED);
03182                                                         }
03183                                                         switch_core_session_rwunlock(holding_session);
03184                                                 }
03185                                         }
03186                                 }
03187 
03188                                 peer_session = NULL;
03189                                 peer_channel = NULL;
03190                         }
03191 
03192                         for (i = 0; i < and_argc; i++) {
03193                                 if (!peer_eligible(originate_status[i].peer_channel)) {
03194                                         continue;
03195                                 }
03196 
03197                                 if (i != oglobals.idx) {
03198                                         holding = NULL;
03199                                         
03200                                         if (oglobals.idx == IDX_TIMEOUT || to) {
03201                                                 reason = SWITCH_CAUSE_NO_ANSWER;
03202                                         } else {
03203                                                 if (oglobals.idx == IDX_CANCEL) {
03204                                                         reason = SWITCH_CAUSE_ORIGINATOR_CANCEL;
03205                                                 } else {
03206                                                         if (and_argc > 1) {
03207                                                                 reason = SWITCH_CAUSE_LOSE_RACE;
03208                                                         } else if (!switch_channel_ready(originate_status[i].peer_channel)) {
03209                                                                 wait_for_cause(originate_status[i].peer_channel);
03210                                                                 if (switch_channel_down_nosig(originate_status[i].peer_channel)) {
03211                                                                         reason = switch_channel_get_cause(originate_status[i].peer_channel);
03212                                                                 }
03213                                                         } else {
03214                                                                 reason = SWITCH_CAUSE_NO_ANSWER;
03215                                                         }
03216                                                 }
03217                                         }
03218                                         if (switch_channel_up_nosig(originate_status[i].peer_channel)) {
03219                                                 if (caller_channel && i == 0) {
03220                                                         holding = switch_channel_get_variable(caller_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
03221                                                         switch_channel_set_variable(caller_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL);
03222                                                 }
03223 
03224                                                 if (holding && oglobals.idx != IDX_TIMEOUT && oglobals.idx != IDX_KEY_CANCEL && oglobals.idx < 0) {
03225                                                         switch_core_session_t *holding_session;
03226 
03227                                                         if ((holding_session = switch_core_session_locate(holding))) {
03228                                                                 switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
03229                                                                 
03230                                                                 switch_channel_set_variable(holding_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
03231 
03232                                                                 if (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "recording_follow_transfer"))) {
03233                                                                         switch_core_media_bug_transfer_recordings(session, originate_status[i].peer_session);
03234                                                                 }
03235 
03236                                                                 if (switch_true(switch_channel_get_variable(holding_channel, "recording_follow_transfer"))) {
03237                                                                         switch_core_media_bug_transfer_recordings(holding_session, originate_status[i].peer_session);
03238                                                                 }
03239                                                                 
03240                                                                 switch_core_session_rwunlock(holding_session);
03241                                                         }
03242                                                         switch_channel_set_flag(originate_status[i].peer_channel, CF_LAZY_ATTENDED_TRANSFER);
03243                                                         switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(originate_status[i].peer_session));
03244                                                         holding = NULL;
03245                                                 } else {
03246                                                         switch_channel_hangup(originate_status[i].peer_channel, force_reason ? force_reason : reason);
03247                                                 }
03248                                         }
03249                                 }
03250                         }
03251 
03252 
03253 
03254                         if (oglobals.idx > IDX_NADA) {
03255                                 if ((peer_session = originate_status[oglobals.idx].peer_session)) {
03256                                         peer_channel = switch_core_session_get_channel(originate_status[oglobals.idx].peer_session);
03257                                 }
03258                         } else {
03259                                 status = SWITCH_STATUS_FALSE;
03260                                 if (caller_channel && peer_channel) {
03261                                         switch_process_import(oglobals.session, peer_channel, "import", NULL);
03262                                 }
03263                                 peer_channel = NULL;
03264                                 goto done;
03265                         }
03266 
03267                         if (caller_channel) {
03268                                 if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
03269                                         switch_channel_pass_callee_id(peer_channel, caller_channel);
03270                                         if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
03271                                                 status = SWITCH_STATUS_SUCCESS;
03272                                         } else {
03273                                         status = switch_channel_answer(caller_channel);
03274                                         }
03275                                 } else if (switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
03276                                         if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
03277                                                 status = SWITCH_STATUS_SUCCESS;
03278                                         } else {
03279                                         status = switch_channel_pre_answer(caller_channel);
03280                                         }
03281                                 } else {
03282                                         status = SWITCH_STATUS_SUCCESS;
03283                                 }
03284 
03285                                 if (status != SWITCH_STATUS_SUCCESS) {
03286                                         switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(peer_channel), SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n",
03287                                                                           switch_channel_get_name(caller_channel));
03288                                         switch_channel_hangup(peer_channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
03289                                 }
03290                         }
03291 
03292                         if (switch_channel_test_flag(peer_channel, CF_ANSWERED) ||
03293                                 (oglobals.early_ok && switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) ||
03294                                 (oglobals.return_ring_ready && switch_channel_test_flag(peer_channel, CF_RING_READY))
03295                                 ) {
03296                                 *bleg = peer_session;
03297 
03298                                 if (oglobals.monitor_early_media_ring || oglobals.monitor_early_media_fail) {
03299                                         switch_ivr_stop_tone_detect_session(peer_session);
03300                                         switch_channel_set_private(peer_channel, "_oglobals_", NULL);
03301                                 }
03302 
03303                                 status = SWITCH_STATUS_SUCCESS;
03304                         } else {
03305                                 status = SWITCH_STATUS_FALSE;
03306                         }
03307 
03308                   done:
03309 
03310                         *cause = SWITCH_CAUSE_NONE;
03311 
03312                         if (caller_channel && !switch_channel_ready(caller_channel)) {
03313                                 status = SWITCH_STATUS_FALSE;
03314                         }
03315 
03316                         if (status == SWITCH_STATUS_SUCCESS) {
03317                                 if (caller_channel) {
03318                                         switch_channel_set_variable(caller_channel, "originate_disposition", "call accepted");
03319                                         if (peer_channel) {
03320                                                 switch_process_import(oglobals.session, peer_channel, "import", NULL);
03321 
03322                                                 if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
03323                                                         switch_channel_set_variable(caller_channel, "DIALSTATUS", "EARLY");
03324                                                 } else {
03325                                                         switch_channel_set_variable(caller_channel, "DIALSTATUS", "ANSWER");
03326                                                 }
03327 
03328                                         }
03329                                 }
03330                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oglobals.session), SWITCH_LOG_DEBUG, "Originate Resulted in Success: [%s]\n",
03331                                                                   switch_channel_get_name(peer_channel));
03332                                 *cause = SWITCH_CAUSE_SUCCESS;
03333 
03334                         } else {
03335                                 const char *cdr_var = NULL;
03336                                 switch_xml_t cdr = NULL;
03337                                 char *xml_text;
03338                                 char buf[128] = "", buf2[128] = "";
03339 
03340                                 if (caller_channel) {
03341                                         cdr_var = switch_channel_get_variable(caller_channel, "failed_xml_cdr_prefix");
03342                                 }
03343 
03344                                 if (peer_channel) {
03345                                         wait_for_cause(peer_channel);
03346                                         *cause = switch_channel_get_cause(peer_channel);
03347                                 } else {
03348                                         for (i = 0; i < and_argc; i++) {
03349                                                 if (!originate_status[i].peer_channel) {
03350                                                         continue;
03351                                                 }
03352                                                 *cause = switch_channel_get_cause(originate_status[i].peer_channel);
03353                                                 break;
03354                                         }
03355                                 }
03356 
03357                                 if (cdr_var) {
03358                                         for (i = 0; i < and_argc; i++) {
03359                                                 switch_channel_t *channel;
03360 
03361                                                 if (!originate_status[i].peer_session) {
03362                                                         continue;
03363                                                 }
03364 
03365                                                 channel = switch_core_session_get_channel(originate_status[i].peer_session);
03366 
03367                                                 switch_channel_wait_for_state_timeout(channel, CS_REPORTING, 5000);
03368 
03369                                                 if (!switch_channel_test_flag(channel, CF_TIMESTAMP_SET)) {
03370                                                         switch_channel_set_timestamps(channel);
03371                                                 }
03372 
03373                                                 if (switch_ivr_generate_xml_cdr(originate_status[i].peer_session, &cdr) == SWITCH_STATUS_SUCCESS) {
03374                                                         if ((xml_text = switch_xml_toxml(cdr, SWITCH_FALSE))) {
03375                                                                 switch_snprintf(buf, sizeof(buf), "%s_%d", cdr_var, ++cdr_total);
03376                                                                 switch_channel_set_variable(caller_channel, buf, xml_text);
03377                                                                 switch_safe_free(xml_text);
03378                                                         }
03379                                                         switch_xml_free(cdr);
03380                                                         cdr = NULL;
03381                                                 }
03382 
03383                                         }
03384                                         switch_snprintf(buf, sizeof(buf), "%s_total", cdr_var);
03385                                         switch_snprintf(buf2, sizeof(buf2), "%d", cdr_total ? cdr_total : 0);
03386                                         switch_channel_set_variable(caller_channel, buf, buf2);
03387                                 }
03388 
03389                                 if (caller_channel && switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
03390                                         *cause = SWITCH_CAUSE_PICKED_OFF;
03391                                 }
03392 
03393                                 if (!*cause) {
03394                                         if (reason) {
03395                                                 *cause = reason;
03396                                         } else if (caller_channel) {
03397                                                 *cause = switch_channel_get_cause(caller_channel);
03398                                         } else {
03399                                                 *cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
03400                                                 for (i = 0; i < and_argc; i++) {
03401                                                         if (!peer_eligible(originate_status[i].peer_channel)) {
03402                                                                 continue;
03403                                                         }
03404 
03405                                                         wait_for_cause(originate_status[i].peer_channel);
03406                                                         
03407                                                         if (switch_channel_down_nosig(originate_status[i].peer_channel)) {
03408                                                                 *cause = switch_channel_get_cause(originate_status[i].peer_channel);
03409                                                                 break;
03410                                                         }
03411                                                         
03412                                                 }
03413                                         }
03414                                 }
03415 
03416                                 if (*cause == SWITCH_CAUSE_SUCCESS || *cause == SWITCH_CAUSE_NONE) {
03417                                         *cause = SWITCH_CAUSE_ORIGINATOR_CANCEL;
03418                                 }
03419 
03420                                 if (oglobals.idx == IDX_CANCEL) {
03421                                         *cause = SWITCH_CAUSE_ORIGINATOR_CANCEL;
03422                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oglobals.session), SWITCH_LOG_DEBUG,
03423                                                                           "Originate Cancelled by originator termination Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
03424 
03425                                 } else if (oglobals.idx == IDX_TIMEOUT) {
03426                                         *cause = SWITCH_CAUSE_NO_ANSWER;
03427                                 } else {
03428                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oglobals.session), SWITCH_LOG_DEBUG,
03429                                                                           "Originate Resulted in Error Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
03430                                 }
03431                         }
03432 
03433                         if (caller_channel) {
03434                                 switch_channel_set_variable(caller_channel, "originate_disposition", switch_channel_cause2str(*cause));
03435 
03436                                 switch (*cause) {
03437                                 case SWITCH_CAUSE_ORIGINATOR_CANCEL:
03438                                         switch_channel_set_variable(caller_channel, "DIALSTATUS", "CANCEL");
03439                                         break;
03440                                 case SWITCH_CAUSE_USER_BUSY:
03441                                         switch_channel_set_variable(caller_channel, "DIALSTATUS", "BUSY");
03442                                         break;
03443                                 case SWITCH_CAUSE_NO_ANSWER:
03444                                         switch_channel_set_variable(caller_channel, "DIALSTATUS", "NOANSWER");
03445                                         break;
03446                                 case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
03447                                 case SWITCH_CAUSE_INVALID_PROFILE:
03448                                         switch_channel_set_variable(caller_channel, "DIALSTATUS", "INVALIDARGS");
03449                                         break;
03450                                 case SWITCH_CAUSE_CALL_REJECTED:
03451                                         switch_channel_set_variable(caller_channel, "DIALSTATUS", "DONTCALL");
03452                                         break;
03453                                 default:
03454                                         switch_channel_set_variable(caller_channel, "DIALSTATUS", switch_channel_cause2str(*cause));
03455                                         break;
03456                                 }
03457                         }
03458 
03459                         early_state.ready = 0;
03460 
03461                         if (oglobals.ethread) {
03462                                 switch_status_t st;
03463                                 switch_thread_join(&st, oglobals.ethread);
03464                         }
03465 
03466                         if (early_state.buffer) {
03467                                 switch_buffer_destroy(&early_state.buffer);
03468                         }
03469 
03470                         if (ringback.fh) {
03471                                 switch_core_file_close(ringback.fh);
03472                                 ringback.fh = NULL;
03473                         } else if (ringback.audio_buffer) {
03474                                 teletone_destroy_session(&ringback.ts);
03475                                 switch_buffer_destroy(&ringback.audio_buffer);
03476                         }
03477 
03478                         if (oglobals.session) {
03479                                 switch_core_session_reset(oglobals.session, SWITCH_FALSE, SWITCH_TRUE);
03480                         }
03481 
03482                         if (switch_core_codec_ready(&write_codec)) {
03483                                 switch_core_codec_destroy(&write_codec);
03484                         }
03485 
03486                         for (i = 0; i < and_argc; i++) {
03487                                 switch_channel_state_t state;
03488 
03489                                 if (!originate_status[i].peer_channel) {
03490                                         continue;
03491                                 }
03492 
03493                                 if (status == SWITCH_STATUS_SUCCESS) {
03494                                         switch_channel_clear_flag(originate_status[i].peer_channel, CF_ORIGINATING);
03495                                         if (bleg && *bleg && *bleg == originate_status[i].peer_session) {
03496                                                 continue;
03497                                         }
03498                                 } else if ((state = switch_channel_get_state(originate_status[i].peer_channel)) < CS_HANGUP &&
03499                                                    switch_channel_test_flag(originate_status[i].peer_channel, CF_ORIGINATING)) {
03500                                         if (!(state == CS_RESET || switch_channel_test_flag(originate_status[i].peer_channel, CF_TRANSFER) ||
03501                                                   switch_channel_test_flag(originate_status[i].peer_channel, CF_REDIRECT) ||
03502                                                   switch_channel_test_flag(originate_status[i].peer_channel, CF_BRIDGED))) {
03503                                                 if (caller_channel && switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
03504                                                         switch_channel_set_flag(originate_status[i].peer_channel, CF_INTERCEPT);
03505                                                 }
03506                                                 switch_channel_hangup(originate_status[i].peer_channel, *cause);
03507                                         }
03508                                 }
03509                                 switch_channel_clear_flag(originate_status[i].peer_channel, CF_ORIGINATING);
03510 
03511                                 switch_core_session_rwunlock(originate_status[i].peer_session);
03512                         }
03513 
03514                         if (status == SWITCH_STATUS_SUCCESS) {
03515                                 goto outer_for;
03516                         } else {
03517                                 int ok = 1;
03518 
03519                                 if (fail_on_single_reject && check_reject && !switch_true(fail_on_single_reject_var)) {
03520                                         for (i = 0; i < and_argc; i++) {
03521                                                 switch_channel_t *pchannel;
03522                                                 const char *cause_str;
03523                                                         
03524                                                 if (!originate_status[i].peer_session) {
03525                                                         continue;
03526                                                 }
03527                                                         
03528                                                 pchannel = switch_core_session_get_channel(originate_status[i].peer_session);
03529                                                 wait_for_cause(pchannel);
03530 
03531                                                 if (switch_channel_down_nosig(pchannel)) {
03532                                                         int neg, pos;
03533                                                                 
03534                                                         cause_str = switch_channel_cause2str(switch_channel_get_cause(pchannel));
03535 
03536                                                         neg = *fail_on_single_reject_var == '!';
03537                                                         pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
03538 
03539                                                         if (neg) {
03540                                                                 pos = !pos;
03541                                                         }
03542                                                                 
03543                                                                 
03544                                                         if (pos) {
03545                                                                 ok = 0;
03546                                                                 break;
03547                                                         }
03548                                                 }
03549                                         }
03550                                 }
03551                                 
03552                                 if (!ok) {
03553                                         goto outer_for;
03554                                 }
03555 
03556                                 if (to && !oglobals.continue_on_timeout) {
03557                                         goto outer_for;
03558                                 }
03559                         }
03560                 }
03561         }
03562   outer_for:
03563         switch_safe_free(loop_data);
03564         switch_safe_free(odata);
03565         switch_safe_free(oglobals.file);
03566         switch_safe_free(oglobals.error_file);
03567 
03568         if (bleg && status != SWITCH_STATUS_SUCCESS) {
03569                 *bleg = NULL;
03570         }
03571 
03572         if (*bleg) {
03573                 switch_channel_t *bchan = switch_core_session_get_channel(*bleg);
03574 
03575                 if (session && caller_channel) {
03576                         switch_caller_profile_t *cloned_profile, *peer_profile = switch_channel_get_caller_profile(switch_core_session_get_channel(*bleg));
03577 
03578                         if (peer_profile) {
03579                                 if ((cloned_profile = switch_caller_profile_clone(session, peer_profile)) != 0) {
03580                                         switch_channel_set_originatee_caller_profile(caller_channel, cloned_profile);
03581                                 }
03582                         }
03583 
03584                         switch_channel_set_variable(caller_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(*bleg));
03585                         // Now main SWITCH_SIGNAL_BOND_VARIABLE is populated, don't need this one anymore...
03586                         switch_channel_set_variable(caller_channel, "originate_signal_bond", NULL);
03587                 }
03588                 
03589 
03590                 while(switch_channel_state_change_pending(bchan)) {
03591                         switch_cond_next();
03592                 }
03593 
03594                 switch_channel_audio_sync(bchan);
03595 
03596                 if (caller_channel) {
03597                         switch_channel_audio_sync(caller_channel);
03598                 }
03599         }
03600 
03601         if (oglobals.session) {
03602                 switch_ivr_parse_all_events(oglobals.session);
03603         }
03604 
03605         if (oglobals.session && status == SWITCH_STATUS_SUCCESS) {
03606                 switch_ivr_sleep(oglobals.session, 0, SWITCH_TRUE, NULL);
03607         }
03608 
03609         if (var_event && var_event != ovars) {
03610                 switch_event_destroy(&var_event);
03611         }
03612 
03613         switch_safe_free(write_frame.data);
03614         switch_safe_free(fail_on_single_reject_var);
03615 
03616         if (caller_channel) {
03617                 switch_channel_clear_flag(caller_channel, CF_ORIGINATOR);
03618                 switch_channel_clear_flag(caller_channel, CF_XFER_ZOMBIE);
03619         }
03620 
03621         if (force_reason != SWITCH_CAUSE_NONE) {
03622                 *cause = force_reason;
03623         }
03624 
03625         switch_core_destroy_memory_pool(&oglobals.pool);
03626 
03627         return status;
03628 }

switch_status_t switch_ivr_park ( switch_core_session_t session,
switch_input_args_t args 
)

Definition at line 837 of file switch_ivr.c.

References switch_codec_implementation::actual_samples_per_second, switch_frame::buflen, CF_CONTROLLED, CF_PARK, CF_RECOVERED, CF_SERVICE, CF_UNICAST, switch_frame::codec, CS_RESET, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, switch_unicast_conninfo::read_codec, switch_unicast_conninfo::remote_addr, switch_frame::samples, switch_codec_implementation::samples_per_second, SFF_CNG, switch_unicast_conninfo::socket, SUF_NATIVE, switch_assert, SWITCH_CAUSE_NORMAL_CLEARING, switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_event_set_data(), switch_channel_get_private(), switch_channel_get_state(), switch_channel_get_variable, switch_channel_hangup, switch_channel_has_dtmf(), switch_channel_media_ready, switch_channel_pre_answer, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_set_variable, switch_channel_str2cause(), switch_channel_test_flag(), SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_cond_next(), switch_core_codec_decode(), switch_core_codec_destroy(), switch_core_codec_init, switch_core_session_dequeue_event(), switch_core_session_dequeue_private_event(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_codec(), switch_core_session_get_read_impl(), switch_core_session_read_frame(), switch_core_session_write_frame(), switch_epoch_time_now(), SWITCH_EVENT_CHANNEL_PARK, SWITCH_EVENT_CHANNEL_UNPARK, switch_event_create, switch_event_destroy(), switch_event_fire, SWITCH_FALSE, switch_generate_sln_silence(), SWITCH_INPUT_TYPE_DTMF, SWITCH_INPUT_TYPE_EVENT, SWITCH_IO_FLAG_NONE, switch_ivr_deactivate_unicast(), switch_ivr_dmachine_feed(), switch_ivr_dmachine_ping(), switch_ivr_parse_all_events(), switch_ivr_parse_event(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, SWITCH_LOG_NOTICE, switch_log_printf(), SWITCH_PARK_AFTER_BRIDGE_VARIABLE, SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, switch_safe_free, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, switch_socket_sendto(), SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_NOOP, SWITCH_STATUS_SUCCESS, switch_test_flag, switch_yield, switch_zmalloc, and unicast_thread_launch().

Referenced by switch_core_standard_on_park().

00838 {
00839         switch_status_t status = SWITCH_STATUS_SUCCESS;
00840         switch_channel_t *channel = switch_core_session_get_channel(session);
00841         switch_frame_t *read_frame = NULL;
00842         int stream_id = 0;
00843         switch_event_t *event;
00844         switch_unicast_conninfo_t *conninfo = NULL;
00845         uint32_t rate = 0;
00846         uint32_t bpf = 0;
00847         const char *to;
00848         int timeout = 0;
00849         time_t expires = 0;
00850         switch_codec_implementation_t read_impl = { 0 };
00851         switch_call_cause_t timeout_cause = SWITCH_CAUSE_NORMAL_CLEARING;
00852         switch_codec_t codec = { 0 };
00853         int sval = 0;
00854         const char *var;
00855         switch_frame_t write_frame = { 0 };
00856         unsigned char *abuf = NULL;
00857         switch_codec_implementation_t imp = { 0 };
00858 
00859         if (switch_channel_test_flag(channel, CF_RECOVERED) && switch_channel_test_flag(channel, CF_CONTROLLED)) {
00860                 switch_channel_clear_flag(channel, CF_CONTROLLED);
00861         }
00862 
00863         if (switch_channel_test_flag(channel, CF_CONTROLLED)) {
00864                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot park channels that are under control already.\n");
00865                 return SWITCH_STATUS_FALSE;
00866         }
00867 
00868         if (switch_channel_get_state(channel) == CS_RESET) {
00869                 return SWITCH_STATUS_FALSE;
00870         }
00871 
00872         if ((to = switch_channel_get_variable(channel, "park_timeout"))) {
00873                 char *cause_str;
00874 
00875                 if ((cause_str = strchr(to, ':'))) {
00876                         timeout_cause = switch_channel_str2cause(cause_str + 1);
00877                 }
00878                 
00879                 if ((timeout = atoi(to)) < 0) {
00880                         timeout = 0;
00881                 } else {
00882                         expires = switch_epoch_time_now(NULL) + timeout;
00883                 }
00884                 switch_channel_set_variable(channel, "park_timeout", NULL);
00885                 switch_channel_set_variable(channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
00886         }
00887 
00888         switch_channel_set_flag(channel, CF_CONTROLLED);
00889         switch_channel_set_flag(channel, CF_PARK);
00890 
00891         if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PARK) == SWITCH_STATUS_SUCCESS) {
00892                 switch_channel_event_set_data(channel, event);
00893                 switch_event_fire(&event);
00894         }
00895 
00896         while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_CONTROLLED) && switch_channel_test_flag(channel, CF_PARK)) {
00897 
00898                 if (!rate && switch_channel_media_ready(channel)) {
00899                         switch_core_session_get_read_impl(session, &read_impl);
00900                         rate = read_impl.actual_samples_per_second;
00901                         bpf = read_impl.decoded_bytes_per_packet;
00902 
00903                         if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
00904                                 switch_core_session_get_read_impl(session, &imp);
00905 
00906                                 if (switch_core_codec_init(&codec,
00907                                                                    "L16",
00908                                                                    NULL,
00909                                                                    imp.samples_per_second,
00910                                                                    imp.microseconds_per_packet / 1000,
00911                                                                    imp.number_of_channels,
00912                                                                    SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
00913                                                                    switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
00914                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
00915                                                                           imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
00916                                         return SWITCH_STATUS_FALSE;
00917                                 }
00918 
00919 
00920                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
00921                                                                   imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
00922 
00923                                 write_frame.codec = &codec;
00924                                 switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE);
00925                                 write_frame.data = abuf;
00926                                 write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
00927                                 write_frame.datalen = imp.decoded_bytes_per_packet;
00928                                 write_frame.samples = write_frame.datalen / sizeof(int16_t);
00929                         }
00930                 }
00931 
00932                 if (rate) {
00933                         if (switch_channel_test_flag(channel, CF_SERVICE)) {
00934                                 switch_cond_next();
00935                                 status = SWITCH_STATUS_SUCCESS;
00936                         } else {
00937                                 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, stream_id);
00938                         }
00939                 } else {
00940                         switch_yield(20000);
00941 
00942                         if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
00943                                 switch_ivr_parse_event(session, event);
00944                                 switch_event_destroy(&event);
00945                         }
00946 
00947                         status = SWITCH_STATUS_SUCCESS;
00948                 }
00949 
00950                 if (!SWITCH_READ_ACCEPTABLE(status)) {
00951                         break;
00952                 }
00953 
00954                 if (rate && write_frame.data && sval) {
00955                         switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, sval);
00956                         switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
00957                 }
00958                 
00959                 if (expires && switch_epoch_time_now(NULL) >= expires) {
00960                         switch_channel_hangup(channel, timeout_cause);
00961                         break;
00962                 }
00963 
00964                 if (switch_channel_test_flag(channel, CF_UNICAST)) {
00965                         if (!switch_channel_media_ready(channel)) {
00966                                 if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
00967                                         return SWITCH_STATUS_FALSE;
00968                                 }
00969                         }
00970 
00971                         if (!conninfo) {
00972                                 if (!(conninfo = switch_channel_get_private(channel, "unicast"))) {
00973                                         switch_channel_clear_flag(channel, CF_UNICAST);
00974                                 }
00975 
00976                                 if (conninfo) {
00977                                         unicast_thread_launch(conninfo);
00978                                 }
00979                         }
00980 
00981                         if (conninfo) {
00982                                 switch_size_t len = 0;
00983                                 uint32_t flags = 0;
00984                                 switch_byte_t decoded[SWITCH_RECOMMENDED_BUFFER_SIZE];
00985                                 uint32_t dlen = sizeof(decoded);
00986                                 switch_status_t tstatus;
00987                                 switch_byte_t *sendbuf = NULL;
00988                                 uint32_t sendlen = 0;
00989 
00990                                 switch_assert(read_frame);
00991 
00992                                 if (switch_test_flag(read_frame, SFF_CNG)) {
00993                                         sendlen = bpf;
00994                                         switch_assert(sendlen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
00995                                         memset(decoded, 255, sendlen);
00996                                         sendbuf = decoded;
00997                                         tstatus = SWITCH_STATUS_SUCCESS;
00998                                 } else {
00999                                         if (switch_test_flag(conninfo, SUF_NATIVE)) {
01000                                                 tstatus = SWITCH_STATUS_NOOP;
01001                                         } else {
01002                                                 switch_codec_t *read_codec = switch_core_session_get_read_codec(session);
01003                                                 tstatus = switch_core_codec_decode(read_codec,
01004                                                                                                                    &conninfo->read_codec,
01005                                                                                                                    read_frame->data,
01006                                                                                                                    read_frame->datalen, read_impl.actual_samples_per_second, decoded, &dlen, &rate, &flags);
01007                                         }
01008                                         switch (tstatus) {
01009                                         case SWITCH_STATUS_NOOP:
01010                                         case SWITCH_STATUS_BREAK:
01011                                                 sendbuf = read_frame->data;
01012                                                 sendlen = read_frame->datalen;
01013                                                 tstatus = SWITCH_STATUS_SUCCESS;
01014                                                 break;
01015                                         case SWITCH_STATUS_SUCCESS:
01016                                                 sendbuf = decoded;
01017                                                 sendlen = dlen;
01018                                                 tstatus = SWITCH_STATUS_SUCCESS;
01019                                                 break;
01020                                         default:
01021                                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Codec Error\n");
01022                                                 switch_ivr_deactivate_unicast(session);
01023                                                 break;
01024                                         }
01025                                 }
01026 
01027                                 if (tstatus == SWITCH_STATUS_SUCCESS) {
01028                                         len = sendlen;
01029                                         if (switch_socket_sendto(conninfo->socket, conninfo->remote_addr, 0, (void *) sendbuf, &len) != SWITCH_STATUS_SUCCESS) {
01030                                                 switch_ivr_deactivate_unicast(session);
01031                                         }
01032                                 }
01033                         }
01034                 }
01035 
01036                 switch_ivr_parse_all_events(session);
01037 
01038 
01039                 if (switch_channel_has_dtmf(channel)) {
01040                         switch_dtmf_t dtmf = { 0 };
01041                                 
01042                         if (args && !args->input_callback && !args->buf && !args->dmachine) {
01043                                 status = SWITCH_STATUS_BREAK;
01044                                 break;
01045                         }
01046                                 
01047                         switch_channel_dequeue_dtmf(channel, &dtmf);
01048 
01049                         if (args) {
01050                                 if (args->dmachine) {
01051                                         char ds[2] = {dtmf.digit, '\0'};
01052                                         if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
01053                                                 break;
01054                                         }
01055                                 } 
01056 
01057                                 if (args->input_callback) {
01058                                         if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
01059                                                 break;
01060                                         }
01061                                 }
01062                         }
01063                 }
01064 
01065                 if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
01066                         if (args && args->input_callback) {
01067                                 if ((status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
01068                                         break;
01069                                 }
01070                         } else {
01071                                 switch_channel_event_set_data(channel, event);
01072                                 switch_event_fire(&event);
01073                         }
01074                 }
01075                         
01076                 if (args && args->dmachine) {
01077                         if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
01078                                 break;
01079                         }
01080                 }
01081                 
01082 
01083         }
01084 
01085         if (write_frame.codec) {
01086                 switch_core_codec_destroy(&codec);
01087         }
01088 
01089         switch_safe_free(abuf);
01090 
01091         switch_channel_clear_flag(channel, CF_CONTROLLED);
01092         switch_channel_clear_flag(channel, CF_PARK);
01093 
01094         if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNPARK) == SWITCH_STATUS_SUCCESS) {
01095                 switch_channel_event_set_data(channel, event);
01096                 switch_event_fire(&event);
01097         }
01098 
01099         if (switch_channel_test_flag(channel, CF_UNICAST)) {
01100                 switch_ivr_deactivate_unicast(session);
01101         }
01102 
01103         return status;
01104 }

switch_status_t switch_ivr_parse_all_events ( switch_core_session_t session  ) 

Parse all commands from an event.

Parameters:
session the session on which to parse the events
Returns:
SWITCH_STATUS_SUCCESS if successful

Definition at line 808 of file switch_ivr.c.

References CF_BLOCK_BROADCAST_UNTIL_MEDIA, CF_PROXY_MODE, switch_channel_clear_flag(), switch_channel_media_up, switch_channel_test_flag(), switch_core_session_get_channel(), switch_ivr_parse_all_messages(), switch_ivr_parse_next_event(), switch_ivr_sleep(), SWITCH_STATUS_SUCCESS, and SWITCH_TRUE.

Referenced by check_channel_status(), switch_core_session_run(), switch_ivr_collect_digits_callback(), switch_ivr_collect_digits_count(), switch_ivr_gentones(), switch_ivr_multi_threaded_bridge(), switch_ivr_park(), switch_ivr_play_file(), switch_ivr_record_file(), switch_ivr_session_echo(), switch_ivr_sleep(), and switch_ivr_wait_for_answer().

00809 {
00810         int x = 0;
00811         switch_channel_t *channel;
00812 
00813         switch_ivr_parse_all_messages(session);
00814 
00815         channel = switch_core_session_get_channel(session);
00816 
00817         if (!switch_channel_test_flag(channel, CF_PROXY_MODE) && switch_channel_test_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA)) {
00818                 if (switch_channel_media_up(channel)) {
00819                         switch_channel_clear_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA);
00820                 } else {
00821                         return SWITCH_STATUS_SUCCESS;
00822                 }
00823         }
00824 
00825         while (switch_ivr_parse_next_event(session) == SWITCH_STATUS_SUCCESS) {
00826                 x++;
00827         }
00828 
00829         if (x) {
00830                 switch_ivr_sleep(session, 0, SWITCH_TRUE, NULL);
00831         }
00832 
00833         return SWITCH_STATUS_SUCCESS;
00834 }

switch_status_t switch_ivr_parse_all_messages ( switch_core_session_t session  ) 

Definition at line 754 of file switch_ivr.c.

References switch_core_session_dequeue_message(), switch_core_session_free_message(), switch_core_session_receive_message, switch_ivr_parse_all_signal_data(), switch_ivr_process_indications(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by audio_bridge_thread(), enterprise_originate_ringback_thread(), originate_on_consume_media_transmit(), signal_bridge_on_hibernate(), switch_ivr_multi_threaded_bridge(), switch_ivr_parse_all_events(), switch_ivr_play_file(), switch_ivr_speak_text_handle(), and switch_ivr_wait_for_answer().

00755 {
00756         switch_core_session_message_t *message;
00757         int i = 0;
00758 
00759         switch_ivr_parse_all_signal_data(session);
00760 
00761         while (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) {
00762                 i++;
00763 
00764                 if (switch_ivr_process_indications(session, message) == SWITCH_STATUS_SUCCESS) {
00765                         switch_core_session_free_message(&message);
00766                 } else {
00767                         switch_core_session_receive_message(session, message);
00768                         message = NULL;
00769                 }
00770         }
00771 
00772         return i ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
00773 }

switch_status_t switch_ivr_parse_all_signal_data ( switch_core_session_t session  ) 

Definition at line 776 of file switch_ivr.c.

References CF_SIGNAL_DATA, switch_core_session_message::from, switch_core_session_message::message_id, switch_core_session_message::pointer_arg, switch_channel_clear_flag(), switch_channel_set_flag, switch_channel_test_flag(), switch_core_session_dequeue_signal_data(), switch_core_session_get_channel(), switch_core_session_receive_message, SWITCH_MESSAGE_INDICATE_SIGNAL_DATA, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_channel_check_signal(), and switch_ivr_parse_all_messages().

00777 {
00778         void *data;
00779         switch_core_session_message_t msg = { 0 };
00780         int i = 0;
00781         switch_channel_t *channel = switch_core_session_get_channel(session);
00782 
00783 
00784         if (switch_channel_test_flag(channel, CF_SIGNAL_DATA)) {
00785                 return SWITCH_STATUS_FALSE;
00786         }
00787 
00788         switch_channel_set_flag(channel, CF_SIGNAL_DATA);
00789 
00790         msg.message_id = SWITCH_MESSAGE_INDICATE_SIGNAL_DATA;
00791         msg.from = __FILE__;
00792 
00793         while (switch_core_session_dequeue_signal_data(session, &data) == SWITCH_STATUS_SUCCESS) {
00794                 i++;
00795         
00796                 msg.pointer_arg = data; 
00797                 switch_core_session_receive_message(session, &msg);
00798 
00799                 data = NULL;
00800 
00801         }
00802 
00803         switch_channel_clear_flag(channel, CF_SIGNAL_DATA);
00804 
00805         return i ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
00806 }

switch_status_t switch_ivr_parse_event ( _In_ switch_core_session_t session,
_In_ switch_event_t event 
)

Parse command from an event.

Parameters:
session the session on which to parse the event
event the event to parse
Returns:
SWITCH_STATUS_SUCCESS if successful

Referenced by switch_ivr_park(), switch_ivr_parse_next_event(), and switch_ivr_speak_text_handle().

switch_status_t switch_ivr_parse_next_event ( switch_core_session_t session  ) 

Definition at line 711 of file switch_ivr.c.

References switch_core_session_dequeue_private_event(), switch_event_fire, switch_ivr_parse_event(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by audio_bridge_thread(), and switch_ivr_parse_all_events().

00712 {
00713         switch_event_t *event;
00714         switch_status_t status = SWITCH_STATUS_FALSE;
00715 
00716         if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
00717                 status = switch_ivr_parse_event(session, event);
00718                 switch_event_fire(&event);
00719         }
00720 
00721         return status;
00722 
00723 }

switch_status_t switch_ivr_pause_detect_speech ( switch_core_session_t session  ) 

Pause background Speech detection on a session.

Parameters:
session The session to pause detection on
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3672 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), switch_core_asr_pause(), switch_core_session_get_channel(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_play_and_detect_speech().

03673 {
03674         switch_channel_t *channel = switch_core_session_get_channel(session);
03675         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03676 
03677         if (sth) {
03678                 switch_core_asr_pause(sth->ah);
03679                 return SWITCH_STATUS_SUCCESS;
03680         }
03681         return SWITCH_STATUS_FALSE;
03682 }

switch_status_t switch_ivr_play_and_detect_speech ( switch_core_session_t session,
const char *  file,
const char *  mod_name,
const char *  grammar,
char **  result,
uint32_t  input_timeout,
switch_input_args_t args 
)

play a file to the session while doing speech recognition.

Parameters:
session the session to play and detect on
file the path to the file
mod_name the module name of the ASR library
grammar the grammar text, URI, or local file name
result of speech recognition, allocated from the session pool
input_timeout time to wait for input
args arguements to pass for callbacks etc
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3380 of file switch_ivr_async.c.

References play_and_detect_speech_state_t::done, switch_input_args_t::input_callback, play_and_detect_input_callback(), play_and_detect_speech_state_t::result, switch_channel_get_name(), switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_core_session_get_channel(), SWITCH_FALSE, switch_ivr_detect_speech(), switch_ivr_detect_speech_start_input_timers(), switch_ivr_dmachine_last_ping(), switch_ivr_pause_detect_speech(), switch_ivr_play_file(), switch_ivr_sleep(), SWITCH_LOG_INFO, switch_log_printf(), SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

03387 {
03388         switch_status_t status = SWITCH_STATUS_SUCCESS;
03389         int recognizing = 0;
03390         switch_input_args_t myargs = { 0 };
03391         play_and_detect_speech_state_t state = { 0, "" };
03392         switch_channel_t *channel = switch_core_session_get_channel(session);
03393 
03394         if (result == NULL) {
03395                 goto done;
03396         }
03397 
03398         if (!input_timeout) input_timeout = 5000;
03399 
03400         if (!args) {
03401                 args = &myargs;
03402         }
03403 
03404         /* start speech detection */
03405         if (switch_ivr_detect_speech(session, mod_name, grammar, grammar, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
03406                 goto done;
03407         }
03408         recognizing = 1;
03409 
03410         /* play the prompt, looking for detection result */
03411         args->input_callback = play_and_detect_input_callback;
03412         args->buf = &state;
03413         args->buflen = sizeof(state);
03414         status = switch_ivr_play_file(session, NULL, file, args);
03415 
03416         if (args->dmachine && switch_ivr_dmachine_last_ping(args->dmachine) != SWITCH_STATUS_SUCCESS) {
03417                 state.done = 1;
03418                 goto done;
03419         }
03420 
03421         if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) {
03422                 goto done;
03423         }
03424 
03425         /* wait for result if not done */
03426         if (!state.done) {
03427                 switch_ivr_detect_speech_start_input_timers(session);
03428                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) WAITING FOR RESULT\n", switch_channel_get_name(channel));
03429                 while (!state.done && switch_channel_ready(channel)) {
03430                         status = switch_ivr_sleep(session, input_timeout, SWITCH_FALSE, args);
03431                         
03432                         if (args->dmachine && switch_ivr_dmachine_last_ping(args->dmachine) != SWITCH_STATUS_SUCCESS) {
03433                                 state.done = 1;
03434                                 goto done;
03435                         }                       
03436 
03437                         if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) {
03438                                 goto done;
03439                         }
03440                 }
03441         }
03442         recognizing = !state.done;
03443 
03444 done:
03445         if (recognizing) {
03446                 switch_ivr_pause_detect_speech(session);
03447         }
03448 
03449         *result = state.result;
03450 
03451         if (!state.done) {
03452                 status = SWITCH_STATUS_FALSE;
03453         }
03454 
03455         return status;;
03456 }

switch_status_t switch_ivr_play_file ( switch_core_session_t session,
switch_file_handle_t fh,
const char *  file,
switch_input_args_t args 
)

play a file from the disk to the session

Parameters:
session the session to play the file too
fh file handle to use (NULL for builtin one)
file the path to the file
args arguements to pass for callbacks etc
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1014 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, add_playback_vars_to_event(), switch_directories::base_dir, switch_frame::buflen, CF_BREAK, CF_HOLD, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, switch_codec_implementation::encoded_bytes_per_packet, FILE_BLOCKSIZE, FILE_BUFSIZE, FILE_STARTSAMPLES, switch_codec_implementation::iananame, switch_codec::implementation, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, pool, switch_frame::rate, switch_timer::samplecount, switch_frame::samples, switch_codec_implementation::samples_per_packet, switch_codec_implementation::samples_per_second, switch_assert, SWITCH_AUDIO_COL_STR_ARTIST, SWITCH_AUDIO_COL_STR_COMMENT, SWITCH_AUDIO_COL_STR_COPYRIGHT, SWITCH_AUDIO_COL_STR_DATE, SWITCH_AUDIO_COL_STR_SOFTWARE, SWITCH_AUDIO_COL_STR_TITLE, switch_buffer_create_dynamic(), switch_buffer_destroy(), switch_buffer_inuse(), switch_buffer_read(), switch_buffer_write(), switch_buffer_zero(), switch_change_sln_volume(), switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_event_set_data(), switch_channel_get_variable, switch_channel_has_dtmf(), switch_channel_media_ready, switch_channel_pre_answer, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), switch_channel_set_variable, switch_channel_set_variable_printf(), switch_channel_test_flag(), switch_clear_flag, SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_core_codec_destroy(), switch_core_codec_init, switch_core_codec_ready(), switch_core_file_close(), switch_core_file_get_string(), switch_core_file_open, switch_core_file_read(), switch_core_file_seek(), switch_core_service_session, switch_core_session_dequeue_event(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_codec(), switch_core_session_get_read_impl(), switch_core_session_io_rwunlock(), switch_core_session_io_write_lock(), switch_core_session_read_frame(), switch_core_session_reset(), switch_core_session_sprintf(), switch_core_session_strdup, switch_core_session_write_frame(), switch_core_thread_session_end(), switch_core_timer_destroy(), switch_core_timer_init(), switch_core_timer_next(), switch_core_timer_sync(), switch_event_add_header_string(), switch_event_create, switch_event_destroy(), switch_event_fire, SWITCH_EVENT_PLAYBACK_START, SWITCH_EVENT_PLAYBACK_STOP, SWITCH_FALSE, SWITCH_FILE_CALLBACK, SWITCH_FILE_DATA_SHORT, SWITCH_FILE_FLAG_READ, SWITCH_FILE_NATIVE, SWITCH_FILE_PAUSE, SWITCH_FILE_SEEK, switch_find_end_paren(), SWITCH_GLOBAL_dirs, SWITCH_INPUT_TYPE_DTMF, SWITCH_INPUT_TYPE_EVENT, SWITCH_IO_FLAG_NONE, SWITCH_IO_FLAG_SINGLE_READ, switch_is_file_path(), switch_ivr_dmachine_feed(), switch_ivr_dmachine_ping(), switch_ivr_parse_all_events(), switch_ivr_parse_all_messages(), switch_ivr_phrase_macro, switch_ivr_sleep(), switch_ivr_speak_text(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_PATH_SEPARATOR, SWITCH_READ_ACCEPTABLE, switch_safe_free, switch_separate_string(), switch_set_flag, SWITCH_STACK_BOTTOM, SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_MORE_DATA, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, switch_str_nil, switch_swap_linear(), switch_test_flag, SWITCH_TRUE, SWITCH_URL_SEPARATOR, switch_yield, switch_zmalloc, switch_frame::timestamp, and zstr.

Referenced by collect_thread_run(), enterprise_originate_ringback_thread(), fs_ivr_play_file(), fs_ivr_play_file2(), play_and_collect(), CoreSession::streamFile(), switch_ivr_menu_execute(), switch_ivr_phrase_macro_event(), switch_ivr_play_and_detect_speech(), switch_ivr_read(), switch_ivr_soft_hold(), and switch_play_and_get_digits().

01015 {
01016         switch_channel_t *channel = switch_core_session_get_channel(session);
01017         int16_t *abuf = NULL;
01018         switch_dtmf_t dtmf = { 0 };
01019         uint32_t interval = 0, samples = 0, framelen, sample_start = 0;
01020         uint32_t ilen = 0;
01021         switch_size_t olen = 0, llen = 0;
01022         switch_frame_t write_frame = { 0 };
01023         switch_timer_t timer = { 0 };
01024         switch_codec_t codec = { 0 };
01025         switch_memory_pool_t *pool = switch_core_session_get_pool(session);
01026         char *codec_name;
01027         switch_status_t status = SWITCH_STATUS_SUCCESS;
01028         switch_file_handle_t lfh;
01029         const char *p;
01030         //char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
01031         char *ext;
01032         const char *prefix;
01033         const char *timer_name;
01034         const char *prebuf;
01035         const char *alt = NULL;
01036         const char *sleep_val;
01037         const char *play_delimiter_val;
01038         char play_delimiter = 0;
01039         int sleep_val_i = 250;
01040         int eof = 0;
01041         switch_size_t bread = 0;
01042         int l16 = 0;
01043         switch_codec_implementation_t read_impl = { 0 };
01044         char *file_dup;
01045         char *argv[128] = { 0 };
01046         int argc;
01047         int cur;
01048         int done = 0;
01049         int timeout_samples = 0;
01050         const char *var;
01051         int more_data = 0;
01052         char *playback_vars, *tmp;
01053         switch_event_t *event;
01054         uint32_t test_native = 0, last_native = 0;
01055 
01056         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
01057                 return SWITCH_STATUS_FALSE;
01058         }
01059 
01060         switch_core_session_get_read_impl(session, &read_impl);
01061 
01062         if ((var = switch_channel_get_variable(channel, "playback_timeout_sec"))) {
01063                 int tmp = atoi(var);
01064                 if (tmp > 1) {
01065                         timeout_samples = read_impl.actual_samples_per_second * tmp;
01066                 }
01067         }
01068 
01069         if ((play_delimiter_val = switch_channel_get_variable(channel, "playback_delimiter"))) {
01070                 play_delimiter = *play_delimiter_val;
01071 
01072                 if ((sleep_val = switch_channel_get_variable(channel, "playback_sleep_val"))) {
01073                         int tmp = atoi(sleep_val);
01074                         if (tmp >= 0) {
01075                                 sleep_val_i = tmp;
01076                         }
01077                 }
01078         }
01079 
01080         prefix = switch_channel_get_variable(channel, "sound_prefix");
01081         timer_name = switch_channel_get_variable(channel, "timer_name");
01082 
01083         if (zstr(file) || !switch_channel_media_ready(channel)) {
01084                 return SWITCH_STATUS_FALSE;
01085         }
01086 
01087         if (!strcasecmp(read_impl.iananame, "l16")) {
01088                 l16++;
01089         }
01090 
01091         if (play_delimiter) {
01092                 file_dup = switch_core_session_strdup(session, file);
01093                 argc = switch_separate_string(file_dup, play_delimiter, argv, (sizeof(argv) / sizeof(argv[0])));
01094         } else {
01095                 argc = 1;
01096                 argv[0] = (char *) file;
01097         }
01098 
01099         if (!fh) {
01100                 fh = &lfh;
01101                 memset(fh, 0, sizeof(lfh));
01102         }
01103         
01104         if (fh->samples > 0) {
01105                 sample_start = fh->samples;
01106                 fh->samples = 0;
01107         }
01108         
01109         for (cur = 0; switch_channel_ready(channel) && !done && cur < argc; cur++) {
01110                 file = argv[cur];
01111                 eof = 0;
01112 
01113                 if (cur) {
01114                         fh->samples = sample_start = 0;
01115                         if (sleep_val_i) {
01116                                 status = switch_ivr_sleep(session, sleep_val_i, SWITCH_FALSE, args);
01117                                 if(status != SWITCH_STATUS_SUCCESS) {
01118                                         break;
01119                                 }
01120                         }
01121                 }
01122 
01123                 status = SWITCH_STATUS_SUCCESS;
01124 
01125                 if ((alt = strchr(file, ':'))) {
01126                         char *dup;
01127 
01128                         if (!strncasecmp(file, "phrase:", 7)) {
01129                                 char *arg = NULL;
01130                                 const char *lang = switch_channel_get_variable(channel, "language");
01131                                 alt = file + 7;
01132                                 dup = switch_core_session_strdup(session, alt);
01133 
01134                                 if (dup) {
01135                                         if ((arg = strchr(dup, ':'))) {
01136                                                 *arg++ = '\0';
01137                                         }
01138                                         if ((status = switch_ivr_phrase_macro(session, dup, arg, lang, args)) != SWITCH_STATUS_SUCCESS) {
01139                                                 return status;
01140                                         }
01141                                         continue;
01142                                 } else {
01143                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
01144                                         continue;
01145                                 }
01146                         } else if (!strncasecmp(file, "say:", 4)) {
01147                                 char *engine = NULL, *voice = NULL, *text = NULL;
01148                                 alt = file + 4;
01149                                 dup = switch_core_session_strdup(session, alt);
01150                                 engine = dup;
01151 
01152                                 if (!zstr(engine)) {
01153                                         if ((voice = strchr(engine, ':'))) {
01154                                                 *voice++ = '\0';
01155                                                 if (!zstr(voice) && (text = strchr(voice, ':'))) {
01156                                                         *text++ = '\0';
01157                                                 }
01158                                         }
01159                                 }
01160 
01161                                 if (!zstr(engine) && !zstr(voice) && !zstr(text)) {
01162                                         if ((status = switch_ivr_speak_text(session, engine, voice, text, args)) != SWITCH_STATUS_SUCCESS) {
01163                                                 return status;
01164                                         }
01165                                 } else {
01166                                         text = engine;
01167                                         engine = (char *) switch_channel_get_variable(channel, "tts_engine");
01168                                         voice = (char *) switch_channel_get_variable(channel, "tts_voice");
01169                                         if (engine && text) {
01170                                                 if ((status = switch_ivr_speak_text(session, engine, voice, text, args)) != SWITCH_STATUS_SUCCESS) {
01171                                                         return status;
01172                                                 }
01173                                         } else {
01174                                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
01175                                         }
01176                                 }
01177                                 continue;
01178                         }
01179 
01180                 }
01181 
01182                 if (!prefix) {
01183                         prefix = SWITCH_GLOBAL_dirs.base_dir;
01184                 }
01185 
01186                 if (!strstr(file, SWITCH_URL_SEPARATOR)) {
01187                         if (!switch_is_file_path(file)) {
01188                                 char *tfile = NULL;
01189                                 char *e;
01190 
01191                                 if (*file == '[') {
01192                                         tfile = switch_core_session_strdup(session, file);
01193                                         if ((e = switch_find_end_paren(tfile, '[', ']'))) {
01194                                                 *e = '\0';
01195                                                 file = e + 1;
01196                                         } else {
01197                                                 tfile = NULL;
01198                                         }
01199                                 }
01200 
01201                                 file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
01202                         }
01203                         if ((ext = strrchr(file, '.'))) {
01204                                 ext++;
01205                         } else {
01206                                 ext = read_impl.iananame;
01207                                 file = switch_core_session_sprintf(session, "%s.%s", file, ext);
01208                         }
01209                 }
01210 
01211                 /* Try to parse extra parameters for this playback (parameters within {} at the end of the filename */
01212                 playback_vars = NULL;
01213                 if ((tmp = strchr(file, '{'))) {
01214                         char *tfile, *e;
01215                         
01216                         if ((tfile = switch_core_session_strdup(session, tmp))) {
01217                                 if ((e = switch_find_end_paren(tfile, '{', '}')) && *(e + 1) == '\0') {
01218                                         *tmp = '\0';
01219                                         *e = '\0';
01220                                         playback_vars = tfile+1;
01221                                 }
01222                         }
01223                 }
01224 
01225                 if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
01226                         int maybe = atoi(prebuf);
01227                         if (maybe > 0) {
01228                                 fh->prebuf = maybe;
01229                         }
01230                 }
01231 
01232 
01233                 if (!fh->prefix) {
01234                         fh->prefix = prefix;
01235                 }
01236 
01237                 if (switch_core_file_open(fh,
01238                                                                   file,
01239                                                                   read_impl.number_of_channels,
01240                                                                   read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
01241                         switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
01242                         status = SWITCH_STATUS_NOTFOUND;
01243                         continue;
01244                 }
01245 
01246                 switch_core_session_io_write_lock(session);
01247                 switch_channel_set_private(channel, "__fh", fh);
01248                 switch_core_session_io_rwunlock(session);
01249 
01250 
01251                 if (!abuf) {
01252                         switch_zmalloc(abuf, FILE_STARTSAMPLES * sizeof(*abuf));
01253                         write_frame.data = abuf;
01254                         write_frame.buflen = FILE_STARTSAMPLES;
01255                 }
01256 
01257                 if (sample_start > 0) {
01258                         uint32_t pos = 0;
01259                         switch_core_file_seek(fh, &pos, 0, SEEK_SET);
01260                         switch_core_file_seek(fh, &pos, sample_start, SEEK_CUR);
01261                         switch_clear_flag(fh, SWITCH_FILE_SEEK);
01262                 }
01263 
01264                 if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_TITLE, &p) == SWITCH_STATUS_SUCCESS) {
01265                         //title = switch_core_session_strdup(session, p);
01266                         switch_channel_set_variable(channel, "RECORD_TITLE", p);
01267                 }
01268 
01269                 if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_COPYRIGHT, &p) == SWITCH_STATUS_SUCCESS) {
01270                         //copyright = switch_core_session_strdup(session, p);
01271                         switch_channel_set_variable(channel, "RECORD_COPYRIGHT", p);
01272                 }
01273 
01274                 if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_SOFTWARE, &p) == SWITCH_STATUS_SUCCESS) {
01275                         //software = switch_core_session_strdup(session, p);
01276                         switch_channel_set_variable(channel, "RECORD_SOFTWARE", p);
01277                 }
01278 
01279                 if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_ARTIST, &p) == SWITCH_STATUS_SUCCESS) {
01280                         //artist = switch_core_session_strdup(session, p);
01281                         switch_channel_set_variable(channel, "RECORD_ARTIST", p);
01282                 }
01283 
01284                 if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_COMMENT, &p) == SWITCH_STATUS_SUCCESS) {
01285                         //comment = switch_core_session_strdup(session, p);
01286                         switch_channel_set_variable(channel, "RECORD_COMMENT", p);
01287                 }
01288 
01289                 if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_DATE, &p) == SWITCH_STATUS_SUCCESS) {
01290                         //date = switch_core_session_strdup(session, p);
01291                         switch_channel_set_variable(channel, "RECORD_DATE", p);
01292                 }
01293                 
01294                 interval = read_impl.microseconds_per_packet / 1000;
01295 
01296                 if (!fh->audio_buffer) {
01297                         switch_buffer_create_dynamic(&fh->audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0);
01298                         switch_assert(fh->audio_buffer);
01299                 }
01300 
01301                 codec_name = "L16";
01302                 
01303                 if (!switch_core_codec_ready((&codec))) {
01304                         if (switch_core_codec_init(&codec,
01305                                                                            codec_name,
01306                                                                            NULL,
01307                                                                            fh->samplerate,
01308                                                                            interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
01309                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
01310                                                                   SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
01311                                 
01312                                 
01313                         } else {
01314                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
01315                                                                   "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
01316                                 switch_core_session_io_write_lock(session);
01317                                 switch_channel_set_private(channel, "__fh", NULL);
01318                                 switch_core_session_io_rwunlock(session);
01319                                 
01320                                 switch_core_file_close(fh);
01321                                 
01322                                 switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
01323                                 status = SWITCH_STATUS_GENERR;
01324                                 continue;
01325                         }
01326                 }
01327 
01328                 test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
01329 
01330                 if (test_native) {
01331                         write_frame.codec = switch_core_session_get_read_codec(session);
01332                         samples = read_impl.samples_per_packet;
01333                         framelen = read_impl.encoded_bytes_per_packet;
01334                 } else {
01335                         write_frame.codec = &codec;
01336                         samples = codec.implementation->samples_per_packet;
01337                         framelen = codec.implementation->decoded_bytes_per_packet;
01338                 }
01339                 
01340                 last_native = test_native;
01341 
01342                 if (timer_name && !timer.samplecount) {
01343                         uint32_t len;
01344 
01345                         len = samples * 2;
01346                         if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) {
01347                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n");
01348                                 switch_core_codec_destroy(&codec);
01349                                 switch_core_session_io_write_lock(session);
01350                                 switch_channel_set_private(channel, "__fh", NULL);
01351                                 switch_core_session_io_rwunlock(session);
01352                                 switch_core_file_close(fh);
01353                                 switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
01354                                 status = SWITCH_STATUS_GENERR;
01355                                 continue;
01356                         }
01357                         switch_core_timer_sync(&timer); // Sync timer
01358                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", len, interval);
01359                 }
01360                 write_frame.rate = fh->samplerate;
01361 
01362                 if (timer_name) {
01363                         /* start a thread to absorb incoming audio */
01364                         switch_core_service_session(session);
01365                 }
01366 
01367                 ilen = samples;
01368 
01369                 if (switch_event_create(&event, SWITCH_EVENT_PLAYBACK_START) == SWITCH_STATUS_SUCCESS) {
01370                         switch_channel_event_set_data(channel, event);
01371                         switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file);
01372                         add_playback_vars_to_event(session, event, playback_vars); 
01373                         switch_event_fire(&event);
01374                 }
01375 
01376                 for (;;) {
01377                         int do_speed = 1;
01378                         int last_speed = -1;
01379                         int f;
01380                         
01381                         if (!switch_channel_ready(channel)) {
01382                                 status = SWITCH_STATUS_FALSE;
01383                                 break;
01384                         }
01385 
01386                         if ((f = switch_channel_test_flag(channel, CF_BREAK))) {
01387                                 switch_channel_clear_flag(channel, CF_BREAK);
01388                                 if (f == 2) {
01389                                         done = 1;
01390                                 }
01391                                 status = SWITCH_STATUS_BREAK;
01392                                 break;
01393                         }
01394 
01395                         switch_ivr_parse_all_events(session);
01396 
01397                         if (args) {
01398                                 /*
01399                                    dtmf handler function you can hook up to be executed when a digit is dialed during playback 
01400                                    if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
01401                                  */
01402                                 if (switch_channel_has_dtmf(channel)) {
01403                                         if (!args->input_callback && !args->buf && !args->dmachine) {
01404                                                 status = SWITCH_STATUS_BREAK;
01405                                                 done = 1;
01406                                                 break;
01407                                         }
01408                                         switch_channel_dequeue_dtmf(channel, &dtmf);
01409 
01410                                         if (args->dmachine) {
01411                                                 char ds[2] = {dtmf.digit, '\0'};
01412                                                 if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
01413                                                         break;
01414                                                 }
01415                                         } 
01416 
01417                                         if (args->input_callback) {
01418                                                 status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
01419                                         } else if (args->buf) {
01420                                                 *((char *) args->buf) = dtmf.digit;
01421                                                 status = SWITCH_STATUS_BREAK;
01422                                         }
01423                                 }
01424 
01425                                 if (args->input_callback) {
01426                                         switch_event_t *event;
01427 
01428                                         if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
01429                                                 status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
01430                                                 switch_event_destroy(&event);
01431                                         }
01432                                 }
01433 
01434                                 if (status != SWITCH_STATUS_SUCCESS) {
01435                                         done = 1;
01436                                         break;
01437                                 }
01438                         }
01439 
01440                         if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
01441                                 if (framelen > FILE_STARTSAMPLES) {
01442                                         framelen = FILE_STARTSAMPLES;
01443                                 }
01444                                 memset(abuf, 255, framelen);
01445                                 olen = ilen;
01446                                 do_speed = 0;
01447                         } else if (fh->sp_audio_buffer && (eof || (switch_buffer_inuse(fh->sp_audio_buffer) > (switch_size_t) (framelen)))) {
01448                                 if (!(bread = switch_buffer_read(fh->sp_audio_buffer, abuf, framelen))) {
01449                                         if (eof) {
01450                                                 continue;
01451                                         } else {
01452                                                 break;
01453                                         }
01454                                 }
01455 
01456                                 if (bread < framelen) {
01457                                         memset(abuf + bread, 255, framelen - bread);
01458                                 }
01459 
01460                                 olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
01461                                 do_speed = 0;
01462                         } else if (fh->audio_buffer && (eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (framelen)))) {
01463                                 if (!(bread = switch_buffer_read(fh->audio_buffer, abuf, framelen))) {
01464                                         if (eof) {
01465                                                 break;
01466                                         } else {
01467                                                 continue;
01468                                         }
01469                                 }
01470 
01471                                 fh->offset_pos += switch_test_flag(fh, SWITCH_FILE_NATIVE) ? bread : bread / 2;
01472 
01473                                 if (bread < framelen) {
01474                                         memset(abuf + bread, 255, framelen - bread);
01475                                 }
01476 
01477                                 olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
01478                         } else {
01479                                 if (eof) {
01480                                         break;
01481                                 }
01482                                 olen = FILE_STARTSAMPLES;
01483                                 if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
01484                                         olen /= 2;
01485                                 }
01486                                 if (switch_core_file_read(fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
01487                                         eof++;
01488                                         continue;
01489                                 }
01490                                 
01491                                 test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
01492 
01493                                 if (test_native != last_native) {
01494                                         if (test_native) {
01495                                                 write_frame.codec = switch_core_session_get_read_codec(session);
01496                                                 samples = read_impl.samples_per_packet;
01497                                                 framelen = read_impl.encoded_bytes_per_packet;                                          
01498                                         } else {
01499                                                 write_frame.codec = &codec;
01500                                                 samples = codec.implementation->samples_per_packet;
01501                                                 framelen = codec.implementation->decoded_bytes_per_packet;
01502                                         }
01503                                         switch_buffer_zero(fh->audio_buffer);
01504                                 }
01505 
01506                                 last_native = test_native;
01507 
01508                                 switch_buffer_write(fh->audio_buffer, abuf, switch_test_flag(fh, SWITCH_FILE_NATIVE) ? olen : olen * 2);
01509                                 olen = switch_buffer_read(fh->audio_buffer, abuf, framelen);
01510                                 fh->offset_pos += olen / 2;
01511 
01512                                 if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
01513                                         olen /= 2;
01514                                 }
01515 
01516                         }
01517 
01518                         if (done || olen <= 0) {
01519                                 break;
01520                         }
01521 
01522                         if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
01523                                 if (fh->speed > 2) {
01524                                         fh->speed = 2;
01525                                 } else if (fh->speed < -2) {
01526                                         fh->speed = -2;
01527                                 }
01528                         }
01529 
01530                         if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
01531                                 switch_buffer_zero(fh->sp_audio_buffer);
01532                         }
01533 
01534                         if (switch_test_flag(fh, SWITCH_FILE_SEEK)) {
01535                                 /* file position has changed flush the buffer */
01536                                 switch_buffer_zero(fh->audio_buffer);
01537                                 switch_clear_flag(fh, SWITCH_FILE_SEEK);
01538                         }
01539 
01540 
01541                         if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->speed && do_speed) {
01542                                 float factor = 0.25f * abs(fh->speed);
01543                                 switch_size_t newlen, supplement, step;
01544                                 short *bp = write_frame.data;
01545                                 switch_size_t wrote = 0;
01546 
01547                                 supplement = (int) (factor * olen);
01548                                 if (!supplement) {
01549                                         supplement = 1;
01550                                 }
01551                                 newlen = (fh->speed > 0) ? olen - supplement : olen + supplement;
01552 
01553                                 step = (fh->speed > 0) ? (newlen / supplement) : (olen / supplement);
01554 
01555                                 if (!fh->sp_audio_buffer) {
01556                                         switch_buffer_create_dynamic(&fh->sp_audio_buffer, 1024, 1024, 0);
01557                                 }
01558 
01559                                 while ((wrote + step) < newlen) {
01560                                         switch_buffer_write(fh->sp_audio_buffer, bp, step * 2);
01561                                         wrote += step;
01562                                         bp += step;
01563                                         if (fh->speed > 0) {
01564                                                 bp++;
01565                                         } else {
01566                                                 float f;
01567                                                 short s;
01568                                                 f = (float) (*bp + *(bp + 1) + *(bp - 1));
01569                                                 f /= 3;
01570                                                 s = (short) f;
01571                                                 switch_buffer_write(fh->sp_audio_buffer, &s, 2);
01572                                                 wrote++;
01573                                         }
01574                                 }
01575                                 if (wrote < newlen) {
01576                                         switch_size_t r = newlen - wrote;
01577                                         switch_buffer_write(fh->sp_audio_buffer, bp, r * 2);
01578                                         wrote += r;
01579                                 }
01580                                 last_speed = fh->speed;
01581                                 continue;
01582                         }
01583                         
01584                         if (olen < llen) {
01585                                 uint8_t *dp = (uint8_t *) write_frame.data;
01586                                 memset(dp + (int) olen, 255, (int) (llen - olen));
01587                                 olen = llen;
01588                         }
01589 
01590                         if (!more_data) {
01591                                 if (timer_name) {
01592                                         if (switch_core_timer_next(&timer) != SWITCH_STATUS_SUCCESS) {
01593                                                 break;
01594                                         }
01595                                 } else {                        /* time off the channel (if you must) */
01596                                         switch_frame_t *read_frame;
01597                                         switch_status_t tstatus;
01598                                         
01599                                         while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
01600                                                 switch_ivr_parse_all_messages(session);
01601                                                 switch_yield(10000);
01602                                         }
01603 
01604                                         tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_SINGLE_READ, 0);
01605 
01606                                         if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
01607                                                 break;
01608                                         }
01609 
01610                                         if (args && args->dmachine) {
01611                                                 if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
01612                                                         break;
01613                                                 }
01614                                         }
01615 
01616                                         if (args && (args->read_frame_callback)) {
01617                                                 int ok = 1;
01618                                                 switch_set_flag(fh, SWITCH_FILE_CALLBACK);
01619                                                 if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
01620                                                         ok = 0;
01621                                                 }
01622                                                 switch_clear_flag(fh, SWITCH_FILE_CALLBACK);
01623                                                 if (!ok) {
01624                                                         break;
01625                                                 }
01626                                         }
01627                                 }
01628                         }
01629 
01630                         more_data = 0;
01631                         write_frame.samples = (uint32_t) olen;
01632 
01633                         if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
01634                                 write_frame.datalen = (uint32_t) olen;
01635                         } else {
01636                                 write_frame.datalen = write_frame.samples * 2;
01637                         }
01638 
01639                         llen = olen;
01640 
01641                         if (timer_name) {
01642                                 write_frame.timestamp = timer.samplecount;
01643                         }
01644 #ifndef WIN32
01645 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
01646                         if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && l16) {
01647                                 switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);
01648                         }
01649 #endif
01650 #endif
01651                         if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->vol) {
01652                                 switch_change_sln_volume(write_frame.data, write_frame.datalen / 2, fh->vol);
01653                         }
01654 
01655                         status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
01656 
01657                         if (timeout_samples) {
01658                                 timeout_samples -= write_frame.samples;
01659                                 if (timeout_samples <= 0) {
01660                                         timeout_samples = 0;
01661                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "timeout reached playing file\n");
01662                                         status = SWITCH_STATUS_TIMEOUT;
01663                                         break;
01664                                 }
01665                         }
01666                         
01667 
01668                         if (status == SWITCH_STATUS_MORE_DATA) {
01669                                 status = SWITCH_STATUS_SUCCESS;
01670                                 more_data = 1;
01671                                 continue;
01672                         } else if (status != SWITCH_STATUS_SUCCESS) {
01673                                 done = 1;
01674                                 break;
01675                         }
01676 
01677                         if (done) {
01678                                 break;
01679                         }
01680                 }
01681 
01682                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done playing file %s\n", file);
01683 
01684                 if (read_impl.samples_per_second) {
01685                         switch_channel_set_variable_printf(channel, "playback_seconds", "%d", fh->samples_in / read_impl.samples_per_second);
01686                         switch_channel_set_variable_printf(channel, "playback_ms", "%d", fh->samples_in / (read_impl.samples_per_second / 1000));
01687                 }
01688                 switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_in);
01689 
01690                 if (switch_event_create(&event, SWITCH_EVENT_PLAYBACK_STOP) == SWITCH_STATUS_SUCCESS) {
01691                         switch_channel_event_set_data(channel, event);
01692                         switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file);
01693                         if (status == SWITCH_STATUS_BREAK) {
01694                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "break");
01695                         } else {
01696                                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "done");
01697                         }
01698                         add_playback_vars_to_event(session, event, playback_vars); 
01699                         switch_event_fire(&event);
01700                 }
01701 
01702                 switch_core_session_io_write_lock(session);
01703                 switch_channel_set_private(channel, "__fh", NULL);
01704                 switch_core_session_io_rwunlock(session);
01705 
01706                 switch_core_file_close(fh);
01707 
01708                 if (fh->audio_buffer) {
01709                         switch_buffer_destroy(&fh->audio_buffer);
01710                 }
01711 
01712                 if (fh->sp_audio_buffer) {
01713                         switch_buffer_destroy(&fh->sp_audio_buffer);
01714                 }
01715         }
01716 
01717         if (switch_core_codec_ready((&codec))) {
01718                 switch_core_codec_destroy(&codec);
01719         }
01720 
01721         if (timer.samplecount) {
01722                 /* End the audio absorbing thread */
01723                 switch_core_thread_session_end(session);
01724                 switch_core_timer_destroy(&timer);
01725         }
01726 
01727         switch_safe_free(abuf);
01728 
01729         switch_core_session_reset(session, SWITCH_FALSE, SWITCH_FALSE);
01730         return status;
01731 }

switch_status_t switch_ivr_process_indications ( switch_core_session_t session,
switch_core_session_message_t message 
)

Definition at line 725 of file switch_ivr.c.

References SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, switch_channel_answer, switch_channel_hangup, switch_channel_pre_answer, switch_channel_ring_ready, switch_core_session_get_channel(), SWITCH_MESSAGE_INDICATE_ANSWER, SWITCH_MESSAGE_INDICATE_PROGRESS, SWITCH_MESSAGE_INDICATE_RINGING, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_core_session_flush_message(), and switch_ivr_parse_all_messages().

00726 {
00727         switch_status_t status = SWITCH_STATUS_SUCCESS;
00728         switch_channel_t *channel = switch_core_session_get_channel(session);
00729                 
00730                 switch(message->message_id) {
00731                 case SWITCH_MESSAGE_INDICATE_ANSWER:
00732                         if (switch_channel_answer(channel) != SWITCH_STATUS_SUCCESS) {
00733                                 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
00734                         }
00735                         break;
00736                 case SWITCH_MESSAGE_INDICATE_PROGRESS:
00737                         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
00738                                 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
00739                         }
00740                         break;
00741                 case SWITCH_MESSAGE_INDICATE_RINGING:
00742                         if (switch_channel_ring_ready(channel) != SWITCH_STATUS_SUCCESS) {
00743                                 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
00744                         }
00745                         break;
00746                 default:
00747                 status = SWITCH_STATUS_FALSE;
00748                         break;
00749                 }
00750 
00751         return status;
00752 }

switch_status_t switch_ivr_record_file ( _In_ switch_core_session_t session,
_In_ switch_file_handle_t fh,
_In_z_ const char *  file,
_In_opt_ switch_input_args_t args,
_In_ uint32_t  limit 
)

record a file from the session to a file

Parameters:
session the session to record from
fh file handle to use
file the path to the file
args arguements to pass for callbacks etc
limit max limit to record for (0 for infinite)
Returns:
SWITCH_STATUS_SUCCESS if all is well

Referenced by fs_switch_ivr_record_file(), and CoreSession::recordFile().

switch_status_t switch_ivr_record_session ( switch_core_session_t session,
char *  file,
uint32_t  limit,
switch_file_handle_t fh 
)

Record a session to disk.

Parameters:
session the session to record
file the path to the file
limit stop recording after this amount of time (in ms, 0 = never stop)
fh file handle to use (NULL for builtin one)
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1646 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, switch_directories::base_dir, switch_codec_implementation::decoded_bytes_per_packet, eavesdrop_pvt::flags, record_helper::hangup_on_error, switch_codec_implementation::number_of_channels, record_callback(), SMBF_ANSWER_REQ, SMBF_READ_PING, SMBF_READ_STREAM, SMBF_STEREO, SMBF_STEREO_SWAP, SMBF_WRITE_STREAM, SWITCH_AUDIO_COL_STR_ARTIST, SWITCH_AUDIO_COL_STR_COMMENT, SWITCH_AUDIO_COL_STR_COPYRIGHT, SWITCH_AUDIO_COL_STR_DATE, SWITCH_AUDIO_COL_STR_SOFTWARE, SWITCH_AUDIO_COL_STR_TITLE, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, switch_channel_get_private(), switch_channel_get_variable, switch_channel_hangup, switch_channel_media_up, switch_channel_pre_answer, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), switch_channel_set_variable, switch_core_file_close(), switch_core_file_open, switch_core_file_set_string(), switch_core_media_bug_add(), switch_core_media_bug_set_pre_buffer_framecount(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_partner(), switch_core_session_get_pool(), switch_core_session_get_read_codec(), switch_core_session_get_read_impl(), switch_core_session_reset(), switch_core_session_rwunlock(), switch_core_session_sprintf(), switch_core_session_strdup, SWITCH_DEFAULT_DIR_PERMS, SWITCH_DEFAULT_FILE_BUFFER_LEN, switch_dir_make_recursive(), switch_epoch_time_now(), SWITCH_FALSE, SWITCH_FILE_DATA_SHORT, SWITCH_FILE_FLAG_WRITE, SWITCH_FILE_WRITE_APPEND, switch_find_end_paren(), SWITCH_GLOBAL_dirs, switch_is_file_path(), switch_is_valid_rate, switch_ivr_stop_record_session(), SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_PATH_SEPARATOR, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, switch_str_nil, switch_true(), and SWITCH_TRUE.

Referenced by switch_core_media_bug_transfer_recordings().

01647 {
01648         switch_channel_t *channel = switch_core_session_get_channel(session);
01649         const char *p;
01650         const char *vval;
01651         switch_media_bug_t *bug;
01652         switch_status_t status;
01653         time_t to = 0;
01654         switch_media_bug_flag_t flags = SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING;
01655         uint8_t channels;
01656         switch_codec_implementation_t read_impl = { 0 };
01657         struct record_helper *rh = NULL;
01658         int file_flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT;
01659         switch_bool_t hangup_on_error = SWITCH_FALSE;
01660         char *file_path = NULL;
01661         
01662         if ((p = switch_channel_get_variable(channel, "RECORD_HANGUP_ON_ERROR"))) {
01663                 hangup_on_error = switch_true(p);
01664         }
01665 
01666         switch_core_session_get_read_impl(session, &read_impl);
01667 
01668         if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
01669                 return SWITCH_STATUS_FALSE;
01670         }
01671 
01672         if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
01673                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not record session.  Media not enabled on channel\n");
01674                 return SWITCH_STATUS_FALSE;
01675         }
01676 
01677         channels = read_impl.number_of_channels;
01678 
01679         if ((bug = switch_channel_get_private(channel, file))) {
01680                 if (switch_true(switch_channel_get_variable(channel, "RECORD_TOGGLE_ON_REPEAT"))) {
01681                         return switch_ivr_stop_record_session(session, file);
01682                 }
01683                 
01684                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Already recording [%s]\n", file);
01685                 return SWITCH_STATUS_SUCCESS;
01686         }
01687 
01688         
01689         if ((p = switch_channel_get_variable(channel, "RECORD_CHECK_BRIDGE")) && switch_true(p)) {
01690                 switch_core_session_t *other_session;
01691                 int exist = 0;
01692                 switch_status_t rstatus = SWITCH_STATUS_SUCCESS;
01693                 
01694                 if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
01695                         switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
01696                         if ((bug = switch_channel_get_private(other_channel, file))) {
01697                                 if (switch_true(switch_channel_get_variable(other_channel, "RECORD_TOGGLE_ON_REPEAT"))) {
01698                                         rstatus = switch_ivr_stop_record_session(other_session, file);
01699                                 } else {
01700                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(other_session), SWITCH_LOG_WARNING, "Already recording [%s]\n", file);
01701                                 }
01702                                 exist = 1;
01703                         }
01704                         switch_core_session_rwunlock(other_session);
01705                 }
01706                 
01707                 if (exist) {
01708                         return rstatus;
01709                 }
01710         }
01711 
01712         if (!fh) {
01713                 if (!(fh = switch_core_session_alloc(session, sizeof(*fh)))) {
01714                         return SWITCH_STATUS_MEMERR;
01715                 }
01716         }
01717 
01718         if ((p = switch_channel_get_variable(channel, "RECORD_WRITE_ONLY")) && switch_true(p)) {
01719                 flags &= ~SMBF_READ_STREAM;
01720                 flags |= SMBF_WRITE_STREAM;
01721         }
01722 
01723         if ((p = switch_channel_get_variable(channel, "RECORD_READ_ONLY")) && switch_true(p)) {
01724                 flags &= ~SMBF_WRITE_STREAM;
01725                 flags |= SMBF_READ_STREAM;
01726         }
01727 
01728         if ((p = switch_channel_get_variable(channel, "RECORD_STEREO")) && switch_true(p)) {
01729                 flags |= SMBF_STEREO;
01730                 flags &= ~SMBF_STEREO_SWAP;
01731                 channels = 2;
01732         }
01733 
01734         if ((p = switch_channel_get_variable(channel, "RECORD_STEREO_SWAP")) && switch_true(p)) {
01735                 flags |= SMBF_STEREO;
01736                 flags |= SMBF_STEREO_SWAP;
01737                 channels = 2;
01738         }
01739 
01740         if ((p = switch_channel_get_variable(channel, "RECORD_ANSWER_REQ")) && switch_true(p)) {
01741                 flags |= SMBF_ANSWER_REQ;
01742         }
01743 
01744         if ((p = switch_channel_get_variable(channel, "RECORD_APPEND")) && switch_true(p)) {
01745                 file_flags |= SWITCH_FILE_WRITE_APPEND;
01746         }
01747 
01748 
01749         fh->samplerate = 0;
01750         if ((vval = switch_channel_get_variable(channel, "record_sample_rate"))) {
01751                 int tmp = 0;
01752 
01753                 tmp = atoi(vval);
01754 
01755                 if (switch_is_valid_rate(tmp)) {
01756                         fh->samplerate = tmp;
01757                 }
01758         }
01759 
01760         if (!fh->samplerate) {
01761                 fh->samplerate = read_impl.actual_samples_per_second;
01762         }
01763 
01764         fh->channels = channels;
01765 
01766         if ((vval = switch_channel_get_variable(channel, "enable_file_write_buffering"))) {
01767                 int tmp = atoi(vval);
01768                 
01769                 if (tmp > 0) {
01770                         fh->pre_buffer_datalen = tmp;
01771                 } else if (switch_true(vval)) {
01772                         fh->pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
01773                 }
01774 
01775         } else {
01776                 fh->pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
01777         }
01778 
01779         
01780         if (!switch_is_file_path(file)) {
01781                 char *tfile = NULL;
01782                 char *e;
01783                 const char *prefix;
01784 
01785                 prefix = switch_channel_get_variable(channel, "sound_prefix");
01786 
01787                 if (!prefix) {
01788                         prefix = SWITCH_GLOBAL_dirs.base_dir;
01789                 }
01790 
01791                 if (*file == '[') {
01792                         tfile = switch_core_session_strdup(session, file);
01793                         if ((e = switch_find_end_paren(tfile, '[', ']'))) {
01794                                 *e = '\0';
01795                                 file = e + 1;
01796                         } else {
01797                                 tfile = NULL;
01798                         }
01799                 } else {
01800                         file_path = switch_core_session_sprintf(session, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, file);
01801                 }
01802 
01803                 file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
01804         } else {
01805                 file_path = switch_core_session_strdup(session, file);
01806         }
01807 
01808         if (file_path) {
01809                 char *p;
01810                 char *path = switch_core_session_strdup(session, file_path);
01811 
01812                 if ((p = strrchr(path, *SWITCH_PATH_SEPARATOR))) {
01813                         *p = '\0';
01814                         if (switch_dir_make_recursive(path, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
01815                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error creating %s\n", path);
01816                                 return SWITCH_STATUS_GENERR;
01817                         }
01818 
01819                 } else {
01820                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error finding the folder path section in '%s'\n", path);
01821                         path = NULL;
01822                 }
01823         }
01824 
01825         if (switch_core_file_open(fh, file, channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
01826                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", file);
01827                 if (hangup_on_error) {
01828                         switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
01829                         switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
01830                 }
01831                 return SWITCH_STATUS_GENERR;
01832         }
01833 
01834         if ((p = switch_channel_get_variable(channel, "RECORD_TITLE"))) {
01835                 vval = (const char *) switch_core_session_strdup(session, p);
01836                 switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_TITLE, vval);
01837                 switch_channel_set_variable(channel, "RECORD_TITLE", NULL);
01838         }
01839 
01840         if ((p = switch_channel_get_variable(channel, "RECORD_COPYRIGHT"))) {
01841                 vval = (const char *) switch_core_session_strdup(session, p);
01842                 switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_COPYRIGHT, vval);
01843                 switch_channel_set_variable(channel, "RECORD_COPYRIGHT", NULL);
01844         }
01845 
01846         if ((p = switch_channel_get_variable(channel, "RECORD_SOFTWARE"))) {
01847                 vval = (const char *) switch_core_session_strdup(session, p);
01848                 switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_SOFTWARE, vval);
01849                 switch_channel_set_variable(channel, "RECORD_SOFTWARE", NULL);
01850         }
01851 
01852         if ((p = switch_channel_get_variable(channel, "RECORD_ARTIST"))) {
01853                 vval = (const char *) switch_core_session_strdup(session, p);
01854                 switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_ARTIST, vval);
01855                 switch_channel_set_variable(channel, "RECORD_ARTIST", NULL);
01856         }
01857 
01858         if ((p = switch_channel_get_variable(channel, "RECORD_COMMENT"))) {
01859                 vval = (const char *) switch_core_session_strdup(session, p);
01860                 switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_COMMENT, vval);
01861                 switch_channel_set_variable(channel, "RECORD_COMMENT", NULL);
01862         }
01863 
01864         if ((p = switch_channel_get_variable(channel, "RECORD_DATE"))) {
01865                 vval = (const char *) switch_core_session_strdup(session, p);
01866                 switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_DATE, vval);
01867                 switch_channel_set_variable(channel, "RECORD_DATE", NULL);
01868         }
01869 
01870         if (limit) {
01871                 to = switch_epoch_time_now(NULL) + limit;
01872         }
01873 
01874         rh = switch_core_session_alloc(session, sizeof(*rh));
01875         rh->fh = fh;
01876         rh->file = switch_core_session_strdup(session, file);
01877         rh->packet_len = read_impl.decoded_bytes_per_packet;
01878 
01879         if (file_flags & SWITCH_FILE_WRITE_APPEND) {
01880                 rh->min_sec = 3;
01881         }
01882 
01883         if ((p = switch_channel_get_variable(channel, "RECORD_MIN_SEC"))) {
01884                 int tmp = atoi(p);
01885                 if (tmp >= 0) {
01886                         rh->min_sec = tmp;
01887                 }
01888         }
01889 
01890         rh->hangup_on_error = hangup_on_error;
01891         
01892         if ((status = switch_core_media_bug_add(session, "session_record", file,
01893                                                                                         record_callback, rh, to, flags, &bug)) != SWITCH_STATUS_SUCCESS) {
01894                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error adding media bug for file %s\n", file);
01895                 switch_core_file_close(fh);
01896                 return status;
01897         }
01898 
01899         if ((p = switch_channel_get_variable(channel, "RECORD_PRE_BUFFER_FRAMES"))) {
01900                 int tmp = atoi(p);
01901                 
01902                 if (tmp > 0) {
01903                         switch_core_media_bug_set_pre_buffer_framecount(bug, tmp);
01904                 }
01905         } else {
01906                 switch_core_media_bug_set_pre_buffer_framecount(bug, 25);
01907         }
01908 
01909         switch_channel_set_private(channel, file, bug);
01910 
01911         return SWITCH_STATUS_SUCCESS;
01912 }

switch_status_t switch_ivr_resume_detect_speech ( switch_core_session_t session  ) 

Resume background Speech detection on a session.

Parameters:
session The session to resume detection on
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3684 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), switch_core_asr_resume(), switch_core_session_get_channel(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by speech_thread().

03685 {
03686         switch_channel_t *channel = switch_core_session_get_channel(session);
03687         struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
03688 
03689         if (sth) {
03690                 switch_core_asr_resume(sth->ah);
03691                 return SWITCH_STATUS_SUCCESS;
03692         }
03693         return SWITCH_STATUS_FALSE;
03694 }

uint32_t switch_ivr_schedule_broadcast ( time_t  runtime,
const char *  uuid,
const char *  path,
switch_media_flag_t  flags 
)

Signal the session to broadcast audio in the future.

Parameters:
runtime when (in epoch time) to run the broadcast
uuid the uuid of the session to broadcast on
path the path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>"
flags flags to send to the request (SMF_ECHO_BRIDGED to send the broadcast to both sides of the call)
Returns:
the id of the task

Definition at line 4009 of file switch_ivr_async.c.

References __SWITCH_FUNC__, broadcast_helper::flags, SSHF_FREE_ARG, switch_copy_string(), switch_scheduler_add_task(), switch_zmalloc, and broadcast_helper::uuid_str.

04010 {
04011         struct broadcast_helper *helper;
04012         size_t len = sizeof(*helper) + strlen(path) + 1;
04013         char *cur = NULL;
04014 
04015         switch_zmalloc(cur, len);
04016         helper = (struct broadcast_helper *) cur;
04017 
04018         cur += sizeof(*helper);
04019         switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
04020         helper->flags = flags;
04021 
04022         switch_copy_string(cur, path, len - sizeof(helper));
04023         helper->path = cur;
04024 
04025         return switch_scheduler_add_task(runtime, sch_broadcast_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
04026 }

uint32_t switch_ivr_schedule_hangup ( time_t  runtime,
const char *  uuid,
switch_call_cause_t  cause,
switch_bool_t  bleg 
)

Hangup an existing session in the future.

Parameters:
runtime the time (int epoch seconds) to transfer the call
uuid the uuid of the session to hangup
cause the hanup cause code
bleg hangup up the B-Leg if possible
Returns:
the id of the task

Definition at line 3912 of file switch_ivr_async.c.

References __SWITCH_FUNC__, hangup_helper::bleg, hangup_helper::cause, SSHF_FREE_ARG, switch_copy_string(), switch_scheduler_add_task(), switch_zmalloc, and hangup_helper::uuid_str.

03913 {
03914         struct hangup_helper *helper;
03915         size_t len = sizeof(*helper);
03916 
03917         switch_zmalloc(helper, len);
03918 
03919         switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
03920         helper->cause = cause;
03921         helper->bleg = bleg;
03922 
03923         return switch_scheduler_add_task(runtime, sch_hangup_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
03924 }

uint32_t switch_ivr_schedule_transfer ( time_t  runtime,
const char *  uuid,
char *  extension,
char *  dialplan,
char *  context 
)

Transfer an existing session to another location in the future.

Parameters:
runtime the time (int epoch seconds) to transfer the call
uuid the uuid of the session to transfer
extension the new extension
dialplan the new dialplan (OPTIONAL, may be NULL)
context the new context (OPTIONAL, may be NULL)
Returns:
the id of the task

Definition at line 3949 of file switch_ivr_async.c.

References __SWITCH_FUNC__, transfer_helper::context, transfer_helper::dialplan, transfer_helper::extension, SSHF_FREE_ARG, switch_copy_string(), switch_scheduler_add_task(), switch_zmalloc, and transfer_helper::uuid_str.

03950 {
03951         struct transfer_helper *helper;
03952         size_t len = sizeof(*helper);
03953         char *cur = NULL;
03954 
03955         if (extension) {
03956                 len += strlen(extension) + 1;
03957         }
03958 
03959         if (dialplan) {
03960                 len += strlen(dialplan) + 1;
03961         }
03962 
03963         if (context) {
03964                 len += strlen(context) + 1;
03965         }
03966 
03967         switch_zmalloc(cur, len);
03968         helper = (struct transfer_helper *) cur;
03969 
03970         switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
03971 
03972         cur += sizeof(*helper);
03973 
03974         if (extension) {
03975                 switch_copy_string(cur, extension, strlen(extension) + 1);
03976                 helper->extension = cur;
03977                 cur += strlen(helper->extension) + 1;
03978         }
03979 
03980         if (dialplan) {
03981                 switch_copy_string(cur, dialplan, strlen(dialplan) + 1);
03982                 helper->dialplan = cur;
03983                 cur += strlen(helper->dialplan) + 1;
03984         }
03985 
03986         if (context) {
03987                 switch_copy_string(cur, context, strlen(context) + 1);
03988                 helper->context = cur;
03989         }
03990 
03991         return switch_scheduler_add_task(runtime, sch_transfer_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
03992 }

switch_status_t switch_ivr_session_audio ( switch_core_session_t session,
const char *  cmd,
const char *  direction,
int  level 
)

Definition at line 2278 of file switch_ivr_async.c.

References switch_session_audio_t::read_level, switch_session_audio_t::read_mute, session_audio_callback(), SMBF_NO_PAUSE, SMBF_READ_REPLACE, SMBF_WRITE_REPLACE, switch_channel_get_private(), switch_channel_pre_answer, switch_channel_set_private(), switch_core_media_bug_add(), switch_core_media_bug_get_user_data(), switch_core_media_bug_set_flag(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_read_impl(), SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, switch_session_audio_t::write_level, and switch_session_audio_t::write_mute.

02279 {
02280         switch_channel_t *channel = switch_core_session_get_channel(session);
02281         switch_media_bug_t *bug;
02282         switch_status_t status;
02283         switch_session_audio_t *pvt;
02284         switch_codec_implementation_t read_impl = { 0 };
02285         int existing = 0, c_read = 0, c_write = 0, flags = SMBF_NO_PAUSE;
02286 
02287         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
02288                 return SWITCH_STATUS_FALSE;
02289         }
02290 
02291         switch_core_session_get_read_impl(session, &read_impl);
02292 
02293 
02294         if ((bug = switch_channel_get_private(channel, "__audio"))) {
02295                 pvt = switch_core_media_bug_get_user_data(bug);
02296                 existing = 1;
02297         } else {
02298                 if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
02299                         return SWITCH_STATUS_MEMERR;
02300                 }
02301 
02302                 pvt->session = session;
02303         }
02304 
02305 
02306         if (!strcasecmp(direction, "write")) {
02307                 flags = SMBF_WRITE_REPLACE;
02308                 c_write = 1;
02309         } else if (!strcasecmp(direction, "read")) {
02310                 flags = SMBF_READ_REPLACE;
02311                 c_read = 1;
02312         } else if (!strcasecmp(direction, "both")) {
02313                 flags = SMBF_READ_REPLACE | SMBF_WRITE_REPLACE;
02314                 c_read = c_write = 1;
02315         }
02316 
02317 
02318         if (!strcasecmp(cmd, "mute")) {
02319                 if (c_read) {
02320                         pvt->read_mute = level;
02321                         pvt->read_level = 0;
02322                 }
02323                 if (c_write) {
02324                         pvt->write_mute = level;
02325                         pvt->write_level = 0;
02326                 }
02327         } else if (!strcasecmp(cmd, "level")) {
02328                 if (level < 5 && level > -5) {
02329                         if (c_read) {
02330                                 pvt->read_level = level;
02331                         }
02332                         if (c_write) {
02333                                 pvt->write_level = level;
02334                         }
02335                 }
02336         }
02337 
02338         if (existing) {
02339                 switch_core_media_bug_set_flag(bug, flags);
02340         } else {
02341                 if ((status = switch_core_media_bug_add(session, "audio", cmd,
02342                                                                                                 session_audio_callback, pvt, 0, flags, &bug)) != SWITCH_STATUS_SUCCESS) {
02343                         return status;
02344                 }
02345 
02346                 switch_channel_set_private(channel, "__audio", bug);
02347         }
02348 
02349 
02350         return SWITCH_STATUS_SUCCESS;
02351 }

void switch_ivr_session_echo ( switch_core_session_t session,
switch_input_args_t args 
)

Parameters:
session the session to act on

Definition at line 599 of file switch_ivr_async.c.

References CF_BREAK, CF_VIDEO, switch_dtmf_t::digit, SFF_CNG, switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_has_dtmf(), switch_channel_pre_answer, switch_channel_ready, switch_channel_test_flag(), switch_cond_next(), switch_core_session_dequeue_event(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_read_frame(), switch_core_session_read_video_frame(), switch_core_session_write_frame(), switch_core_session_write_video_frame(), switch_event_destroy(), SWITCH_FALSE, SWITCH_INPUT_TYPE_DTMF, SWITCH_INPUT_TYPE_EVENT, SWITCH_IO_FLAG_NONE, switch_ivr_parse_all_events(), SWITCH_READ_ACCEPTABLE, SWITCH_STATUS_BREAK, SWITCH_STATUS_SUCCESS, switch_test_flag, switch_thread_create(), SWITCH_THREAD_STACKSIZE, switch_threadattr_create(), switch_threadattr_detach_set(), and switch_threadattr_stacksize_set().

00600 {
00601         switch_status_t status;
00602         switch_frame_t *read_frame;
00603         switch_channel_t *channel = switch_core_session_get_channel(session);
00604 #ifdef SWITCH_VIDEO_IN_THREADS
00605         struct echo_helper eh = { 0 };
00606         switch_thread_t *thread;
00607         switch_threadattr_t *thd_attr = NULL;
00608 #endif
00609 
00610         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
00611                 return;
00612         }
00613 #ifdef SWITCH_VIDEO_IN_THREADS
00614         if (switch_channel_test_flag(channel, CF_VIDEO)) {
00615                 eh.session = session;
00616                 switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
00617                 switch_threadattr_detach_set(thd_attr, 1);
00618                 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
00619                 switch_thread_create(&thread, thd_attr, echo_video_thread, &eh, switch_core_session_get_pool(session));
00620         }
00621 #endif
00622 
00623         while (switch_channel_ready(channel)) {
00624                 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
00625                 if (!SWITCH_READ_ACCEPTABLE(status)) {
00626                         break;
00627                 }
00628 
00629                 switch_ivr_parse_all_events(session);
00630 
00631                 if (args && (args->input_callback || args->buf || args->buflen)) {
00632                         switch_dtmf_t dtmf = {0};
00633 
00634                         /*
00635                            dtmf handler function you can hook up to be executed when a digit is dialed during playback 
00636                            if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
00637                          */
00638                         if (switch_channel_has_dtmf(channel)) {
00639                                 if (!args->input_callback && !args->buf) {
00640                                         status = SWITCH_STATUS_BREAK;
00641                                         break;
00642                                 }
00643                                 switch_channel_dequeue_dtmf(channel, &dtmf);
00644                                 if (args->input_callback) {
00645                                         status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
00646                                 } else {
00647                                         *((char *) args->buf) = dtmf.digit;
00648                                         status = SWITCH_STATUS_BREAK;
00649                                 }
00650                         }
00651 
00652                         if (args->input_callback) {
00653                                 switch_event_t *event = NULL;
00654 
00655                                 if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
00656                                         status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
00657                                         switch_event_destroy(&event);
00658                                 }
00659                         }
00660 
00661                         if (status != SWITCH_STATUS_SUCCESS) {
00662                                 break;
00663                         }
00664                 }
00665 
00666 
00667                 switch_core_session_write_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
00668 
00669 #ifndef SWITCH_VIDEO_IN_THREADS
00670                 status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
00671 
00672                 if (!SWITCH_READ_ACCEPTABLE(status)) {
00673                         break;
00674                 }
00675 
00676                 if (switch_test_flag(read_frame, SFF_CNG)) {
00677                         continue;
00678                 }
00679 
00680                 switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
00681 #endif
00682 
00683                 if (switch_channel_test_flag(channel, CF_BREAK)) {
00684                         switch_channel_clear_flag(channel, CF_BREAK);
00685                         break;
00686                 }
00687         }
00688 
00689 #ifdef SWITCH_VIDEO_IN_THREADS
00690         if (eh.up) {
00691                 while (eh.up) {
00692                         switch_cond_next();
00693                 }
00694         }
00695 #endif
00696 
00697 }

switch_status_t switch_ivr_session_transfer ( _In_ switch_core_session_t session,
const char *  extension,
const char *  dialplan,
const char *  context 
)

Transfer an existing session to another location.

Parameters:
session the session to transfer
extension the new extension
dialplan the new dialplan (OPTIONAL, may be NULL)
context the new context (OPTIONAL, may be NULL)

Referenced by fs_switch_ivr_session_transfer(), switch_ivr_multi_threaded_bridge(), switch_play_and_get_digits(), SWITCH_STANDARD_SCHED_FUNC(), CoreSession::transfer(), transfer_after_bridge(), and uuid_bridge_on_soft_execute().

switch_status_t switch_ivr_set_param_detect_speech ( switch_core_session_t session,
const char *  name,
const char *  val 
)

Definition at line 3712 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_get_private(), switch_core_asr_text_param(), switch_core_session_get_channel(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

03713 {
03714         struct speech_thread_handle *sth = switch_channel_get_private(switch_core_session_get_channel(session), SWITCH_SPEECH_KEY);
03715         switch_status_t status = SWITCH_STATUS_FALSE;
03716 
03717         if (sth && sth->ah && name && val) {
03718                 switch_core_asr_text_param(sth->ah, (char *) name, val);
03719                 status = SWITCH_STATUS_SUCCESS;
03720         }
03721 
03722         return status;
03723 }

int switch_ivr_set_xml_chan_vars ( switch_xml_t  xml,
switch_channel_t channel,
int  off 
)

Definition at line 2150 of file switch_ivr.c.

References switch_event_header::array, switch_event_header::idx, switch_event_header::name, switch_event_header::next, switch_channel_variable_first(), switch_ivr_set_xml_chan_var(), and switch_event_header::value.

Referenced by switch_ivr_generate_xml_cdr().

02151 {
02152 
02153         switch_event_header_t *hi = switch_channel_variable_first(channel);
02154 
02155         if (!hi)
02156                 return off;
02157 
02158         for (; hi; hi = hi->next) {
02159                 if (hi->idx) {
02160                         int i;
02161                         
02162                         for (i = 0; i < hi->idx; i++) {
02163                                 off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->array[i], off);
02164                         }
02165                 } else {
02166                         off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->value, off);
02167                 }
02168         }
02169         switch_channel_variable_last(channel);
02170 
02171         return off;
02172 }

int switch_ivr_set_xml_profile_data ( switch_xml_t  xml,
switch_caller_profile_t caller_profile,
int  off 
)

Definition at line 2025 of file switch_ivr.c.

References switch_xml_add_child_d, and switch_xml_set_txt_d.

Referenced by switch_ivr_generate_xml_cdr().

02026 {
02027         switch_xml_t param;
02028 
02029         if (!(param = switch_xml_add_child_d(xml, "username", off++))) {
02030                 return -1;
02031         }
02032         switch_xml_set_txt_d(param, caller_profile->username);
02033 
02034         if (!(param = switch_xml_add_child_d(xml, "dialplan", off++))) {
02035                 return -1;
02036         }
02037         switch_xml_set_txt_d(param, caller_profile->dialplan);
02038 
02039         if (!(param = switch_xml_add_child_d(xml, "caller_id_name", off++))) {
02040                 return -1;
02041         }
02042         switch_xml_set_txt_d(param, caller_profile->caller_id_name);
02043 
02044         if (!(param = switch_xml_add_child_d(xml, "caller_id_number", off++))) {
02045                 return -1;
02046         }
02047         switch_xml_set_txt_d(param, caller_profile->caller_id_number);
02048 
02049         if (!(param = switch_xml_add_child_d(xml, "callee_id_name", off++))) {
02050                 return -1;
02051         }
02052         switch_xml_set_txt_d(param, caller_profile->callee_id_name);
02053 
02054         if (!(param = switch_xml_add_child_d(xml, "callee_id_number", off++))) {
02055                 return -1;
02056         }
02057         switch_xml_set_txt_d(param, caller_profile->callee_id_number);
02058 
02059         if (!(param = switch_xml_add_child_d(xml, "ani", off++))) {
02060                 return -1;
02061         }
02062         switch_xml_set_txt_d(param, caller_profile->ani);
02063 
02064         if (!(param = switch_xml_add_child_d(xml, "aniii", off++))) {
02065                 return -1;
02066         }
02067         switch_xml_set_txt_d(param, caller_profile->aniii);
02068 
02069 
02070         if (!(param = switch_xml_add_child_d(xml, "network_addr", off++))) {
02071                 return -1;
02072         }
02073         switch_xml_set_txt_d(param, caller_profile->network_addr);
02074 
02075         if (!(param = switch_xml_add_child_d(xml, "rdnis", off++))) {
02076                 return -1;
02077         }
02078         switch_xml_set_txt_d(param, caller_profile->rdnis);
02079 
02080         if (!(param = switch_xml_add_child_d(xml, "destination_number", off++))) {
02081                 return -1;
02082         }
02083         switch_xml_set_txt_d(param, caller_profile->destination_number);
02084 
02085         if (!(param = switch_xml_add_child_d(xml, "uuid", off++))) {
02086                 return -1;
02087         }
02088         switch_xml_set_txt_d(param, caller_profile->uuid);
02089 
02090         if (!(param = switch_xml_add_child_d(xml, "source", off++))) {
02091                 return -1;
02092         }
02093         switch_xml_set_txt_d(param, caller_profile->source);
02094 
02095         if (caller_profile->transfer_source) {
02096                 if (!(param = switch_xml_add_child_d(xml, "transfer_source", off++))) {
02097                         return -1;
02098                 }
02099                 switch_xml_set_txt_d(param, caller_profile->transfer_source);
02100         }
02101 
02102         if (!(param = switch_xml_add_child_d(xml, "context", off++))) {
02103                 return -1;
02104         }
02105         switch_xml_set_txt_d(param, caller_profile->context);
02106 
02107         if (!(param = switch_xml_add_child_d(xml, "chan_name", off++))) {
02108                 return -1;
02109         }
02110         switch_xml_set_txt_d(param, caller_profile->chan_name);
02111 
02112 
02113         if (caller_profile->soft) {
02114                 profile_node_t *pn;
02115 
02116                 for (pn = caller_profile->soft; pn; pn = pn->next) {
02117 
02118                         if (!(param = switch_xml_add_child_d(xml, pn->var, off++))) {
02119                                 return -1;
02120                         }
02121                         switch_xml_set_txt_d(param, pn->val);
02122                 }
02123 
02124         }
02125 
02126 
02127         return off;
02128 }

switch_status_t switch_ivr_signal_bridge ( switch_core_session_t session,
switch_core_session_t peer_session 
)

Bridge Signalling from one session to another.

Parameters:
session one session
peer_session the other session
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1108 of file switch_ivr_bridge.c.

References CF_BRIDGE_ORIGINATOR, CF_BRIDGED, CF_RESET, CF_SIGNAL_BRIDGE_TTL, CF_TRANSFER, check_bridge_export(), CS_HIBERNATE, signal_bridge_state_handlers, SWITCH_CAUSE_ORIGINATOR_CANCEL, switch_channel_add_state_handler(), switch_channel_clear_flag(), switch_channel_clear_state_handler(), switch_channel_down_nosig, switch_channel_event_set_data(), switch_channel_get_cause(), switch_channel_hangup, switch_channel_set_bridge_time(), switch_channel_set_flag, switch_channel_set_flag_recursive(), switch_channel_set_state, switch_channel_set_state_flag(), switch_channel_set_variable, switch_channel_test_flag(), switch_channel_up_nosig, switch_core_session_get_channel(), switch_core_session_get_uuid(), switch_event_add_header_string(), SWITCH_EVENT_CHANNEL_EXECUTE, switch_event_create, switch_event_fire, switch_ivr_bridge_display(), SWITCH_SIGNAL_BRIDGE_VARIABLE, SWITCH_STACK_BOTTOM, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_multi_threaded_bridge(), and switch_ivr_nomedia().

01109 {
01110         switch_channel_t *caller_channel = switch_core_session_get_channel(session);
01111         switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
01112         switch_event_t *event;
01113 
01114         if (switch_channel_down_nosig(peer_channel)) {
01115                 switch_channel_hangup(caller_channel, switch_channel_get_cause(peer_channel));
01116                 return SWITCH_STATUS_FALSE;
01117         }
01118 
01119         if (!switch_channel_up_nosig(caller_channel)) {
01120                 switch_channel_hangup(peer_channel, SWITCH_CAUSE_ORIGINATOR_CANCEL);
01121                 return SWITCH_STATUS_FALSE;
01122         }
01123 
01124         check_bridge_export(caller_channel, peer_channel);
01125 
01126         switch_channel_set_flag_recursive(caller_channel, CF_SIGNAL_BRIDGE_TTL);
01127         switch_channel_set_flag_recursive(peer_channel, CF_SIGNAL_BRIDGE_TTL);
01128 
01129         switch_channel_set_variable(caller_channel, SWITCH_SIGNAL_BRIDGE_VARIABLE, switch_core_session_get_uuid(peer_session));
01130         switch_channel_set_variable(peer_channel, SWITCH_SIGNAL_BRIDGE_VARIABLE, switch_core_session_get_uuid(session));
01131         switch_channel_set_variable(peer_channel, "call_uuid", switch_core_session_get_uuid(session));
01132 
01133         switch_channel_set_flag_recursive(caller_channel, CF_BRIDGE_ORIGINATOR);
01134         switch_channel_clear_flag(peer_channel, CF_BRIDGE_ORIGINATOR);
01135 
01136         switch_channel_clear_state_handler(caller_channel, NULL);
01137         switch_channel_clear_state_handler(peer_channel, NULL);
01138 
01139         switch_channel_add_state_handler(caller_channel, &signal_bridge_state_handlers);
01140         switch_channel_add_state_handler(peer_channel, &signal_bridge_state_handlers);
01141 
01142         switch_channel_set_variable(caller_channel, "signal_bridge", "true");
01143         switch_channel_set_variable(peer_channel, "signal_bridge", "true");
01144 
01145         /* fire events that will change the data table from "show channels" */
01146         if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
01147                 switch_channel_event_set_data(caller_channel, event);
01148                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", "signal_bridge");
01149                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(peer_session));
01150                 switch_event_fire(&event);
01151         }
01152 
01153         if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
01154                 switch_channel_event_set_data(peer_channel, event);
01155                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", "signal_bridge");
01156                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(session));
01157                 switch_event_fire(&event);
01158         }
01159 
01160         switch_channel_set_bridge_time(caller_channel);
01161         switch_channel_set_bridge_time(peer_channel);
01162         
01163         switch_channel_set_state_flag(caller_channel, CF_RESET);
01164         switch_channel_set_state_flag(peer_channel, CF_RESET);
01165 
01166         switch_channel_set_state(caller_channel, CS_HIBERNATE);
01167         switch_channel_set_state(peer_channel, CS_HIBERNATE);
01168 
01169 #if 0
01170         if (switch_channel_test_flag(caller_channel, CF_BRIDGED)) {
01171                 switch_channel_set_flag(caller_channel, CF_TRANSFER);
01172                 switch_channel_set_flag(peer_channel, CF_TRANSFER);
01173         }
01174 #endif
01175 
01176         switch_ivr_bridge_display(session, peer_session);
01177 
01178         return SWITCH_STATUS_SUCCESS;
01179 }

switch_status_t switch_ivr_sleep ( switch_core_session_t session,
uint32_t  ms,
switch_bool_t  sync,
switch_input_args_t args 
)

Wait for time to pass for a specified number of milliseconds.

Parameters:
session the session to wait for.
ms the number of milliseconds
sync synchronize the channel's audio before waiting
args arguements to pass for callbacks etc
Returns:
SWITCH_STATUS_SUCCESS if the channel is still up

Definition at line 127 of file switch_ivr.c.

References switch_frame::buflen, CF_BREAK, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, switch_frame::samples, switch_codec_implementation::samples_per_second, SFF_CNG, switch_channel_audio_sync, switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_get_variable, switch_channel_has_dtmf(), switch_channel_media_ready, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_test_flag(), SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_core_codec_destroy(), switch_core_codec_init, switch_core_session_dequeue_event(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_read_frame(), switch_core_session_write_frame(), switch_event_destroy(), SWITCH_FALSE, switch_generate_sln_silence(), SWITCH_INPUT_TYPE_DTMF, SWITCH_INPUT_TYPE_EVENT, SWITCH_IO_FLAG_NONE, switch_ivr_dmachine_feed(), switch_ivr_dmachine_ping(), switch_ivr_parse_all_events(), SWITCH_IVR_VERIFY_SILENCE_DIVISOR, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), switch_micro_time_now(), SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, switch_safe_free, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, switch_set_flag, SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_yield, and switch_zmalloc.

Referenced by collect_thread_run(), fs_switch_ivr_sleep(), originate_on_consume_media_transmit(), CoreSession::sleep(), switch_ivr_menu_execute(), switch_ivr_parse_all_events(), switch_ivr_phrase_macro_event(), switch_ivr_play_and_detect_speech(), and switch_ivr_play_file().

00128 {
00129         switch_channel_t *channel = switch_core_session_get_channel(session);
00130         switch_status_t status = SWITCH_STATUS_SUCCESS;
00131         switch_time_t start = switch_micro_time_now(), now, done = switch_micro_time_now() + (ms * 1000);
00132         switch_frame_t *read_frame, cng_frame = { 0 };
00133         int32_t left;
00134         uint32_t elapsed;
00135         char data[2] = "";
00136 
00137         switch_frame_t write_frame = { 0 };
00138         unsigned char *abuf = NULL;
00139         switch_codec_implementation_t imp = { 0 };
00140         switch_codec_t codec = { 0 };
00141         int sval = 0;
00142         const char *var;
00143 
00144         /*
00145            if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_PROXY_MODE) && 
00146            !switch_channel_media_ready(channel) && !switch_channel_test_flag(channel, CF_SERVICE)) {
00147            if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
00148            switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media.\n");
00149            return SWITCH_STATUS_FALSE;
00150            }
00151            }
00152          */
00153 
00154         if (!switch_channel_media_ready(channel)) {
00155                 
00156                 for (elapsed=0; elapsed<(ms/20); elapsed++) {
00157                         if (switch_channel_test_flag(channel, CF_BREAK)) {
00158                                 switch_channel_clear_flag(channel, CF_BREAK);
00159                                 return SWITCH_STATUS_BREAK;
00160                         }
00161                 
00162                         switch_yield(20 * 1000);
00163                 }
00164                 return SWITCH_STATUS_SUCCESS;
00165         }
00166 
00167         var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE);
00168         if (var) {
00169                 sval = atoi(var);
00170                 SWITCH_IVR_VERIFY_SILENCE_DIVISOR(sval);
00171         }
00172 
00173         if (ms > 10 && sval) {
00174                 switch_core_session_get_read_impl(session, &imp);
00175 
00176                 if (switch_core_codec_init(&codec,
00177                                                                    "L16",
00178                                                                    NULL,
00179                                                                    imp.samples_per_second,
00180                                                                    imp.microseconds_per_packet / 1000,
00181                                                                    imp.number_of_channels,
00182                                                                    SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
00183                                                                    switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
00184                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
00185                                                           imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
00186                         return SWITCH_STATUS_FALSE;
00187                 }
00188 
00189 
00190                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
00191                                                   imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
00192 
00193                 write_frame.codec = &codec;
00194                 switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE);
00195                 write_frame.data = abuf;
00196                 write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
00197                 write_frame.datalen = imp.decoded_bytes_per_packet;
00198                 write_frame.samples = write_frame.datalen / sizeof(int16_t);
00199 
00200         }
00201 
00202         if (!write_frame.datalen) {
00203                 sval = 0;
00204         }
00205 
00206         cng_frame.data = data;
00207         cng_frame.datalen = 2;
00208         cng_frame.buflen = 2;
00209         switch_set_flag((&cng_frame), SFF_CNG);
00210 
00211         if (sync) {
00212                 switch_channel_audio_sync(channel);
00213         }
00214 
00215         if (!ms) {
00216                 return SWITCH_STATUS_SUCCESS;
00217         }
00218 
00219         for (;;) {
00220                 now = switch_micro_time_now();
00221                 elapsed = (int32_t) ((now - start) / 1000);
00222                 left = ms - elapsed;
00223 
00224                 if (!switch_channel_ready(channel)) {
00225                         status = SWITCH_STATUS_FALSE;
00226                         break;
00227                 }
00228 
00229                 if (switch_channel_test_flag(channel, CF_BREAK)) {
00230                         switch_channel_clear_flag(channel, CF_BREAK);
00231                         status = SWITCH_STATUS_BREAK;
00232                         break;
00233                 }
00234 
00235                 if (now > done || left <= 0) {
00236                         break;
00237                 }
00238 
00239 
00240                 switch_ivr_parse_all_events(session);
00241 
00242 
00243                 if (args) {
00244                         switch_dtmf_t dtmf = {0};
00245 
00246                         /*
00247                            dtmf handler function you can hook up to be executed when a digit is dialed during playback 
00248                            if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
00249                          */
00250                         if (switch_channel_has_dtmf(channel)) {
00251                                 if (!args->input_callback && !args->buf && !args->dmachine) {
00252                                         status = SWITCH_STATUS_BREAK;
00253                                         break;
00254                                 }
00255                                 switch_channel_dequeue_dtmf(channel, &dtmf);
00256 
00257                                 if (args->dmachine) {
00258                                         char ds[2] = {dtmf.digit, '\0'};
00259                                         if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
00260                                                 break;
00261                                         }
00262                                 } 
00263 
00264                                 if (args->input_callback) {
00265                                         status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
00266                                 } else if (args->buf) {
00267                                         *((char *) args->buf) = dtmf.digit;
00268                                         status = SWITCH_STATUS_BREAK;
00269                                 }
00270                         }
00271 
00272                         if (args->input_callback) {
00273                                 switch_event_t *event = NULL;
00274 
00275                                 if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
00276                                         status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
00277                                         switch_event_destroy(&event);
00278                                 }
00279                         }
00280 
00281                         if (status != SWITCH_STATUS_SUCCESS) {
00282                                 break;
00283                         }
00284                 }
00285 
00286                 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
00287 
00288                 if (!SWITCH_READ_ACCEPTABLE(status)) {
00289                         break;
00290                 }
00291 
00292                 if (args && args->dmachine) {
00293                         if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
00294                                 break;
00295                         }
00296                 }
00297 
00298                 if (sval && write_frame.datalen) {
00299                         switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, sval);
00300                         switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
00301                 } else {
00302                         switch_core_session_write_frame(session, &cng_frame, SWITCH_IO_FLAG_NONE, 0);
00303                 }
00304         }
00305 
00306         if (write_frame.codec) {
00307                 switch_core_codec_destroy(&codec);
00308         }
00309 
00310         switch_safe_free(abuf);
00311 
00312         return status;
00313 }

switch_status_t switch_ivr_speak_text ( switch_core_session_t session,
const char *  tts_name,
const char *  voice_name,
char *  text,
switch_input_args_t args 
)

Speak given text with given tts engine.

Parameters:
session the session to speak on
tts_name the desired tts module
voice_name the desired voice
text the text to speak
args arguements to pass for callbacks etc
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2397 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, cached_speech_handle::codec, switch_frame::codec, switch_codec_implementation::microseconds_per_packet, pool, switch_speech_handle::samples, cached_speech_handle::sh, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, SWITCH_CACHE_SPEECH_HANDLES_VARIABLE, switch_channel_get_private(), switch_channel_get_variable, switch_channel_pre_answer, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_copy_string(), switch_core_codec_destroy(), switch_core_codec_init, switch_core_service_session, switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_reset(), switch_core_speech_close(), switch_core_speech_open(), switch_core_speech_text_param_tts(), switch_core_thread_session_end(), switch_core_timer_destroy(), switch_core_timer_init(), switch_core_timer_sync(), SWITCH_FALSE, switch_ivr_clear_speech_cache(), switch_ivr_speak_text_handle(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_SPEECH_FLAG_NONE, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, switch_true(), SWITCH_TRUE, cached_speech_handle::timer, cached_speech_handle::tts_name, and cached_speech_handle::voice_name.

Referenced by fs_switch_ivr_speak_text(), CoreSession::speak(), switch_ivr_phrase_macro_event(), and switch_ivr_play_file().

02399 {
02400         switch_channel_t *channel = switch_core_session_get_channel(session);
02401         uint32_t rate = 0;
02402         int interval = 0;
02403         switch_frame_t write_frame = { 0 };
02404         switch_timer_t ltimer, *timer;
02405         switch_codec_t lcodec, *codec;
02406         switch_memory_pool_t *pool = switch_core_session_get_pool(session);
02407         char *codec_name;
02408         switch_status_t status = SWITCH_STATUS_SUCCESS;
02409         switch_speech_handle_t lsh, *sh;
02410         switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
02411         const char *timer_name, *var;
02412         cached_speech_handle_t *cache_obj = NULL;
02413         int need_create = 1, need_alloc = 1;
02414         switch_codec_implementation_t read_impl = { 0 };
02415         switch_core_session_get_read_impl(session, &read_impl);
02416 
02417         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
02418                 return SWITCH_STATUS_FALSE;
02419         }
02420 
02421         sh = &lsh;
02422         codec = &lcodec;
02423         timer = &ltimer;
02424 
02425         if ((var = switch_channel_get_variable(channel, SWITCH_CACHE_SPEECH_HANDLES_VARIABLE)) && switch_true(var)) {
02426                 if ((cache_obj = (cached_speech_handle_t *) switch_channel_get_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME))) {
02427                         need_create = 0;
02428                         if (!strcasecmp(cache_obj->tts_name, tts_name)) {
02429                                 need_alloc = 0;
02430                         } else {
02431                                 switch_ivr_clear_speech_cache(session);
02432                         }
02433                 }
02434 
02435                 if (!cache_obj) {
02436                         cache_obj = (cached_speech_handle_t *) switch_core_session_alloc(session, sizeof(*cache_obj));
02437                 }
02438                 if (need_alloc) {
02439                         switch_copy_string(cache_obj->tts_name, tts_name, sizeof(cache_obj->tts_name));
02440                         switch_copy_string(cache_obj->voice_name, voice_name, sizeof(cache_obj->voice_name));
02441                         switch_channel_set_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, cache_obj);
02442                 }
02443                 sh = &cache_obj->sh;
02444                 codec = &cache_obj->codec;
02445                 timer = &cache_obj->timer;
02446         }
02447 
02448         timer_name = switch_channel_get_variable(channel, "timer_name");
02449 
02450         switch_core_session_reset(session, SWITCH_FALSE, SWITCH_FALSE);
02451 
02452         rate = read_impl.actual_samples_per_second;
02453         interval = read_impl.microseconds_per_packet / 1000;
02454 
02455         if (need_create) {
02456                 memset(sh, 0, sizeof(*sh));
02457                 if ((status = switch_core_speech_open(sh, tts_name, voice_name, (uint32_t) rate, interval, &flags, NULL)) != SWITCH_STATUS_SUCCESS) {
02458                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid TTS module!\n");
02459                         switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
02460                         switch_ivr_clear_speech_cache(session);
02461                         return status;
02462                 }
02463         } else if (cache_obj && strcasecmp(cache_obj->voice_name, voice_name)) {
02464                 switch_copy_string(cache_obj->voice_name, voice_name, sizeof(cache_obj->voice_name));
02465                 switch_core_speech_text_param_tts(sh, "voice", voice_name);
02466         }
02467 
02468         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
02469                 flags = 0;
02470                 switch_core_speech_close(sh, &flags);
02471                 return SWITCH_STATUS_FALSE;
02472         }
02473         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
02474 
02475         codec_name = "L16";
02476 
02477         if (need_create) {
02478                 if (switch_core_codec_init(codec,
02479                                                                    codec_name,
02480                                                                    NULL, (int) rate, interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
02481                                                                    pool) == SWITCH_STATUS_SUCCESS) {
02482                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
02483                 } else {
02484                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed %s@%uhz 1 channel %dms\n", codec_name,
02485                                                           rate, interval);
02486                         flags = 0;
02487                         switch_core_speech_close(sh, &flags);
02488                         switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
02489                         switch_ivr_clear_speech_cache(session);
02490                         return SWITCH_STATUS_GENERR;
02491                 }
02492         }
02493 
02494         write_frame.codec = codec;
02495 
02496         if (timer_name) {
02497                 if (need_create) {
02498                         if (switch_core_timer_init(timer, timer_name, interval, (int) sh->samples, pool) != SWITCH_STATUS_SUCCESS) {
02499                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n");
02500                                 switch_core_codec_destroy(write_frame.codec);
02501                                 flags = 0;
02502                                 switch_core_speech_close(sh, &flags);
02503                                 switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
02504                                 switch_ivr_clear_speech_cache(session);
02505                                 return SWITCH_STATUS_GENERR;
02506                         }
02507                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", sh->samples * 2,
02508                                                           interval);
02509                 }
02510                 switch_core_timer_sync(timer); // Sync timer
02511 
02512                 /* start a thread to absorb incoming audio */
02513                 switch_core_service_session(session);
02514 
02515         }
02516 
02517         status = switch_ivr_speak_text_handle(session, sh, write_frame.codec, timer_name ? timer : NULL, text, args);
02518         flags = 0;
02519 
02520         if (!cache_obj) {
02521                 switch_core_speech_close(sh, &flags);
02522                 switch_core_codec_destroy(codec);
02523         }
02524 
02525         if (timer_name) {
02526                 /* End the audio absorbing thread */
02527                 switch_core_thread_session_end(session);
02528                 if (!cache_obj) {
02529                         switch_core_timer_destroy(timer);
02530                 }
02531         }
02532 
02533         switch_core_session_reset(session, SWITCH_FALSE, SWITCH_TRUE);
02534         return status;
02535 }

switch_status_t switch_ivr_speak_text_handle ( switch_core_session_t session,
switch_speech_handle_t sh,
switch_codec_t codec,
switch_timer_t timer,
char *  text,
switch_input_args_t args 
)

Definition at line 2086 of file switch_ivr_play_say.c.

References switch_frame::buflen, CF_BREAK, CF_HOLD, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_dtmf_t::digit, switch_frame::rate, switch_frame::samples, switch_assert, switch_channel_audio_sync, switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_get_variable, switch_channel_has_dtmf(), switch_channel_pre_answer, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_test_flag(), switch_core_session_dequeue_event(), switch_core_session_dequeue_private_event(), switch_core_session_get_channel(), switch_core_session_read_frame(), switch_core_session_write_frame(), switch_core_speech_feed_tts(), switch_core_speech_flush_tts(), switch_core_speech_read_tts(), switch_core_timer_next(), switch_event_destroy(), SWITCH_FALSE, SWITCH_INPUT_TYPE_DTMF, SWITCH_INPUT_TYPE_EVENT, SWITCH_IO_FLAG_NONE, switch_ivr_dmachine_feed(), switch_ivr_dmachine_ping(), switch_ivr_parse_all_messages(), switch_ivr_parse_event(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_READ_ACCEPTABLE, switch_safe_free, SWITCH_SPEECH_FLAG_BLOCKING, SWITCH_SPEECH_FLAG_NONE, SWITCH_SPEECH_FLAG_PAUSE, SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, switch_test_flag, switch_yield, and switch_frame::timestamp.

Referenced by switch_ivr_speak_text().

02089 {
02090         switch_channel_t *channel = switch_core_session_get_channel(session);
02091         short abuf[960];
02092         switch_dtmf_t dtmf = { 0 };
02093         uint32_t len = 0;
02094         switch_size_t ilen = 0;
02095         switch_frame_t write_frame = { 0 };
02096         int x;
02097         int done = 0;
02098         int lead_in_out = 10;
02099         switch_status_t status = SWITCH_STATUS_SUCCESS;
02100         switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
02101         switch_size_t extra = 0;
02102         char *p, *tmp = NULL;
02103         const char *star, *pound;
02104         switch_size_t starlen, poundlen;
02105 
02106         if (!sh) {
02107                 return SWITCH_STATUS_FALSE;
02108         }
02109 
02110         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
02111                 return SWITCH_STATUS_FALSE;
02112         }
02113 
02114         write_frame.data = abuf;
02115         write_frame.buflen = sizeof(abuf);
02116 
02117         len = sh->samples * 2;
02118 
02119         flags = 0;
02120 
02121         if (!(star = switch_channel_get_variable(channel, "star_replace"))) {
02122                 star = "star";
02123         }
02124         if (!(pound = switch_channel_get_variable(channel, "pound_replace"))) {
02125                 pound = "pound";
02126         }
02127         starlen = strlen(star);
02128         poundlen = strlen(pound);
02129 
02130 
02131         for (p = text; p && *p; p++) {
02132                 if (*p == '*') {
02133                         extra += starlen;
02134                 } else if (*p == '#') {
02135                         extra += poundlen;
02136                 }
02137         }
02138 
02139         if (extra) {
02140                 char *tp;
02141                 switch_size_t mylen = strlen(text) + extra + 1;
02142                 tmp = malloc(mylen);
02143                 if (!tmp) {
02144                         return SWITCH_STATUS_MEMERR;
02145                 }
02146                 memset(tmp, 0, mylen);
02147                 tp = tmp;
02148                 for (p = text; p && *p; p++) {
02149                         if (*p == '*') {
02150                                 strncat(tp, star, starlen);
02151                                 tp += starlen;
02152                         } else if (*p == '#') {
02153                                 strncat(tp, pound, poundlen);
02154                                 tp += poundlen;
02155                         } else {
02156                                 *tp++ = *p;
02157                         }
02158                 }
02159 
02160                 text = tmp;
02161         }
02162 
02163         switch_core_speech_feed_tts(sh, text, &flags);
02164         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Speaking text: %s\n", text);
02165         switch_safe_free(tmp);
02166         text = NULL;
02167 
02168         write_frame.rate = sh->rate;
02169 
02170         memset(write_frame.data, 0, len);
02171         write_frame.datalen = len;
02172         write_frame.samples = len / 2;
02173         write_frame.codec = codec;
02174 
02175         switch_assert(codec->implementation != NULL);
02176 
02177         for (x = 0; !done && x < lead_in_out; x++) {
02178                 switch_yield(codec->implementation->microseconds_per_packet);
02179                 if (timer) {
02180                         write_frame.timestamp = timer->samplecount;
02181                 }
02182                 if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
02183                         done = 1;
02184                         break;
02185                 }
02186         }
02187 
02188         switch_channel_audio_sync(channel);
02189 
02190         ilen = len;
02191         for (;;) {
02192                 switch_event_t *event;
02193 
02194                 if (!switch_channel_ready(channel)) {
02195                         status = SWITCH_STATUS_FALSE;
02196                         break;
02197                 }
02198 
02199                 if (switch_channel_test_flag(channel, CF_BREAK)) {
02200                         switch_channel_clear_flag(channel, CF_BREAK);
02201                         status = SWITCH_STATUS_BREAK;
02202                         break;
02203                 }
02204 
02205                 if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
02206                         switch_ivr_parse_event(session, event);
02207                         switch_event_destroy(&event);
02208                 }
02209 
02210                 if (args) {
02211                         /* dtmf handler function you can hook up to be executed when a digit is dialed during playback 
02212                          * if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
02213                          */
02214                         if (switch_channel_has_dtmf(channel)) {
02215                                 if (!args->input_callback && !args->buf && !args->dmachine) {
02216                                         status = SWITCH_STATUS_BREAK;
02217                                         done = 1;
02218                                         break;
02219                                 }
02220                                 if (args->buf && !strcasecmp(args->buf, "_break_")) {
02221                                         status = SWITCH_STATUS_BREAK;
02222                                 } else {
02223                                         switch_channel_dequeue_dtmf(channel, &dtmf);
02224 
02225                                         if (args->dmachine) {
02226                                                 char ds[2] = {dtmf.digit, '\0'};
02227                                                 if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
02228                                                         break;
02229                                                 }
02230                                         } 
02231 
02232                                         if (args->input_callback) {
02233                                                 status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
02234                                         } else if (args->buf) {
02235                                                 *((char *) args->buf) = dtmf.digit;
02236                                                 status = SWITCH_STATUS_BREAK;
02237                                         }
02238                                 }
02239                         }
02240 
02241                         if (args->input_callback) {
02242                                 if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
02243                                         status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
02244                                         switch_event_destroy(&event);
02245                                 }
02246                         }
02247 
02248                         if (status != SWITCH_STATUS_SUCCESS) {
02249                                 done = 1;
02250                                 break;
02251                         }
02252                 }
02253 
02254                 if (switch_test_flag(sh, SWITCH_SPEECH_FLAG_PAUSE)) {
02255                         if (timer) {
02256                                 if (switch_core_timer_next(timer) != SWITCH_STATUS_SUCCESS) {
02257                                         break;
02258                                 }
02259                         } else {
02260                                 switch_frame_t *read_frame;
02261                                 switch_status_t tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
02262 
02263                                 while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
02264                                         switch_ivr_parse_all_messages(session);
02265                                         switch_yield(10000);
02266                                 }
02267 
02268                                 if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
02269                                         break;
02270                                 }
02271 
02272                                 if (args && args->dmachine) {
02273                                         if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
02274                                                 goto done;
02275                                         }
02276                                 }
02277 
02278                                 if (args && (args->read_frame_callback)) {
02279                                         if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
02280                                                 goto done;
02281                                         }
02282                                 }
02283                         }
02284                         continue;
02285                 }
02286 
02287                 flags = SWITCH_SPEECH_FLAG_BLOCKING;
02288                 status = switch_core_speech_read_tts(sh, abuf, &ilen, &flags);
02289 
02290                 if (status != SWITCH_STATUS_SUCCESS) {
02291                         write_frame.datalen = (uint32_t) codec->implementation->decoded_bytes_per_packet;
02292                         write_frame.samples = (uint32_t) (write_frame.datalen / 2);
02293                         memset(write_frame.data, 0, write_frame.datalen);
02294                         for (x = 0; !done && x < lead_in_out; x++) {
02295                                 switch_yield(codec->implementation->microseconds_per_packet);
02296                                 if (timer) {
02297                                         write_frame.timestamp = timer->samplecount;
02298                                 }
02299                                 if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
02300                                         done = 1;
02301                                         break;
02302                                 }
02303                         }
02304                         if (status == SWITCH_STATUS_BREAK) {
02305                                 status = SWITCH_STATUS_SUCCESS;
02306                         }
02307                         done = 1;
02308                 }
02309 
02310                 if (done) {
02311                         break;
02312                 }
02313 
02314                 write_frame.datalen = (uint32_t) ilen;
02315                 write_frame.samples = (uint32_t) (ilen / 2);
02316                 if (timer) {
02317                         write_frame.timestamp = timer->samplecount;
02318                 }
02319                 if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
02320                         done = 1;
02321                         break;
02322                 }
02323 
02324                 if (done) {
02325                         break;
02326                 }
02327 
02328                 if (timer) {
02329                         if (switch_core_timer_next(timer) != SWITCH_STATUS_SUCCESS) {
02330                                 break;
02331                         }
02332                 } else {                                /* time off the channel (if you must) */
02333                         switch_frame_t *read_frame;
02334                         switch_status_t tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
02335 
02336                         while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
02337                                 switch_ivr_parse_all_messages(session);
02338                                 switch_yield(10000);
02339                         }
02340 
02341                         if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
02342                                 break;
02343                         }
02344 
02345                         if (args && args->dmachine) {
02346                                 if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
02347                                         goto done;
02348                                 }
02349                         }
02350 
02351                         if (args && (args->read_frame_callback)) {
02352                                 if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
02353                                         goto done;
02354                                 }
02355                         }
02356                 }
02357         }
02358 
02359  done:
02360 
02361         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done speaking text\n");
02362         flags = 0;
02363         switch_core_speech_flush_tts(sh);
02364         return status;
02365 }

switch_status_t switch_ivr_stop_detect_speech ( switch_core_session_t session  ) 

Stop background Speech detection on a session.

Parameters:
session The session to stop detection on
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3656 of file switch_ivr_async.c.

References speech_thread_handle::bug, speech_on_dtmf(), switch_assert, switch_channel_get_private(), switch_channel_set_private(), switch_core_media_bug_remove(), switch_core_session_get_channel(), SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_detect_speech(), switch_ivr_detect_speech_disable_all_grammars(), switch_ivr_detect_speech_disable_grammar(), switch_ivr_detect_speech_enable_grammar(), switch_ivr_detect_speech_load_grammar(), and switch_ivr_detect_speech_unload_grammar().

03657 {
03658         switch_channel_t *channel = switch_core_session_get_channel(session);
03659         struct speech_thread_handle *sth;
03660 
03661         switch_assert(channel != NULL);
03662         if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
03663                 switch_channel_set_private(channel, SWITCH_SPEECH_KEY, NULL);
03664                 switch_core_event_hook_remove_recv_dtmf(session, speech_on_dtmf);
03665                 switch_core_media_bug_remove(session, &sth->bug);
03666                 return SWITCH_STATUS_SUCCESS;
03667         }
03668 
03669         return SWITCH_STATUS_FALSE;
03670 }

switch_status_t switch_ivr_stop_displace_session ( switch_core_session_t session,
const char *  file 
)

Stop displacing a session.

Parameters:
session the session
file file name from the switch_ivr_displace_session call
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 867 of file switch_ivr_async.c.

References switch_channel_get_private(), switch_channel_set_private(), switch_core_media_bug_remove(), switch_core_session_get_channel(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

00868 {
00869         switch_media_bug_t *bug;
00870         switch_channel_t *channel = switch_core_session_get_channel(session);
00871 
00872         if ((bug = switch_channel_get_private(channel, file))) {
00873                 switch_channel_set_private(channel, file, NULL);
00874                 switch_core_media_bug_remove(session, &bug);
00875                 return SWITCH_STATUS_SUCCESS;
00876         }
00877 
00878         return SWITCH_STATUS_FALSE;
00879 }

switch_status_t switch_ivr_stop_inband_dtmf_generate_session ( switch_core_session_t session  ) 

Stop generating DTMF inband.

Parameters:
session the session to stop generating
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2626 of file switch_ivr_async.c.

References switch_channel_get_private(), switch_channel_set_private(), switch_core_media_bug_remove(), switch_core_session_get_channel(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

02627 {
02628         switch_channel_t *channel = switch_core_session_get_channel(session);
02629         switch_media_bug_t *bug = switch_channel_get_private(channel, "dtmf_generate");
02630 
02631         if (bug) {
02632                 switch_channel_set_private(channel, "dtmf_generate", NULL);
02633                 switch_core_media_bug_remove(session, &bug);
02634                 return SWITCH_STATUS_SUCCESS;
02635         }
02636 
02637         return SWITCH_STATUS_FALSE;
02638 
02639 }

switch_status_t switch_ivr_stop_inband_dtmf_session ( switch_core_session_t session  ) 

Stop looking for DTMF inband.

Parameters:
session the session to stop looking
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2393 of file switch_ivr_async.c.

References switch_channel_get_private(), switch_channel_set_private(), switch_core_media_bug_remove(), switch_core_session_get_channel(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

02394 {
02395         switch_media_bug_t *bug;
02396         switch_channel_t *channel = switch_core_session_get_channel(session);
02397 
02398         if ((bug = switch_channel_get_private(channel, "dtmf"))) {
02399                 switch_channel_set_private(channel, "dtmf", NULL);
02400                 switch_core_media_bug_remove(session, &bug);
02401                 return SWITCH_STATUS_SUCCESS;
02402         }
02403         return SWITCH_STATUS_FALSE;
02404 }

switch_status_t switch_ivr_stop_record_session ( switch_core_session_t session,
const char *  file 
)

Stop Recording a session.

Parameters:
session the session to stop recording
file the path to the file
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1130 of file switch_ivr_async.c.

References record_callback(), switch_channel_get_private(), switch_core_media_bug_remove(), switch_core_media_bug_remove_callback(), switch_core_session_get_channel(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_core_media_bug_transfer_recordings(), and switch_ivr_record_session().

01131 {
01132         switch_media_bug_t *bug;
01133         switch_channel_t *channel = switch_core_session_get_channel(session);
01134 
01135         if (!strcasecmp(file, "all")) {
01136                 return switch_core_media_bug_remove_callback(session, record_callback);
01137         } else if ((bug = switch_channel_get_private(channel, file))) {
01138                 switch_core_media_bug_remove(session, &bug);
01139                 return SWITCH_STATUS_SUCCESS;
01140         }
01141         return SWITCH_STATUS_FALSE;
01142 }

switch_status_t switch_ivr_stop_session_audio ( switch_core_session_t session  ) 

Definition at line 2265 of file switch_ivr_async.c.

References switch_channel_get_private(), switch_channel_set_private(), switch_core_media_bug_remove(), switch_core_session_get_channel(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

02266 {
02267         switch_media_bug_t *bug;
02268         switch_channel_t *channel = switch_core_session_get_channel(session);
02269 
02270         if ((bug = switch_channel_get_private(channel, "__audio"))) {
02271                 switch_channel_set_private(channel, "__audio", NULL);
02272                 switch_core_media_bug_remove(session, &bug);
02273                 return SWITCH_STATUS_SUCCESS;
02274         }
02275         return SWITCH_STATUS_FALSE;
02276 }

switch_status_t switch_ivr_stop_tone_detect_session ( switch_core_session_t session  ) 

Stop looking for TONES.

Parameters:
session the session to stop looking
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2846 of file switch_ivr_async.c.

References switch_tone_container_t::bug, switch_tone_container_t::detect_fax, switch_tone_container_t::index, switch_tone_container_t::list, switch_channel_get_private(), switch_channel_set_private(), switch_core_media_bug_remove(), switch_core_session_get_channel(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_tone_detect_t::up.

02847 {
02848         switch_channel_t *channel = switch_core_session_get_channel(session);
02849         switch_tone_container_t *cont = switch_channel_get_private(channel, "_tone_detect_");
02850         int i = 0;
02851 
02852         if (cont) {
02853                 switch_channel_set_private(channel, "_tone_detect_", NULL);
02854                 for (i = 0; i < cont->index; i++) {
02855                         cont->list[i].up = 0;
02856                 }
02857                 switch_core_media_bug_remove(session, &cont->bug);
02858                 if (cont->detect_fax) {
02859                         cont->detect_fax = 0;
02860                 }
02861                 return SWITCH_STATUS_SUCCESS;
02862         }
02863         return SWITCH_STATUS_FALSE;
02864 }

switch_status_t switch_ivr_tone_detect_session ( switch_core_session_t session,
const char *  key,
const char *  tone_spec,
const char *  flags,
time_t  timeout,
int  hits,
const char *  app,
const char *  data,
switch_tone_detect_callback_t  callback 
)

Start looking for TONES.

Parameters:
session the session to start looking
key the name of the tone.
tone_spec comma sep list of tone freqs
flags one or both of 'r' and 'w'
timeout timeout
app optional application to execute when tone is found
data optional data for appliaction
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2866 of file switch_ivr_async.c.

References switch_tone_detect_t::expires, switch_tone_detect_t::hits, switch_tone_container_t::index, switch_tone_detect_t::key, switch_tone_container_t::list, MAX_TONES, switch_tone_detect_t::sleep, switch_channel_get_private(), SWITCH_CHANNEL_SESSION_LOG, switch_core_session_get_channel(), switch_core_session_get_read_impl(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_tone_detect_t::up, and zstr.

Referenced by check_channel_status().

02870 {
02871         switch_channel_t *channel = switch_core_session_get_channel(session);
02872         switch_status_t status;
02873         switch_tone_container_t *cont = switch_channel_get_private(channel, "_tone_detect_");
02874         char *p, *next;
02875         int i = 0, ok = 0, detect_fax = 0;
02876         switch_media_bug_flag_t bflags = 0;
02877         const char *var;
02878         switch_codec_implementation_t read_impl = { 0 };
02879         switch_core_session_get_read_impl(session, &read_impl);
02880 
02881 
02882         if (zstr(key)) {
02883                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Key Specified!\n");
02884                 return SWITCH_STATUS_FALSE;
02885         }
02886 
02887         if (cont) {
02888                 if (cont->index >= MAX_TONES) {
02889                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Max Tones Reached!\n");
02890                         return SWITCH_STATUS_FALSE;
02891                 }
02892 
02893                 for (i = 0; i < cont->index; i++) {
02894                         if (!zstr(cont->list[i].key) && !strcasecmp(key, cont->list[i].key)) {
02895                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Re-enabling %s\n", key);
02896                                 cont->list[i].up = 1;
02897                                 cont->list[i].hits = 0;
02898                                 cont->list[i].sleep = 0;
02899                                 cont->list[i].expires = 0;
02900                                 return SWITCH_STATUS_SUCCESS;
02901                         }
02902                 }
02903         }
02904 
02905         if (zstr(tone_spec)) {
02906                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Spec Specified!\n");
02907                 return SWITCH_STATUS_FALSE;
02908         }
02909 
02910         if (!cont && !(cont = switch_core_session_alloc(session, sizeof(*cont)))) {
02911                 return SWITCH_STATUS_MEMERR;
02912         }
02913 
02914         if ((var = switch_channel_get_variable(channel, "tone_detect_hits"))) {
02915                 int tmp = atoi(var);
02916                 if (tmp > 0) {
02917                         hits = tmp;
02918                 }
02919         }
02920 
02921         if (!hits) hits = 1;
02922 
02923         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding tone spec %s index %d hits %d\n", tone_spec, cont->index, hits);
02924 
02925         i = 0;
02926         p = (char *) tone_spec;
02927 
02928         do {
02929                 teletone_process_t this;
02930                 next = strchr(p, ',');
02931                 while (*p == ' ')
02932                         p++;
02933                 if ((this = (teletone_process_t) atof(p))) {
02934                         ok++;
02935                         cont->list[cont->index].map.freqs[i++] = this;
02936                 }
02937                 if (!strncasecmp(p, "1100", 4)) {
02938                         detect_fax = cont->index;
02939                 }
02940 
02941                 if (next) {
02942                         p = next + 1;
02943                 }
02944         } while (next);
02945         cont->list[cont->index].map.freqs[i++] = 0;
02946 
02947         if (!ok) {
02948                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid tone spec!\n");
02949                 return SWITCH_STATUS_FALSE;
02950         }
02951 
02952         cont->detect_fax = detect_fax;
02953 
02954         cont->list[cont->index].key = switch_core_session_strdup(session, key);
02955 
02956         if (app) {
02957                 cont->list[cont->index].app = switch_core_session_strdup(session, app);
02958         }
02959 
02960         if (data) {
02961                 cont->list[cont->index].data = switch_core_session_strdup(session, data);
02962         }
02963 
02964         cont->list[cont->index].callback = callback;
02965 
02966         if (!hits)
02967                 hits = 1;
02968 
02969         cont->list[cont->index].hits = 0;
02970         cont->list[cont->index].total_hits = hits;
02971 
02972         cont->list[cont->index].up = 1;
02973         memset(&cont->list[cont->index].mt, 0, sizeof(cont->list[cont->index].mt));
02974         cont->list[cont->index].mt.sample_rate = read_impl.actual_samples_per_second;
02975         teletone_multi_tone_init(&cont->list[cont->index].mt, &cont->list[cont->index].map);
02976         cont->session = session;
02977 
02978         if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
02979                 return SWITCH_STATUS_FALSE;
02980         }
02981 
02982         cont->list[cont->index].default_sleep = 25;
02983         cont->list[cont->index].default_expires = 250;
02984 
02985         if ((var = switch_channel_get_variable(channel, "tone_detect_sleep"))) {
02986                 int tmp = atoi(var);
02987                 if (tmp > 0) {
02988                         cont->list[cont->index].default_sleep = tmp;
02989                 }
02990         }
02991 
02992         if ((var = switch_channel_get_variable(channel, "tone_detect_expires"))) {
02993                 int tmp = atoi(var);
02994                 if (tmp > 0) {
02995                         cont->list[cont->index].default_expires = tmp;
02996                 }
02997         }
02998 
02999 
03000         if (zstr(flags)) {
03001                 bflags = SMBF_READ_REPLACE;
03002         } else {
03003                 if (strchr(flags, 'o')) {
03004                         cont->list[cont->index].once = 1;
03005                 }
03006 
03007                 if (strchr(flags, 'r')) {
03008                         bflags |= SMBF_READ_REPLACE;
03009                 } else if (strchr(flags, 'w')) {
03010                         bflags |= SMBF_WRITE_REPLACE;
03011                 }
03012         }
03013 
03014         bflags |= SMBF_NO_PAUSE;
03015 
03016         if (cont->bug_running) {
03017                 status = SWITCH_STATUS_SUCCESS;
03018                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s bug already running\n", switch_channel_get_name(channel));
03019         } else {
03020                 cont->bug_running = 1;
03021                 if (cont->detect_fax) {
03022                         switch_core_event_hook_add_send_dtmf(session, tone_on_dtmf);
03023                         switch_core_event_hook_add_recv_dtmf(session, tone_on_dtmf);
03024                 }
03025 
03026                 if ((status = switch_core_media_bug_add(session, "tone_detect", key,
03027                                                                                                 tone_detect_callback, cont, timeout, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
03028                         cont->bug_running = 0;
03029                         return status;
03030                 }
03031                 switch_channel_set_private(channel, "_tone_detect_", cont);
03032         }
03033 
03034         cont->index++;
03035 
03036         return SWITCH_STATUS_SUCCESS;
03037 }

switch_status_t switch_ivr_transfer_variable ( switch_core_session_t sessa,
switch_core_session_t sessb,
char *  var 
)

Transfer variables from one session to another.

Parameters:
sessa the original session
sessb the new session
var the name of the variable to transfer (NULL for all)
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1744 of file switch_ivr.c.

References switch_event::headers, switch_event_header::name, switch_event_header::next, switch_channel_get_variable, switch_channel_get_variables(), switch_channel_set_variable, switch_core_session_get_channel(), switch_event_destroy(), SWITCH_STATUS_SUCCESS, and switch_event_header::value.

01745 {
01746         switch_channel_t *chana = switch_core_session_get_channel(sessa);
01747         switch_channel_t *chanb = switch_core_session_get_channel(sessb);
01748         switch_event_t *var_event;
01749 
01750         const char *val = NULL;
01751         uint8_t prefix = 0;
01752 
01753         if (var && *var == '~') {
01754                 var++;
01755                 prefix = 1;
01756         }
01757 
01758         if (var && !prefix) {
01759                 if ((val = switch_channel_get_variable(chana, var))) {
01760                         switch_channel_set_variable(chanb, var, val);
01761                 }
01762         } else {
01763                 switch_event_header_t *hi;
01764 
01765                 switch_channel_get_variables(chana, &var_event);
01766 
01767                 for (hi = var_event->headers; hi; hi = hi->next) {
01768                         char *vvar = hi->name;
01769                         char *vval = hi->value;
01770                         if (vvar && vval && (!prefix || (var && !strncmp((char *) vvar, var, strlen(var))))) {
01771                                 switch_channel_set_variable(chanb, (char *) vvar, (char *) vval);
01772                         }
01773                 }
01774 
01775                 switch_event_destroy(&var_event);
01776         }
01777 
01778         return SWITCH_STATUS_SUCCESS;
01779 }

switch_status_t switch_ivr_unhold ( switch_core_session_t session  ) 

Signal the session with a protocol specific unhold message.

Parameters:
session the session to unhold
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1408 of file switch_ivr.c.

References CF_BROADCAST, CF_HOLD, CF_SUSPEND, switch_core_session_message::from, switch_core_session_message::message_id, switch_channel_clear_flag(), switch_channel_get_variable, switch_channel_stop_broadcast, switch_channel_wait_for_flag(), switch_core_session_get_channel(), switch_core_session_locate(), switch_core_session_receive_message, switch_core_session_rwunlock(), SWITCH_FALSE, SWITCH_MESSAGE_INDICATE_UNHOLD, SWITCH_SIGNAL_BOND_VARIABLE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_unhold_uuid().

01409 {
01410         switch_core_session_message_t msg = { 0 };
01411         switch_channel_t *channel = switch_core_session_get_channel(session);
01412         const char *other_uuid;
01413         switch_core_session_t *b_session;
01414 
01415         msg.message_id = SWITCH_MESSAGE_INDICATE_UNHOLD;
01416         msg.from = __FILE__;
01417 
01418         switch_channel_clear_flag(channel, CF_HOLD);
01419         switch_channel_clear_flag(channel, CF_SUSPEND);
01420 
01421         switch_core_session_receive_message(session, &msg);
01422 
01423 
01424         if ((other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (b_session = switch_core_session_locate(other_uuid))) {
01425                 switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
01426                 switch_channel_stop_broadcast(b_channel);
01427                 switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
01428                 switch_core_session_rwunlock(b_session);
01429         }
01430 
01431 
01432         return SWITCH_STATUS_SUCCESS;
01433 }

switch_status_t switch_ivr_unhold_uuid ( const char *  uuid  ) 

Signal the session with a protocol specific unhold message.

Parameters:
uuid the uuid of the session to hold
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1435 of file switch_ivr.c.

References switch_core_session_locate(), switch_core_session_rwunlock(), switch_ivr_unhold(), and SWITCH_STATUS_SUCCESS.

01436 {
01437         switch_core_session_t *session;
01438 
01439         if ((session = switch_core_session_locate(uuid))) {
01440                 switch_ivr_unhold(session);
01441                 switch_core_session_rwunlock(session);
01442         }
01443 
01444         return SWITCH_STATUS_SUCCESS;
01445 }

switch_status_t switch_ivr_uuid_bridge ( const char *  originator_uuid,
const char *  originatee_uuid 
)

Bridge two existing sessions.

Parameters:
originator_uuid the uuid of the originator
originatee_uuid the uuid of the originator
Remarks:
Any custom state handlers on both channels will be deleted
Returns:
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1543 of file switch_ivr_bridge.c.

References switch_caller_profile::caller_id_name, switch_caller_profile::caller_id_number, CF_BRIDGE_ORIGINATOR, CF_DIALPLAN, CF_ORIGINATING, CF_REDIRECT, CF_TRANSFER, cleanup_proxy_mode_a(), CS_CONSUME_MEDIA, CS_HIBERNATE, switch_caller_profile::destination_number, switch_caller_profile::pool, SWITCH_BRIDGE_CHANNEL_VARIABLE, SWITCH_BRIDGE_UUID_VARIABLE, SWITCH_CALL_DIRECTION_OUTBOUND, switch_caller_profile_clone(), switch_channel_add_state_handler(), switch_channel_add_variable_var_check(), switch_channel_clear_flag(), switch_channel_clear_flag_recursive(), switch_channel_clear_state_flag(), switch_channel_clear_state_handler(), switch_channel_direction(), switch_channel_down_nosig, switch_channel_flip_cid(), switch_channel_get_caller_profile(), switch_channel_get_name(), switch_channel_get_state(), switch_channel_media_up, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_set_originatee_caller_profile(), switch_channel_set_originator_caller_profile(), switch_channel_set_state, switch_channel_set_state_flag(), switch_channel_set_variable, switch_channel_stop_broadcast, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_get_uuid(), switch_core_session_locate(), switch_core_session_rwunlock(), switch_core_sprintf(), switch_epoch_time_now(), SWITCH_FALSE, switch_ivr_bridge_display(), SWITCH_LOG_CRIT, SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_SIGNAL_BOND_VARIABLE, SWITCH_STACK_PUSH, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, SWITCH_TRANSFER_HISTORY_VARIABLE, SWITCH_TRANSFER_SOURCE_VARIABLE, SWITCH_UUID_BRIDGE, switch_caller_profile::transfer_source, uuid_bridge_state_handlers, and switch_caller_profile::uuid_str.

Referenced by switch_ivr_intercept_session(), and switch_ivr_media().

01544 {
01545         switch_core_session_t *originator_session, *originatee_session, *swap_session;
01546         switch_channel_t *originator_channel, *originatee_channel, *swap_channel;
01547         switch_status_t status = SWITCH_STATUS_FALSE;
01548         switch_caller_profile_t *originator_cp, *originatee_cp;
01549         switch_channel_state_t state;
01550 
01551         if ((originator_session = switch_core_session_locate(originator_uuid))) {
01552                 if ((originatee_session = switch_core_session_locate(originatee_uuid))) {
01553                         originator_channel = switch_core_session_get_channel(originator_session);
01554                         originatee_channel = switch_core_session_get_channel(originatee_session);
01555 
01556 
01557                         if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(originatee_channel, CF_DIALPLAN)) {
01558                                 switch_channel_flip_cid(originatee_channel);
01559                                 switch_channel_set_flag(originatee_channel, CF_DIALPLAN);
01560                         }
01561 
01562                         if (switch_channel_direction(originator_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(originator_channel, CF_DIALPLAN)) {
01563                                 switch_channel_flip_cid(originator_channel);
01564                                 switch_channel_set_flag(originator_channel, CF_DIALPLAN);
01565                         }
01566 
01567 
01568                         if (switch_channel_down_nosig(originator_channel)) {
01569                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_DEBUG, "%s is hungup refusing to bridge.\n", switch_channel_get_name(originatee_channel));
01570                                 switch_core_session_rwunlock(originator_session);
01571                                 switch_core_session_rwunlock(originatee_session);
01572                                 return SWITCH_STATUS_FALSE;
01573                         }
01574 
01575                         if (!switch_channel_media_up(originator_channel)) {
01576                                 if (switch_channel_media_up(originatee_channel)) {
01577                                         swap_session = originator_session;
01578                                         originator_session = originatee_session;
01579                                         originatee_session = swap_session;
01580 
01581                                         swap_channel = originator_channel;
01582                                         originator_channel = originatee_channel;
01583                                         originatee_channel = swap_channel;
01584                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originatee_session), SWITCH_LOG_WARNING, "reversing order of channels so this will work!\n");
01585                                 } else {
01586                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_CRIT, "Neither channel is answered, cannot bridge them.\n");
01587                                         switch_core_session_rwunlock(originator_session);
01588                                         switch_core_session_rwunlock(originatee_session);
01589                                         return SWITCH_STATUS_FALSE;
01590                                 }
01591                         }
01592 
01593                         cleanup_proxy_mode_a(originator_session);
01594                         cleanup_proxy_mode_a(originatee_session);
01595 
01596                         /* override transmit state for originator_channel to bridge to originatee_channel 
01597                          * install pointer to originatee_session into originator_channel
01598                          * set CF_TRANSFER on both channels and change state to CS_SOFT_EXECUTE to
01599                          * interrupt anything they are already doing.
01600                          * originatee_session will fall asleep and originator_session will bridge to it
01601                          */
01602 
01603                         switch_channel_set_flag(originator_channel, CF_REDIRECT);
01604                         switch_channel_set_flag(originatee_channel, CF_REDIRECT);
01605 
01606 
01607                         switch_channel_set_variable(originator_channel, SWITCH_UUID_BRIDGE, switch_core_session_get_uuid(originatee_session));
01608                         switch_channel_set_variable(originator_channel, SWITCH_BRIDGE_CHANNEL_VARIABLE, switch_channel_get_name(originatee_channel));
01609                         switch_channel_set_variable(originator_channel, SWITCH_BRIDGE_UUID_VARIABLE, switch_core_session_get_uuid(originatee_session));
01610                         switch_channel_set_variable(originator_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(originatee_session));
01611                         switch_channel_set_variable(originatee_channel, SWITCH_BRIDGE_CHANNEL_VARIABLE, switch_channel_get_name(originator_channel));
01612                         switch_channel_set_variable(originatee_channel, SWITCH_BRIDGE_UUID_VARIABLE, switch_core_session_get_uuid(originator_session));
01613                         switch_channel_set_variable(originatee_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(originator_session));
01614 
01615 
01616                         originator_cp = switch_channel_get_caller_profile(originator_channel);
01617                         originatee_cp = switch_channel_get_caller_profile(originatee_channel);
01618 
01619 
01620                         switch_channel_set_variable(originatee_channel, "original_destination_number", originatee_cp->destination_number);
01621                         switch_channel_set_variable(originatee_channel, "original_caller_id_name", originatee_cp->caller_id_name);
01622                         switch_channel_set_variable(originatee_channel, "original_caller_id_number", originatee_cp->caller_id_number);
01623 
01624                         switch_channel_set_variable(originator_channel, "original_destination_number", originator_cp->destination_number);
01625                         switch_channel_set_variable(originator_channel, "original_caller_id_name", originator_cp->caller_id_name);
01626                         switch_channel_set_variable(originator_channel, "original_caller_id_number", originator_cp->caller_id_number);
01627 
01628 
01629                         switch_channel_set_originator_caller_profile(originatee_channel, switch_caller_profile_clone(originatee_session, originator_cp));
01630                         switch_channel_set_originatee_caller_profile(originator_channel, switch_caller_profile_clone(originator_session, originatee_cp));
01631 
01632                         switch_channel_stop_broadcast(originator_channel);
01633                         switch_channel_stop_broadcast(originatee_channel);
01634 
01635                         switch_channel_set_flag(originator_channel, CF_TRANSFER);
01636                         switch_channel_set_flag(originatee_channel, CF_TRANSFER);
01637 
01638 
01639                         switch_channel_clear_flag(originator_channel, CF_ORIGINATING);
01640                         switch_channel_clear_flag(originatee_channel, CF_ORIGINATING);
01641 
01642 
01643                         originator_cp->transfer_source = switch_core_sprintf(originator_cp->pool, 
01644                                                                                                                                  "%ld:%s:uuid_br:%s", (long)switch_epoch_time_now(NULL), originator_cp->uuid_str, 
01645                                                                                                                                  switch_core_session_get_uuid(originatee_session));
01646                         switch_channel_add_variable_var_check(originator_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, 
01647                                                                                                   originator_cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
01648                         switch_channel_set_variable(originator_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, originator_cp->transfer_source);
01649 
01650                         
01651                         originatee_cp->transfer_source = switch_core_sprintf(originatee_cp->pool,
01652                                                                                                                                  "%ld:%s:uuid_br:%s", (long)switch_epoch_time_now(NULL), originatee_cp->uuid_str, 
01653                                                                                                                                  switch_core_session_get_uuid(originator_session));
01654                         switch_channel_add_variable_var_check(originatee_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, 
01655                                                                                                   originatee_cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
01656                         switch_channel_set_variable(originatee_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, originatee_cp->transfer_source);
01657 
01658                         /* change the states and let the chips fall where they may */
01659 
01660                         //switch_channel_set_variable(originator_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
01661                         //switch_channel_set_variable(originatee_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
01662                         switch_channel_clear_state_handler(originator_channel, NULL);
01663                         switch_channel_clear_state_handler(originatee_channel, NULL);
01664                         switch_channel_clear_flag_recursive(originator_channel, CF_BRIDGE_ORIGINATOR);
01665                         switch_channel_clear_flag_recursive(originatee_channel, CF_BRIDGE_ORIGINATOR);
01666                         switch_channel_set_state_flag(originator_channel, CF_BRIDGE_ORIGINATOR);
01667                         switch_channel_clear_state_flag(originatee_channel, CF_BRIDGE_ORIGINATOR);
01668                         switch_channel_add_state_handler(originator_channel, &uuid_bridge_state_handlers);
01669                         switch_channel_add_state_handler(originatee_channel, &uuid_bridge_state_handlers);
01670 
01671                         state = switch_channel_get_state(originator_channel);
01672                         switch_channel_set_state(originator_channel, state == CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE);
01673                         state = switch_channel_get_state(originatee_channel);
01674                         switch_channel_set_state(originatee_channel, state == CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE);
01675 
01676                         status = SWITCH_STATUS_SUCCESS;
01677 
01678                         switch_ivr_bridge_display(originator_session, originatee_session);
01679 
01680                         /* release the read locks we have on the channels */
01681                         switch_core_session_rwunlock(originator_session);
01682                         switch_core_session_rwunlock(originatee_session);
01683 
01684                 } else {
01685                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_DEBUG, "originatee uuid %s is not present\n", originatee_uuid);
01686                         switch_core_session_rwunlock(originator_session);
01687                 }
01688         } else {
01689                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_DEBUG, "originator uuid %s is not present\n", originator_uuid);
01690         }
01691 
01692         return status;
01693 }

switch_status_t switch_ivr_wait_for_silence ( switch_core_session_t session,
uint32_t  thresh,
uint32_t  silence_hits,
uint32_t  listen_hits,
uint32_t  timeout_ms,
const char *  file 
)

Definition at line 1733 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, switch_frame::buflen, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_codec::implementation, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, switch_frame::samples, switch_codec_implementation::samples_per_packet, switch_channel_ready, SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_core_codec_destroy(), switch_core_codec_init, switch_core_file_close(), switch_core_file_open, switch_core_file_read(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_read_frame(), switch_core_session_reset(), switch_core_session_set_read_codec(), switch_core_session_write_frame(), SWITCH_FALSE, SWITCH_FILE_DATA_SHORT, SWITCH_FILE_FLAG_READ, SWITCH_IO_FLAG_NONE, SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, SWITCH_STATUS_FALSE, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_zmalloc.

01735 {
01736         uint32_t score, count = 0, j = 0;
01737         double energy = 0;
01738         switch_channel_t *channel = switch_core_session_get_channel(session);
01739         int divisor = 0;
01740         uint32_t org_silence_hits = silence_hits;
01741         uint32_t channels;
01742         switch_frame_t *read_frame;
01743         switch_status_t status = SWITCH_STATUS_FALSE;
01744         int16_t *data;
01745         uint32_t listening = 0;
01746         int countdown = 0;
01747         switch_codec_t raw_codec = { 0 };
01748         int16_t *abuf = NULL;
01749         switch_frame_t write_frame = { 0 };
01750         switch_file_handle_t fh = { 0 };
01751         int32_t sample_count = 0;
01752         switch_codec_implementation_t read_impl = { 0 };
01753         switch_core_session_get_read_impl(session, &read_impl);
01754 
01755 
01756         if (timeout_ms) {
01757                 sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
01758         }
01759 
01760         if (file) {
01761                 if (switch_core_file_open(&fh,
01762                                                                   file,
01763                                                                   read_impl.number_of_channels,
01764                                                                   read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
01765                         switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
01766                         return SWITCH_STATUS_NOTFOUND;
01767                 }
01768                 switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE);
01769                 write_frame.data = abuf;
01770                 write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
01771         }
01772 
01773 
01774         if (switch_core_codec_init(&raw_codec,
01775                                                            "L16",
01776                                                            NULL,
01777                                                            read_impl.actual_samples_per_second,
01778                                                            read_impl.microseconds_per_packet / 1000,
01779                                                            1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
01780                                                            NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
01781 
01782                 status = SWITCH_STATUS_FALSE;
01783                 goto end;
01784         }
01785 
01786         write_frame.codec = &raw_codec;
01787 
01788         divisor = read_impl.actual_samples_per_second / 8000;
01789         channels = read_impl.number_of_channels;
01790 
01791         switch_core_session_set_read_codec(session, &raw_codec);
01792 
01793         while (switch_channel_ready(channel)) {
01794 
01795                 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
01796 
01797                 if (!SWITCH_READ_ACCEPTABLE(status)) {
01798                         break;
01799                 }
01800 
01801                 if (sample_count) {
01802                         sample_count -= raw_codec.implementation->samples_per_packet;
01803                         if (sample_count <= 0) {
01804                                 break;
01805                         }
01806                 }
01807 
01808                 if (abuf) {
01809                         switch_size_t olen = raw_codec.implementation->samples_per_packet;
01810 
01811                         if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
01812                                 break;
01813                         }
01814 
01815                         write_frame.samples = (uint32_t) olen;
01816                         write_frame.datalen = (uint32_t) (olen * sizeof(int16_t));
01817                         if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
01818                                 break;
01819                         }
01820                 }
01821 
01822                 if (countdown) {
01823                         if (!--countdown) {
01824                                 break;
01825                         } else {
01826                                 continue;
01827                         }
01828                 }
01829 
01830                 data = (int16_t *) read_frame->data;
01831 
01832                 for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
01833                         energy += abs(data[j++]);
01834                         j += channels;
01835                 }
01836 
01837                 score = (uint32_t) (energy / (read_frame->samples / divisor));
01838 
01839                 if (score >= thresh) {
01840                         listening++;
01841                 }
01842 
01843                 if (listening > listen_hits && score < thresh) {
01844                         if (!--silence_hits) {
01845                                 countdown = 25;
01846                         }
01847                 } else {
01848                         silence_hits = org_silence_hits;
01849                 }
01850         }
01851 
01852         switch_core_session_reset(session, SWITCH_FALSE, SWITCH_TRUE);
01853         switch_core_codec_destroy(&raw_codec);
01854 
01855   end:
01856 
01857         if (abuf) {
01858                 switch_core_file_close(&fh);
01859                 free(abuf);
01860         }
01861 
01862         return status;
01863 }

switch_status_t switch_play_and_get_digits ( switch_core_session_t session,
uint32_t  min_digits,
uint32_t  max_digits,
uint32_t  max_tries,
uint32_t  timeout,
const char *  valid_terminators,
const char *  audio_file,
const char *  bad_input_audio_file,
const char *  var_name,
char *  digit_buffer,
uint32_t  digit_buffer_length,
const char *  digits_regex,
uint32_t  digit_timeout,
const char *  transfer_on_failure 
)

Play a sound and gather digits with the number of retries specified if the user doesn't give digits in the set time.

Parameters:
session the current session to play sound to and collect digits
min_digits the fewest digits allowed for the response to be valid
max_digits the max number of digits to accept
max_tries number of times to replay the sound and capture digits
timeout time to wait for input (this is per iteration, so total possible time = max_tries * (timeout + audio playback length)
valid_terminators for input that can include # or * (useful for variable length prompts)
audio_file file to play
bad_input_audio_file file to play if the input from the user was invalid
var_name variable name to put results in
digit_buffer variable digits captured will be put back into (empty if capture failed)
digit_buffer_length length of the buffer for digits (should be the same or larger than max_digits)
digits_regex the qualifying regex
Returns:
switch status, used to note status of channel (will still return success if digit capture failed)
Note:
to test for digit capture failure look for \0 in the first position of the buffer

Definition at line 1982 of file switch_ivr_play_say.c.

References switch_channel_get_variable, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_core_session_get_channel(), switch_core_session_strdup, switch_ivr_play_file(), switch_ivr_read(), switch_ivr_session_transfer(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_READ_TERMINATOR_USED_VARIABLE, switch_regex_match(), switch_separate_string(), SWITCH_STATUS_FALSE, SWITCH_STATUS_RESTART, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, SWITCH_STATUS_TOO_SMALL, and zstr.

Referenced by CoreSession::playAndGetDigits().

01996 {
01997         switch_channel_t *channel = switch_core_session_get_channel(session);
01998 
01999         while (switch_channel_ready(channel) && max_tries) {
02000                 switch_status_t status;
02001 
02002                 memset(digit_buffer, 0, digit_buffer_length);
02003 
02004                 status = switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name,
02005                                                                  digit_buffer, digit_buffer_length, timeout, valid_terminators, digit_timeout);
02006 
02007                 if (status == SWITCH_STATUS_RESTART) {
02008                         return status;
02009                 }
02010 
02011                 if (status == SWITCH_STATUS_TIMEOUT && strlen(digit_buffer) >= min_digits) {
02012                         status = SWITCH_STATUS_SUCCESS;
02013                 }
02014 
02015                 if ((min_digits == 0) && (strlen(digit_buffer) == 0) && switch_channel_get_variable(channel, SWITCH_READ_TERMINATOR_USED_VARIABLE) != 0)
02016                 {
02017                         return SWITCH_STATUS_SUCCESS;
02018                 }
02019 
02020                 if (!(status == SWITCH_STATUS_TOO_SMALL && strlen(digit_buffer) == 0)) {
02021                         if (status == SWITCH_STATUS_SUCCESS) {
02022                                 if (!zstr(digit_buffer)) {
02023                                         if (zstr(digits_regex)) {
02024                                                 return SWITCH_STATUS_SUCCESS;
02025                                         }
02026                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Test Regex [%s][%s]\n", digit_buffer, digits_regex);
02027                                         if (switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) {
02028                                                 return SWITCH_STATUS_SUCCESS;
02029                                         } else {
02030                                                 switch_channel_set_variable(channel, var_name, NULL);
02031                                         }
02032                                 }
02033                         }
02034                 }
02035 
02036                 if (!switch_channel_ready(channel)) {
02037                         break;
02038                 }
02039 
02040                 switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL);
02041                 max_tries--;
02042         }
02043 
02044         memset(digit_buffer, 0, digit_buffer_length);
02045         
02046         /* If we get here then check for transfer-on-failure ext/dp/context */
02047         /* split this arg on spaces to get ext, dp, and context */
02048                 
02049         if (!zstr(transfer_on_failure)) {
02050                 const char *failure_ext = NULL;
02051                 const char *failure_dialplan = NULL;
02052                 const char *failure_context = NULL;
02053                 char *target[4];
02054                 char *mydata = switch_core_session_strdup(session, transfer_on_failure);
02055                 int argc;
02056                 
02057                 argc = switch_separate_string(mydata, ' ', target, (sizeof(target) / sizeof(target[0])));
02058                 
02059                 if ( argc < 1 ) {
02060                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,"Bad target for PAGD failure: [%s]\n", transfer_on_failure);
02061                         return SWITCH_STATUS_FALSE;
02062                 }
02063                 
02064                 if ( argc > 0 ) {
02065                         failure_ext = target[0];
02066                 }
02067                 
02068                 if ( argc > 1 ) {
02069                         failure_dialplan = target[1];
02070                 }
02071 
02072                 if ( argc > 2 ) {
02073                         failure_context = target[2];
02074                 }
02075 
02076                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, 
02077                         "PAGD failure! Transfer to: %s / %s / %s\n", failure_ext, failure_dialplan, failure_context);
02078                         
02079                 switch_ivr_session_transfer(session,failure_ext, failure_dialplan, failure_context);
02080                 return SWITCH_STATUS_FALSE;
02081         } 
02082         
02083         return SWITCH_STATUS_FALSE;     
02084 }


Generated on Wed May 16 04:00:19 2012 for FreeSWITCH API Documentation by  doxygen 1.4.7