FreeSWITCH API Documentation  1.7.0
Modules | Typedefs | Functions
IVR Library
+ Collaboration diagram for IVR Library:

Modules

 IVR Menu Library
 

Typedefs

typedef struct
switch_ivr_digit_stream_parser 
switch_ivr_digit_stream_parser_t
 
typedef struct
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. More...
 
switch_status_t switch_ivr_generate_xml_cdr (switch_core_session_t *session, switch_xml_t *xml_cdr)
 Generate an XML CDR report. More...
 
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. More...
 
switch_status_t switch_ivr_parse_all_events (switch_core_session_t *session)
 Parse all commands from an event. More...
 
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_parse_signal_data (switch_core_session_t *session, switch_bool_t all, switch_bool_t only_session_thread)
 
switch_status_t switch_ivr_parse_next_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. More...
 
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. More...
 
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. More...
 
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. More...
 
switch_status_t switch_ivr_detect_speech_init (switch_core_session_t *session, const char *mod_name, const char *dest, switch_asr_handle_t *ah)
 Initialize background Speech detection on a session, so that parameters can be set, and grammars loaded. After calling this function, it is possible to call switch_ivr_set_param_detect_speech() to set recognition parameters. Calling switch_ivr_detect_speech_load_grammar() starts the speech recognition. More...
 
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. More...
 
switch_status_t switch_ivr_stop_detect_speech (switch_core_session_t *session)
 Stop background Speech detection on a session. More...
 
switch_status_t switch_ivr_pause_detect_speech (switch_core_session_t *session)
 Pause background Speech detection on a session. More...
 
switch_status_t switch_ivr_resume_detect_speech (switch_core_session_t *session)
 Resume background Speech detection on a session. More...
 
switch_status_t switch_ivr_detect_speech_load_grammar (switch_core_session_t *session, const char *grammar, const char *name)
 Load a grammar on a background speech detection handle. More...
 
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. More...
 
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. More...
 
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. More...
 
switch_status_t switch_ivr_detect_speech_disable_all_grammars (switch_core_session_t *session)
 Disable all grammars on a background speech detection handle. More...
 
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. More...
 
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. More...
 
switch_status_t switch_ivr_transfer_recordings (switch_core_session_t *orig_session, switch_core_session_t *new_session)
 
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. More...
 
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 More...
 
switch_status_t switch_ivr_stop_displace_session (switch_core_session_t *session, const char *file)
 Stop displacing a session. More...
 
switch_status_t switch_ivr_stop_record_session (switch_core_session_t *session, const char *file)
 Stop Recording a session. More...
 
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. More...
 
switch_status_t switch_ivr_stop_inband_dtmf_session (switch_core_session_t *session)
 Stop looking for DTMF inband. More...
 
switch_status_t switch_ivr_inband_dtmf_generate_session (switch_core_session_t *session, switch_bool_t read_stream)
 Start generating DTMF inband. More...
 
switch_status_t switch_ivr_stop_inband_dtmf_generate_session (switch_core_session_t *session)
 Stop generating DTMF inband. More...
 
switch_status_t switch_ivr_session_echo (switch_core_session_t *session, switch_input_args_t *args)
 
  • NEEDDESC -
More...
 
switch_status_t switch_ivr_stop_tone_detect_session (switch_core_session_t *session)
 Stop looking for TONES. More...
 
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. More...
 
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 More...
 
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 More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
switch_status_t switch_ivr_uuid_bridge (const char *originator_uuid, const char *originatee_uuid)
 Bridge two existing sessions. More...
 
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. More...
 
switch_status_t switch_ivr_3p_media (const char *uuid, switch_media_flag_t flags)
 
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. More...
 
switch_status_t switch_ivr_3p_nomedia (const char *uuid, switch_media_flag_t flags)
 
void switch_ivr_bg_media (const char *uuid, switch_media_flag_t flags, switch_bool_t on, switch_bool_t is3p, uint32_t delay)
 
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. More...
 
switch_status_t switch_ivr_hold_toggle_uuid (const char *uuid, const char *message, switch_bool_t moh)
 Toggles channel hold state of session. More...
 
switch_status_t switch_ivr_unhold_uuid (const char *uuid)
 Signal the session with a protocol specific unhold message. More...
 
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. More...
 
switch_status_t switch_ivr_unhold (switch_core_session_t *session)
 Signal the session with a protocol specific unhold message. More...
 
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. More...
 
switch_status_t switch_ivr_broadcast (const char *uuid, const char *path, switch_media_flag_t flags)
 Signal the session to broadcast audio. More...
 
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. More...
 
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. More...
 
switch_status_t switch_ivr_digit_stream_parser_destroy (switch_ivr_digit_stream_parser_t *parser)
 Destroy a digit stream parser object. More...
 
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. More...
 
switch_status_t switch_ivr_digit_stream_destroy (switch_ivr_digit_stream_t **stream)
 Destroys a digit stream object. More...
 
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. More...
 
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. More...
 
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. More...
 
switch_status_t switch_ivr_digit_stream_reset (switch_ivr_digit_stream_t *stream)
 Reset the collected digit stream to nothing. More...
 
switch_status_t switch_ivr_digit_stream_parser_set_terminator (switch_ivr_digit_stream_parser_t *parser, char digit)
 Set a digit string terminator. More...
 

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

Definition at line 679 of file switch_ivr.h.

Definition at line 681 of file switch_ivr.h.

Function Documentation

switch_status_t switch_ivr_3p_media ( const char *  uuid,
switch_media_flag_t  flags 
)

Definition at line 1564 of file switch_ivr.c.

References CF_3P_MEDIA_REQUESTED, CF_BRIDGE_ORIGINATOR, CF_BRIDGED, CF_EARLY_MEDIA, CF_MEDIA_ACK, CF_MEDIA_SET, CF_MEDIA_TRANS, CF_PROXY_MODE, CF_REQ_MEDIA, switch_core_session_message::from, switch_core_session_message::message_id, switch_core_session_message::numeric_arg, SMF_IMMEDIATE, SMF_REBRIDGE, SMF_REPLYONLY_A, SMF_REPLYONLY_B, switch_assert, switch_channel_clear_flag(), switch_channel_clear_state_handler(), switch_channel_get_name(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_set_variable, switch_channel_test_flag(), 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_ivr_uuid_bridge(), SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_MESSAGE_INDICATE_3P_MEDIA, SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS, SWITCH_SIGNAL_BRIDGE_VARIABLE, SWITCH_STATUS_GENERR, SWITCH_STATUS_INUSE, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_yield.

Referenced by media_thread_run().

1565 {
1566  const char *other_uuid = NULL;
1567  switch_channel_t *channel, *other_channel = NULL;
1568  switch_core_session_t *session, *other_session;
1569  switch_core_session_message_t msg = { 0 };
1571  uint8_t swap = 0;
1572  //switch_frame_t *read_frame = NULL;
1573 
1575  msg.from = __FILE__;
1576 
1577  if ((session = switch_core_session_locate(uuid))) {
1578  channel = switch_core_session_get_channel(session);
1579 
1581  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Operation is invalid\n");
1583  return SWITCH_STATUS_INUSE;
1584  }
1585 
1587 
1588  if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
1589  swap = 1;
1590  }
1591 
1592 
1593  status = SWITCH_STATUS_SUCCESS;
1594 
1595  /* If we had early media in bypass mode before, it is no longer relevant */
1596  if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
1597  switch_core_session_message_t msg2 = { 0 };
1598 
1600  msg2.from = __FILE__;
1601  switch_core_session_receive_message(session, &msg2);
1602  }
1603 
1604  if ((flags & SMF_REPLYONLY_A)) {
1605  msg.numeric_arg = 1;
1606  }
1607 
1609 
1611  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't re-establsh media on %s\n", switch_channel_get_name(channel));
1614  return SWITCH_STATUS_GENERR;
1615  }
1616 
1617  if ((flags & SMF_REPLYONLY_B)) {
1618  msg.numeric_arg = 1;
1619  } else {
1620  msg.numeric_arg = 0;
1621  }
1622 
1623  if ((flags & SMF_IMMEDIATE)) {
1625  switch_yield(250000);
1626  } else {
1627  switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1628  switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1629  switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1631  //switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1632  }
1633 
1634  if ((flags & SMF_REBRIDGE)
1636  && (other_session = switch_core_session_locate(other_uuid))) {
1637 
1638  other_channel = switch_core_session_get_channel(other_session);
1639  switch_assert(other_channel != NULL);
1640 
1642  switch_channel_set_variable(other_channel, "rtp_secure_media", "optional");
1643 
1644  switch_core_session_receive_message(other_session, &msg);
1645  switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1646  switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1647  switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1648  switch_channel_wait_for_flag(other_channel, CF_3P_MEDIA_REQUESTED, SWITCH_FALSE, 10000, NULL);
1649  //switch_core_session_read_frame(other_session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1650  switch_channel_clear_state_handler(other_channel, NULL);
1651  switch_core_session_rwunlock(other_session);
1652  }
1653  if (other_channel) {
1654  switch_channel_clear_state_handler(channel, NULL);
1655  }
1656 
1659 
1660  if (other_channel) {
1661  if (swap) {
1662  switch_ivr_uuid_bridge(other_uuid, uuid);
1663  } else {
1664  switch_ivr_uuid_bridge(uuid, other_uuid);
1665  }
1666  switch_channel_wait_for_flag(channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
1667  switch_channel_wait_for_flag(other_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
1668  }
1669  }
1670 
1671  return status;
1672 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:201
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
void switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
clear a state handler table from a given channel
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_ivr_uuid_bridge(const char *originator_uuid, const char *originatee_uuid)
Bridge two existing sessions.
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_status_t
Common return values.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_channel_set_flag(_c, _f)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_assert(expr)
#define switch_channel_set_variable(_channel, _var, _val)
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_status_t switch_ivr_3p_nomedia ( const char *  uuid,
switch_media_flag_t  flags 
)

Definition at line 1774 of file switch_ivr.c.

References CF_3P_NOMEDIA_REQUESTED, CF_3P_NOMEDIA_REQUESTED_BLEG, CF_BRIDGE_ORIGINATOR, CF_MEDIA_ACK, CF_MEDIA_TRANS, 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_core_session_message::string_arg, SWITCH_BRIDGE_VARIABLE, switch_channel_clear_flag(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_set_state, switch_channel_set_variable, 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_LOG_ERROR, switch_log_printf(), SWITCH_MESSAGE_INDICATE_3P_NOMEDIA, SWITCH_R_SDP_VARIABLE, SWITCH_STATUS_GENERR, SWITCH_STATUS_INUSE, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_yield.

Referenced by audio_bridge_thread(), and media_thread_run().

1775 {
1776  const char *other_uuid;
1777  switch_channel_t *channel, *other_channel = NULL;
1778  switch_core_session_t *session, *other_session = NULL;
1779  switch_core_session_message_t msg = { 0 };
1781  uint8_t swap = 0;
1782 
1784  msg.from = __FILE__;
1785 
1786  if ((session = switch_core_session_locate(uuid))) {
1787  status = SWITCH_STATUS_SUCCESS;
1788  channel = switch_core_session_get_channel(session);
1789 
1790  if (switch_channel_test_flag(channel, CF_MEDIA_TRANS) || (!(flags & SMF_FORCE) && switch_channel_test_flag(channel, CF_PROXY_MODE))) {
1791  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Operation is invalid\n");
1793  return SWITCH_STATUS_INUSE;
1794  }
1795 
1797 
1798  if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
1799  swap = 1;
1800  }
1801 
1802  if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_PROXY_MODE)) {
1803  if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
1804  (other_session = switch_core_session_locate(other_uuid))) {
1805  other_channel = switch_core_session_get_channel(other_session);
1806 
1809 
1810  switch_channel_set_flag(other_channel, CF_RESET);
1811  switch_channel_set_flag(other_channel, CF_REDIRECT);
1812 
1815  switch_core_session_receive_message(session, &msg);
1816 
1817  if (!switch_core_session_in_thread(session)) {
1819  }
1820 
1821  switch_channel_set_state(other_channel, CS_PARK);
1822 
1823  if (switch_core_session_in_thread(session)) {
1824  switch_yield(100000);
1825  } else {
1826  switch_channel_wait_for_state(other_channel, channel, CS_PARK);
1827  }
1828 
1829 
1830  if (!switch_core_session_in_thread(session)) {
1831  switch_channel_wait_for_state(channel, NULL, CS_PARK);
1832  }
1833 
1834  switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1835  switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1837 
1841 
1842 
1843  switch_core_session_receive_message(other_session, &msg);
1844  switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1845  switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1847  }
1848 
1849  if (other_channel) {
1850  if (swap) {
1851  switch_ivr_signal_bridge(other_session, session);
1852  } else {
1853  switch_ivr_signal_bridge(session, other_session);
1854  }
1855 
1856  if (switch_core_session_in_thread(session)) {
1857  switch_yield(100000);
1858  } else {
1859  switch_channel_wait_for_state(other_channel, channel, CS_HIBERNATE);
1860  }
1861 
1862  if (!switch_core_session_in_thread(session)) {
1863  switch_channel_wait_for_state(channel, other_channel, CS_HIBERNATE);
1864  }
1865  switch_core_session_rwunlock(other_session);
1866  }
1867  }
1868 
1871  }
1872 
1873 
1874 
1875  return status;
1876 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
#define switch_channel_get_variable(_c, _v)
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:199
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
#define SWITCH_R_SDP_VARIABLE
Definition: switch_types.h:196
switch_status_t
Common return values.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_channel_set_flag(_c, _f)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
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.
#define switch_channel_set_variable(_channel, _var, _val)
switch_bool_t switch_core_session_in_thread(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 
)

Definition at line 398 of file switch_ivr.c.

References switch_codec_implementation::actual_samples_per_second, switch_frame::buflen, CF_UNICAST, switch_frame::codec, switch_frame::data, fail, switch_unicast_conninfo::flag_mutex, switch_codec::implementation, switch_unicast_conninfo::local_addr, switch_unicast_conninfo::local_ip, switch_unicast_conninfo::local_port, switch_codec_implementation::microseconds_per_packet, switch_unicast_conninfo::read_codec, switch_unicast_conninfo::remote_addr, switch_unicast_conninfo::remote_ip, switch_unicast_conninfo::remote_port, switch_unicast_conninfo::session, switch_unicast_conninfo::socket, 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, SWITCH_UNSPEC, switch_unicast_conninfo::transport, switch_unicast_conninfo::type, switch_unicast_conninfo::write_frame, and switch_unicast_conninfo::write_frame_data.

Referenced by switch_ivr_parse_event().

402 {
404  switch_unicast_conninfo_t *conninfo = switch_core_session_alloc(session, sizeof(*conninfo));
405  switch_codec_t *read_codec;
406 
407  switch_assert(conninfo != NULL);
408 
409  conninfo->local_ip = switch_core_session_strdup(session, local_ip);
410  conninfo->local_port = local_port;
411 
412  conninfo->remote_ip = switch_core_session_strdup(session, remote_ip);
413  conninfo->remote_port = remote_port;
414  conninfo->session = session;
415 
416  if (!strcasecmp(transport, "udp")) {
417  conninfo->type = AF_INET;
418  conninfo->transport = SOCK_DGRAM;
419  } else if (!strcasecmp(transport, "tcp")) {
420  conninfo->type = AF_INET;
421  conninfo->transport = SOCK_STREAM;
422  } else {
423  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid transport %s\n", transport);
424  goto fail;
425  }
426 
427  if (flags) {
428  if (strstr(flags, "native")) {
429  switch_set_flag(conninfo, SUF_NATIVE);
430  }
431  }
432 
434 
435  read_codec = switch_core_session_get_read_codec(session);
436 
437  if (!switch_test_flag(conninfo, SUF_NATIVE)) {
438  if (switch_core_codec_init(&conninfo->read_codec,
439  "L16",
440  NULL,
441  NULL,
443  read_codec->implementation->microseconds_per_packet / 1000,
447  "Raw Codec Activation Success L16@%uhz 1 channel %dms\n",
449  } else {
450  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n",
452  goto fail;
453  }
454  }
455 
456  conninfo->write_frame.data = conninfo->write_frame_data;
457  conninfo->write_frame.buflen = sizeof(conninfo->write_frame_data);
458  conninfo->write_frame.codec = switch_test_flag(conninfo, SUF_NATIVE) ? read_codec : &conninfo->read_codec;
459 
460  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "connect %s:%d->%s:%d\n",
461  conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
462 
463  if (switch_sockaddr_info_get(&conninfo->local_addr,
464  conninfo->local_ip, SWITCH_UNSPEC, conninfo->local_port, 0,
466  goto fail;
467  }
468 
469  if (switch_sockaddr_info_get(&conninfo->remote_addr,
470  conninfo->remote_ip, SWITCH_UNSPEC, conninfo->remote_port, 0,
472  goto fail;
473  }
474 
475  if (switch_socket_create(&conninfo->socket, AF_INET, SOCK_DGRAM, 0, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
476  if (switch_socket_bind(conninfo->socket, conninfo->local_addr) != SWITCH_STATUS_SUCCESS) {
477  goto fail;
478  }
479  } else {
480  goto fail;
481  }
482 
483  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Created unicast connection %s:%d->%s:%d\n",
484  conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
485  switch_channel_set_private(channel, "unicast", conninfo);
488  return SWITCH_STATUS_SUCCESS;
489 
490  fail:
491 
492  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure creating unicast connection %s:%d->%s:%d\n",
493  conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
494  return SWITCH_STATUS_FALSE;
495 }
switch_sockaddr_t * local_addr
Definition: switch_ivr.h:57
switch_socket_t * socket
Definition: switch_ivr.h:52
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_status_t switch_socket_bind(switch_socket_t *sock, switch_sockaddr_t *sa)
Definition: switch_apr.c:719
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
#define fail()
Definition: tone2wav.c:70
switch_sockaddr_t * remote_addr
Definition: switch_ivr.h:58
switch_codec_t * codec
Definition: switch_frame.h:45
switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:59
switch_port_t remote_port
Definition: switch_ivr.h:56
switch_codec_t read_codec
Definition: switch_ivr.h:49
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:270
#define switch_set_flag_locked(obj, flag)
Set a flag on an arbitrary object while locked.
Definition: switch_utils.h:638
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
switch_mutex_t * flag_mutex
Definition: switch_ivr.h:59
switch_frame_t write_frame
Definition: switch_ivr.h:50
switch_status_t switch_socket_create(switch_socket_t **new_sock, int family, int type, int protocol, switch_memory_pool_t *pool)
Definition: switch_apr.c:704
#define SWITCH_UNSPEC
Definition: switch_apr.h:1022
#define switch_channel_set_flag(_c, _f)
switch_core_session_t * session
Definition: switch_ivr.h:48
switch_port_t local_port
Definition: switch_ivr.h:54
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
#define switch_assert(expr)
switch_status_t switch_sockaddr_info_get(switch_sockaddr_t **sa, const char *hostname, int32_t family, switch_port_t port, int32_t flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:817
switch_byte_t write_frame_data[SWITCH_RECOMMENDED_BUFFER_SIZE]
Definition: switch_ivr.h:51
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
void switch_ivr_bg_media ( const char *  uuid,
switch_media_flag_t  flags,
switch_bool_t  on,
switch_bool_t  is3p,
uint32_t  delay 
)

Definition at line 2014 of file switch_ivr.c.

References media_job_t::delay, media_job_t::flags, switch_thread_data_s::func, media_job_t::is3p, media_thread_run(), switch_thread_data_s::obj, media_job_t::on, pool, switch_thread_data_s::pool, media_job_t::pool, switch_core_alloc, switch_core_new_memory_pool, switch_core_strdup, switch_thread_pool_launch_thread(), and media_job_t::uuid.

Referenced by switch_core_media_toggle_hold().

2015 {
2018  media_job_t *job;
2019 
2021  td = switch_core_alloc(pool, sizeof(*td));
2022  job = switch_core_alloc(pool, sizeof(*job));
2023  td->func = media_thread_run;
2024  job->pool = pool;
2025  job->uuid = switch_core_strdup(pool, uuid);
2026  job->flags = flags;
2027  job->on = on;
2028  job->is3p = is3p;
2029  job->delay = delay;
2030  td->obj = job;
2031  td->pool = pool;
2033 
2034 }
const char * uuid
Definition: switch_ivr.c:1981
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
switch_memory_pool_t * pool
switch_memory_pool_t * pool
Definition: switch_core.h:69
switch_memory_pool_t * pool
Definition: switch_ivr.c:1980
switch_bool_t on
Definition: switch_ivr.c:1983
uint32_t delay
Definition: switch_ivr.c:1985
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:682
switch_thread_start_t func
Definition: switch_core.h:66
static void *SWITCH_THREAD_FUNC media_thread_run(switch_thread_t *thread, void *obj)
Definition: switch_ivr.c:1988
struct apr_pool_t switch_memory_pool_t
switch_media_flag_t flags
Definition: switch_ivr.c:1982
switch_bool_t is3p
Definition: switch_ivr.c:1984
switch_status_t switch_thread_pool_launch_thread(switch_thread_data_t **tdp)
void switch_ivr_bridge_display ( switch_core_session_t session,
switch_core_session_t peer_session 
)

Definition at line 293 of file switch_ivr_bridge.c.

References send_display().

Referenced by audio_bridge_thread(), and switch_ivr_signal_bridge().

294 {
295 
296  send_display(session, peer_session);
297  send_display(peer_session, session);
298 
299 }
static void send_display(switch_core_session_t *session, switch_core_session_t *peer_session)
switch_status_t switch_ivr_broadcast ( const char *  uuid,
const char *  path,
switch_media_flag_t  flags 
)

Signal the session to broadcast audio.

Parameters
uuidthe uuid of the session to broadcast on
paththe path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>"
flagsflags 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 4963 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_partner_uuid(), 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_STACK_BOTTOM, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

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

4964 {
4965  switch_channel_t *channel;
4966  switch_core_session_t *session, *master;
4967  switch_event_t *event;
4968  switch_core_session_t *other_session = NULL;
4969  const char *other_uuid = NULL;
4970  char *app = "playback";
4971  char *cause = NULL;
4972  char *mypath;
4973  char *p;
4974  int app_flags = 0, nomedia = 0;
4975 
4976  switch_assert(path);
4977 
4978  if (!(master = session = switch_core_session_locate(uuid))) {
4979  return SWITCH_STATUS_FALSE;
4980  }
4981 
4982  channel = switch_core_session_get_channel(session);
4983 
4984  mypath = strdup(path);
4985  assert(mypath);
4986 
4987  if ((p = strchr(mypath, ':')) && *(p + 1) == ':') {
4988  app = mypath;
4989  *p++ = '\0';
4990  *p++ = '\0';
4991  path = p;
4992  }
4993 
4994  if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
4995  nomedia = 1;
4997  }
4998 
4999  if ((cause = strchr(app, '!'))) {
5000  *cause++ = '\0';
5001  if (!cause) {
5002  cause = "normal_clearing";
5003  }
5004  }
5005 
5006  if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_partner_uuid(channel))
5007  && (other_session = switch_core_session_locate(other_uuid))) {
5008  if ((flags & SMF_EXEC_INLINE)) {
5009  switch_core_session_execute_application_get_flags(other_session, app, path, &app_flags);
5010  nomedia = 0;
5011  } else {
5012  switch_core_session_get_app_flags(app, &app_flags);
5014  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
5015  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
5016  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path);
5017  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
5018 
5019  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);
5020 
5021  if ((flags & SMF_LOOP)) {
5022  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1);
5023  }
5024 
5025  if ((flags & SMF_HOLD_BLEG)) {
5026  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true");
5027  }
5028 
5029  switch_core_session_queue_private_event(other_session, &event, (flags & SMF_PRIORITY));
5030  }
5031  }
5032 
5033  switch_core_session_rwunlock(other_session);
5034  master = other_session;
5035  other_session = NULL;
5036  }
5037 
5038  if ((app_flags & SAF_MEDIA_TAP)) {
5039  nomedia = 0;
5040  }
5041 
5042  if ((flags & SMF_ECHO_ALEG)) {
5043  if ((flags & SMF_EXEC_INLINE)) {
5044  nomedia = 0;
5045  switch_core_session_execute_application(session, app, path);
5046  } else {
5048  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
5049  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
5050  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path);
5051  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
5052  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);
5053 
5054  if ((flags & SMF_LOOP)) {
5055  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1);
5056  }
5057  if ((flags & SMF_HOLD_BLEG)) {
5058  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true");
5059  }
5060 
5061  switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY));
5062 
5063  if (nomedia)
5065  }
5066  }
5067  master = session;
5068  }
5069 
5070  if (cause) {
5072  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
5073  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", "hangup");
5074  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", cause);
5075  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
5076  switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY));
5077  }
5078  }
5079 
5081  switch_safe_free(mypath);
5082 
5083  return SWITCH_STATUS_SUCCESS;
5084 }
const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
switch_status_t switch_event_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *fmt,...) PRINTF_FUNCTION(4
Add a header to an event.
Representation of an event.
Definition: switch_event.h:80
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.
Definition: switch_ivr.c:1674
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
#define switch_core_session_execute_application(_a, _b, _c)
Execute an application on a session.
Definition: switch_core.h:1103
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_session_get_app_flags(const char *app, int32_t *flags)
switch_status_t switch_core_session_execute_application_get_flags(_In_ switch_core_session_t *session, _In_ const char *app, _In_opt_z_ const char *arg, _Out_opt_ int32_t *flags)
Execute an application on a session.
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_status_t switch_core_session_queue_private_event(_In_ switch_core_session_t *session, _Inout_ switch_event_t **event, switch_bool_t priority)
Queue a private event on a given session.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
#define switch_channel_set_flag(_c, _f)
#define switch_assert(expr)
void switch_ivr_broadcast_in_thread ( switch_core_session_t session,
const char *  app,
int  flags 
)

Definition at line 3919 of file switch_ivr_async.c.

References bch_t::app, bcast_thread(), bch_t::flags, pool, bch_t::session, switch_assert, switch_core_session_alloc, switch_core_session_get_pool(), switch_thread_create(), SWITCH_THREAD_STACKSIZE, switch_threadattr_create(), switch_threadattr_detach_set(), switch_threadattr_stacksize_set(), and thread.

Referenced by meta_on_dtmf().

3920 {
3922  switch_threadattr_t *thd_attr = NULL;
3924  bch_t *bch;
3925 
3926  switch_assert(session);
3927 
3928  pool = switch_core_session_get_pool(session);
3929 
3930  bch = switch_core_session_alloc(session, sizeof(*bch));
3931  bch->session = session;
3932  bch->app = app;
3933  bch->flags = flags;
3934 
3935 
3936  switch_threadattr_create(&thd_attr, pool);
3937  switch_threadattr_detach_set(thd_attr, 1);
3939  switch_thread_create(&thread, thd_attr, bcast_thread, bch, pool);
3940 }
static void *SWITCH_THREAD_FUNC bcast_thread(switch_thread_t *thread, void *obj)
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:660
switch_memory_pool_t * pool
const char * app
static switch_thread_t * thread
Definition: switch_log.c:279
switch_status_t switch_threadattr_detach_set(switch_threadattr_t *attr, int32_t on)
Definition: switch_apr.c:655
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:551
struct apr_thread_t switch_thread_t
Definition: switch_apr.h:941
switch_core_session_t * session
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
struct apr_pool_t switch_memory_pool_t
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:642
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:675
#define switch_assert(expr)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
void switch_ivr_clear_speech_cache ( switch_core_session_t session)

Definition at line 2629 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().

2630 {
2631  cached_speech_handle_t *cache_obj = NULL;
2633 
2636  if (cache_obj->timer.interval) {
2637  switch_core_timer_destroy(&cache_obj->timer);
2638  }
2639  if (cache_obj->sh.speech_interface) {
2640  switch_core_speech_close(&cache_obj->sh, &flags);
2641  }
2642  switch_core_codec_destroy(&cache_obj->codec);
2644  }
2645 }
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
uint32_t switch_speech_flag_t
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
#define SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME
Definition: switch_types.h:187
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags)
Close an open speech handle.
switch_speech_interface_t * speech_interface
switch_speech_handle_t sh
switch_status_t switch_core_timer_destroy(switch_timer_t *timer)
Destroy an allocated timer.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
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
sessionthe session to read.
argsarguements to pass for callbacks etc
timeouta timeout in milliseconds
Returns
SWITCH_STATUS_SUCCESS to keep the collection moving.

Definition at line 1173 of file switch_ivr.c.

References arg_recursion_check_start, arg_recursion_check_stop, 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, SWITCH_STATUS_TIMEOUT, and switch_frame::user_data.

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

1175 {
1178  switch_time_t abs_started = 0, digit_started = 0;
1179  uint32_t abs_elapsed = 0, digit_elapsed = 0;
1180 
1181  if (!args) {
1182  return SWITCH_STATUS_GENERR;
1183  }
1184 
1186 
1187  if (abs_timeout) {
1188  abs_started = switch_micro_time_now();
1189  }
1190  if (digit_timeout) {
1191  digit_started = switch_micro_time_now();
1192  }
1193 
1194  while (switch_channel_ready(channel)) {
1195  switch_frame_t *read_frame = NULL;
1196  switch_event_t *event;
1197  switch_dtmf_t dtmf = { 0 };
1198 
1199  if (switch_channel_test_flag(channel, CF_BREAK)) {
1201  status = SWITCH_STATUS_BREAK;
1202  break;
1203  }
1204 
1205  if (abs_timeout) {
1206  abs_elapsed = (uint32_t) ((switch_micro_time_now() - abs_started) / 1000);
1207  if (abs_elapsed >= abs_timeout) {
1208  status = SWITCH_STATUS_TIMEOUT;
1209  break;
1210  }
1211  }
1212  if (digit_timeout) {
1213  digit_elapsed = (uint32_t) ((switch_micro_time_now() - digit_started) / 1000);
1214  if (digit_elapsed >= digit_timeout) {
1215  status = SWITCH_STATUS_TIMEOUT;
1216  break;
1217  }
1218  }
1219 
1220 
1221  switch_ivr_parse_all_events(session);
1222 
1223 
1224  if (switch_channel_has_dtmf(channel)) {
1225  if (!args->input_callback && !args->buf && !args->dmachine) {
1226  status = SWITCH_STATUS_BREAK;
1227  break;
1228  }
1229  switch_channel_dequeue_dtmf(channel, &dtmf);
1230 
1231  if (args->dmachine) {
1232  char ds[2] = {dtmf.digit, '\0'};
1233  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
1234  break;
1235  }
1236  }
1237 
1238  if (args->input_callback) {
1239  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
1240  }
1241 
1242  if (digit_timeout) {
1243  digit_started = switch_micro_time_now();
1244  }
1245  }
1246 
1248  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
1249  if (ostatus != SWITCH_STATUS_SUCCESS) {
1250  status = ostatus;
1251  }
1252  switch_event_destroy(&event);
1253  }
1254 
1255  if (status != SWITCH_STATUS_SUCCESS) {
1256  break;
1257  }
1258 
1259  if (switch_channel_test_flag(channel, CF_SERVICE)) {
1260  switch_cond_next();
1261  } else {
1262  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1263  }
1264 
1265  if (!SWITCH_READ_ACCEPTABLE(status)) {
1266  break;
1267  }
1268 
1269  if (args && args->dmachine) {
1270  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1271  break;
1272  }
1273  }
1274 
1275  if (read_frame && args && (args->read_frame_callback)) {
1276  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
1277  break;
1278  }
1279  }
1280  }
1281 
1283 
1284  return status;
1285 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:310
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
#define arg_recursion_check_stop(_args)
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
int64_t switch_time_t
Definition: switch_apr.h:188
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
switch_input_callback_function_t input_callback
An abstraction of a data frame.
Definition: switch_frame.h:43
#define arg_recursion_check_start(_args)
void switch_cond_next(void)
Definition: switch_time.c:638
switch_read_frame_callback_function_t read_frame_callback
switch_status_t
Common return values.
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
switch_ivr_dmachine_t * dmachine
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
sessionthe session to read.
bufstrig to write to
buflenmax size of buf
maxdigitsmax number of digits to read
terminatorsdigits to end the collection
terminatoractual digit that caused the collection to end (if any)
first_timeouttimeout in ms
digit_timeoutdigit timeout in ms
abs_timeoutabs timeout in ms
Returns
SWITCH_STATUS_SUCCESS to keep the collection moving.

Definition at line 1287 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_destroy(), switch_core_codec_init, switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_read_frame(), switch_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_safe_free, 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().

1293 {
1294  switch_size_t i = 0, x = strlen(buf);
1297  switch_time_t started = 0, digit_started = 0;
1298  uint32_t abs_elapsed = 0, digit_elapsed = 0;
1299  uint32_t eff_timeout = 0;
1300  switch_frame_t write_frame = { 0 };
1301  unsigned char *abuf = NULL;
1302  switch_codec_implementation_t imp = { 0 };
1303  switch_codec_t codec = { 0 };
1304  int sval = 0;
1305  const char *var;
1306 
1307  if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
1308  switch_core_session_get_read_impl(session, &imp);
1309 
1310  if (switch_core_codec_init(&codec,
1311  "L16",
1312  NULL,
1313  NULL,
1314  imp.samples_per_second,
1315  imp.microseconds_per_packet / 1000,
1316  imp.number_of_channels,
1319  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
1321  return SWITCH_STATUS_FALSE;
1322  }
1323 
1324 
1325  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
1327 
1328  write_frame.codec = &codec;
1330  write_frame.data = abuf;
1331  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
1332  write_frame.datalen = imp.decoded_bytes_per_packet;
1333  write_frame.samples = write_frame.datalen / sizeof(int16_t);
1334  }
1335 
1336  if (terminator != NULL) {
1337  *terminator = '\0';
1338  }
1339 
1340  if (!zstr(terminators)) {
1341  for (i = 0; i < x; i++) {
1342  if (strchr(terminators, buf[i]) && terminator != NULL) {
1343  *terminator = buf[i];
1344  buf[i] = '\0';
1345  switch_safe_free(abuf);
1346  return SWITCH_STATUS_SUCCESS;
1347  }
1348  }
1349  }
1350 
1351  if (abs_timeout) {
1352  started = switch_micro_time_now();
1353  }
1354 
1355  if (digit_timeout && first_timeout) {
1356  eff_timeout = first_timeout;
1357  } else if (digit_timeout && !first_timeout) {
1358  first_timeout = eff_timeout = digit_timeout;
1359  } else if (first_timeout) {
1360  digit_timeout = eff_timeout = first_timeout;
1361  }
1362 
1363 
1364  if (eff_timeout) {
1365  digit_started = switch_micro_time_now();
1366  }
1367 
1368  while (switch_channel_ready(channel)) {
1369  switch_frame_t *read_frame;
1370 
1371  if (abs_timeout) {
1372  abs_elapsed = (uint32_t) ((switch_micro_time_now() - started) / 1000);
1373  if (abs_elapsed >= abs_timeout) {
1374  status = SWITCH_STATUS_TIMEOUT;
1375  break;
1376  }
1377  }
1378 
1379 
1380  switch_ivr_parse_all_events(session);
1381 
1382 
1383 
1384  if (eff_timeout) {
1385  digit_elapsed = (uint32_t) ((switch_micro_time_now() - digit_started) / 1000);
1386 
1387  if (digit_elapsed >= eff_timeout) {
1388  status = SWITCH_STATUS_TIMEOUT;
1389  break;
1390  }
1391  }
1392 
1393  if (switch_channel_has_dtmf(channel)) {
1394  switch_dtmf_t dtmf = { 0 };
1395  switch_size_t y;
1396 
1397  if (eff_timeout) {
1398  eff_timeout = digit_timeout;
1399  digit_started = switch_micro_time_now();
1400  }
1401 
1402  for (y = 0; y <= maxdigits; y++) {
1403  if (switch_channel_dequeue_dtmf(channel, &dtmf) != SWITCH_STATUS_SUCCESS) {
1404  break;
1405  }
1406 
1407  if (!zstr(terminators) && strchr(terminators, dtmf.digit) && terminator != NULL) {
1408  *terminator = dtmf.digit;
1409  switch_safe_free(abuf);
1410  return SWITCH_STATUS_SUCCESS;
1411  }
1412 
1413 
1414  buf[x++] = dtmf.digit;
1415  buf[x] = '\0';
1416 
1417  if (x >= buflen || x >= maxdigits) {
1418  switch_safe_free(abuf);
1419  return SWITCH_STATUS_SUCCESS;
1420  }
1421  }
1422  }
1423 
1424  if (switch_channel_test_flag(channel, CF_SERVICE)) {
1425  switch_cond_next();
1426  } else {
1427  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1428  if (!SWITCH_READ_ACCEPTABLE(status)) {
1429  break;
1430  }
1431 
1432  if (write_frame.data) {
1433  switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, imp.number_of_channels, sval);
1434  switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
1435  }
1436 
1437  }
1438  }
1439 
1440  if (write_frame.codec) {
1441  switch_core_codec_destroy(&codec);
1442  }
1443 
1444  switch_safe_free(abuf);
1445 
1446  return status;
1447 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:310
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
#define switch_channel_ready(_channel)
void switch_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t channels, uint32_t divisor)
Generate static noise.
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
#define zstr(x)
Definition: switch_utils.h:281
#define SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE
Definition: switch_types.h:129
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
int64_t switch_time_t
Definition: switch_apr.h:188
uint32_t buflen
Definition: switch_frame.h:59
switch_byte_t switch_byte_t * buf
uint32_t datalen
Definition: switch_frame.h:57
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
#define switch_zmalloc(ptr, len)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
An abstraction of a data frame.
Definition: switch_frame.h:43
uintptr_t switch_size_t
switch_byte_t switch_byte_t uint32_t buflen
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
void switch_cond_next(void)
Definition: switch_time.c:638
switch_status_t
Common return values.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
uint32_t samples
Definition: switch_frame.h:61
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_status_t switch_ivr_deactivate_unicast ( switch_core_session_t session)

Definition at line 365 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, switch_thread_join(), switch_yield, and switch_unicast_conninfo::thread.

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

366 {
368  switch_unicast_conninfo_t *conninfo;
369  int sanity = 0;
370 
371  if (!switch_channel_test_flag(channel, CF_UNICAST)) {
372  return SWITCH_STATUS_FALSE;
373  }
374 
375  if ((conninfo = switch_channel_get_private(channel, "unicast"))) {
376  switch_status_t st;
377 
378  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Shutting down unicast connection\n");
381  switch_thread_join(&st, conninfo->thread);
382 
383  while (switch_test_flag(conninfo, SUF_THREAD_RUNNING)) {
384  switch_yield(10000);
385  if (++sanity >= 10000) {
386  break;
387  }
388  }
389  if (switch_core_codec_ready(&conninfo->read_codec)) {
391  }
392  switch_socket_close(conninfo->socket);
393  }
395  return SWITCH_STATUS_SUCCESS;
396 }
switch_socket_t * socket
Definition: switch_ivr.h:52
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1255
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
switch_codec_t read_codec
Definition: switch_ivr.h:49
switch_thread_t * thread
Definition: switch_ivr.h:64
#define switch_clear_flag_locked(obj, flag)
Clear a flag on an arbitrary object.
Definition: switch_utils.h:648
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_status_t switch_socket_close(switch_socket_t *sock)
Definition: switch_apr.c:714
switch_status_t switch_socket_shutdown(switch_socket_t *sock, switch_shutdown_how_e how)
Definition: switch_apr.c:709
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
static switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
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
sessionthe session to attach
mod_namethe module name of the ASR library
grammarthe grammar text, URI, or local file name
namethe grammar name
destthe destination address
ahan ASR handle to use (NULL to create one)
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4778 of file switch_ivr_async.c.

References speech_thread_handle::ah, SWITCH_ASR_FLAG_FIRE_EVENTS, switch_channel_get_private(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_core_asr_load_grammar(), switch_core_session_get_channel(), switch_ivr_detect_speech_init(), switch_ivr_stop_detect_speech(), SWITCH_LOG_DEBUG, switch_log_printf(), switch_set_flag, SWITCH_SPEECH_KEY, SWITCH_STATUS_FALSE, SWITCH_STATUS_NOT_INITALIZED, SWITCH_STATUS_SUCCESS, and switch_true().

Referenced by switch_ivr_play_and_detect_speech().

4781 {
4783  switch_status_t status;
4785  const char *p;
4786 
4787  if (!sth) {
4788  /* No speech thread handle available yet, init speech detection first. */
4789  if ((status = switch_ivr_detect_speech_init(session, mod_name, dest, ah)) != SWITCH_STATUS_SUCCESS) {
4791  }
4792 
4793  /* Fetch the new speech thread handle */
4794  if (!(sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
4796  }
4797  }
4798 
4799  if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) {
4800  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
4802  return SWITCH_STATUS_FALSE;
4803  }
4804 
4805  if ((p = switch_channel_get_variable(channel, "fire_asr_events")) && switch_true(p)) {
4807  }
4808 
4809  return SWITCH_STATUS_SUCCESS;
4810 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_asr_handle_t * ah
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
switch_status_t switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name)
Load a grammar to an asr handle.
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_stop_detect_speech(switch_core_session_t *session)
Stop background Speech detection on a session.
#define switch_channel_get_variable(_c, _v)
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_ivr_detect_speech_init(switch_core_session_t *session, const char *mod_name, const char *dest, switch_asr_handle_t *ah)
Initialize background Speech detection on a session, so that parameters can be set, and grammars loaded. After calling this function, it is possible to call switch_ivr_set_param_detect_speech() to set recognition parameters. Calling switch_ivr_detect_speech_load_grammar() starts the speech recognition.
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
sessionThe session to change the grammar on
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4703 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.

4704 {
4707  switch_status_t status;
4708 
4709  if (sth) {
4711  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error disabling all Grammars\n");
4713  }
4714  return status;
4715  }
4716  return SWITCH_STATUS_FALSE;
4717 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_asr_handle_t * ah
switch_status_t switch_core_asr_disable_all_grammars(switch_asr_handle_t *ah)
Disable all grammars from an asr handle.
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_stop_detect_speech(switch_core_session_t *session)
Stop background Speech detection on a session.
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
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
sessionThe session to change the grammar on
namethe grammar name
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4687 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.

4688 {
4691  switch_status_t status;
4692 
4693  if (sth) {
4694  if ((status = switch_core_asr_disable_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
4695  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error disabling Grammar\n");
4697  }
4698  return status;
4699  }
4700  return SWITCH_STATUS_FALSE;
4701 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given 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_core_asr_disable_grammar(switch_asr_handle_t *ah, const char *name)
Disable a grammar from an asr handle.
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
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
sessionThe session to change the grammar on
namethe grammar name
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4671 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.

4672 {
4675  switch_status_t status;
4676 
4677  if (sth) {
4678  if ((status = switch_core_asr_enable_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
4679  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error enabling Grammar\n");
4681  }
4682  return status;
4683  }
4684  return SWITCH_STATUS_FALSE;
4685 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_stop_detect_speech(switch_core_session_t *session)
Stop background Speech detection on a session.
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_status_t switch_core_asr_enable_grammar(switch_asr_handle_t *ah, const char *name)
Enable a grammar from an asr handle.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_ivr_detect_speech_init ( switch_core_session_t session,
const char *  mod_name,
const char *  dest,
switch_asr_handle_t ah 
)

Initialize background Speech detection on a session, so that parameters can be set, and grammars loaded. After calling this function, it is possible to call switch_ivr_set_param_detect_speech() to set recognition parameters. Calling switch_ivr_detect_speech_load_grammar() starts the speech recognition.

Parameters
sessionthe session to attach
mod_namethe module name of the ASR library
destthe destination address
ahan ASR handle to use (NULL to create one)
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4719 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, speech_thread_handle::ah, speech_thread_handle::bug, speech_thread_handle::pool, speech_thread_handle::session, 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_set_private(), switch_core_asr_close(), 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_set_flag, switch_snprintf(), SWITCH_SPEECH_KEY, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, and switch_true().

Referenced by switch_ivr_detect_speech().

4721 {
4723  switch_status_t status;
4726  switch_codec_implementation_t read_impl = { 0 };
4727  const char *p;
4728  char key[512] = "";
4729 
4730  if (sth) {
4731  /* Already initialized */
4732  return SWITCH_STATUS_SUCCESS;
4733  }
4734 
4735  if (!ah) {
4736  if (!(ah = switch_core_session_alloc(session, sizeof(*ah)))) {
4737  return SWITCH_STATUS_MEMERR;
4738  }
4739  }
4740 
4741  switch_core_session_get_read_impl(session, &read_impl);
4742 
4743  if ((status = switch_core_asr_open(ah,
4744  mod_name,
4745  "L16",
4746  read_impl.actual_samples_per_second, dest, &flags,
4748  return status;
4749  }
4750 
4751  sth = switch_core_session_alloc(session, sizeof(*sth));
4752  sth->pool = switch_core_session_get_pool(session);
4753  sth->session = session;
4754  sth->ah = ah;
4755 
4756  if ((p = switch_channel_get_variable(channel, "fire_asr_events")) && switch_true(p)) {
4758  }
4759 
4760  switch_snprintf(key, sizeof(key), "%s/%s/%s/%s", mod_name, NULL, NULL, dest);
4761 
4762  if ((status = switch_core_media_bug_add(session, "detect_speech", key,
4764  switch_core_asr_close(ah, &flags);
4765  return status;
4766  }
4767 
4768  if ((status = switch_core_event_hook_add_recv_dtmf(session, speech_on_dtmf)) != SWITCH_STATUS_SUCCESS) {
4770  return status;
4771  }
4772 
4774 
4775  return SWITCH_STATUS_SUCCESS;
4776 }
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_asr_handle_t * ah
switch_core_session_t * session
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
switch_status_t switch_core_asr_open(switch_asr_handle_t *ah, const char *module_name, const char *codec, int rate, const char *dest, switch_asr_flag_t *flags, switch_memory_pool_t *pool)
Open an asr handle.
static switch_status_t speech_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session, _In_ const char *function, _In_ const char *target, _In_ switch_media_bug_callback_t callback, _In_opt_ void *user_data, _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug)
Add a media bug to the session.
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
Close an asr handle.
switch_status_t switch_ivr_stop_detect_speech(switch_core_session_t *session)
Stop background Speech detection on a session.
static switch_bool_t speech_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
switch_memory_pool_t * pool
#define switch_channel_get_variable(_c, _v)
uint32_t switch_asr_flag_t
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
A table of settings and callbacks that define a paticular implementation of a codec.
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_media_bug_t * bug
switch_status_t switch_ivr_detect_speech_load_grammar ( switch_core_session_t session,
const char *  grammar,
const char *  name 
)

Load a grammar on a background speech detection handle.

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

Definition at line 4614 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.

4615 {
4618  switch_status_t status;
4619 
4620  if (sth) {
4621  if ((status = switch_core_asr_load_grammar(sth->ah, grammar, name)) != SWITCH_STATUS_SUCCESS) {
4622  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
4624  }
4625  return status;
4626  }
4627  return SWITCH_STATUS_FALSE;
4628 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_asr_handle_t * ah
switch_status_t switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name)
Load a grammar to an asr handle.
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_stop_detect_speech(switch_core_session_t *session)
Stop background Speech detection on a session.
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
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
sessionThe session to start the timers on
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4643 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().

4644 {
4647 
4648  if (sth) {
4650  return SWITCH_STATUS_SUCCESS;
4651  }
4652  return SWITCH_STATUS_FALSE;
4653 }
switch_status_t switch_core_asr_start_input_timers(switch_asr_handle_t *ah)
Start input timers on an asr handle.
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
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
sessionThe session to change the grammar on
namethe grammar name
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4655 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.

4656 {
4659  switch_status_t status;
4660 
4661  if (sth) {
4662  if ((status = switch_core_asr_unload_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
4663  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error unloading Grammar\n");
4665  }
4666  return status;
4667  }
4668  return SWITCH_STATUS_FALSE;
4669 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_stop_detect_speech(switch_core_session_t *session)
Stop background Speech detection on a session.
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name)
Unload a grammar from an asr handle.
switch_status_t switch_ivr_digit_stream_destroy ( switch_ivr_digit_stream_t **  stream)

Destroys a digit stream object.

Parameters
streama 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 2311 of file switch_ivr.c.

References switch_safe_free, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

2312 {
2314 
2315  if (*stream) {
2316  switch_safe_free((*stream)->digits);
2317  free(*stream);
2318  *stream = NULL;
2319  status = SWITCH_STATUS_SUCCESS;
2320  }
2321 
2322  return status;
2323 }
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_status_t
Common return values.
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
parsera pointer to the parser object created by switch_ivr_digit_stream_parser_new
streama 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 2295 of file switch_ivr.c.

References memset(), switch_assert, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_zmalloc.

2296 {
2298 
2299  /* if we have a parser object memory pool and a stream object pointer that is null */
2300  if (parser && stream && *stream == NULL) {
2301  *stream = (switch_ivr_digit_stream_t *) malloc(sizeof(**stream));
2302  switch_assert(*stream);
2303  memset(*stream, 0, sizeof(**stream));
2304  switch_zmalloc((*stream)->digits, parser->buflen + 1);
2305  status = SWITCH_STATUS_SUCCESS;
2306  }
2307 
2308  return status;
2309 }
#define switch_zmalloc(ptr, len)
switch_status_t
Common return values.
#define switch_assert(expr)
memset(buf, 0, buflen)
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
parsera pointer to the parser object created by switch_ivr_digit_stream_parser_new
digitsthe digit string to be removed from the map
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2367 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.

2368 {
2370 
2371  if (parser != NULL && digits != NULL && *digits) {
2373  }
2374 
2375  if (status != SWITCH_STATUS_SUCCESS) {
2376  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to del hash for '%s'\n", digits);
2377  }
2378 
2379  return status;
2380 }
#define SWITCH_CHANNEL_LOG
void * switch_core_hash_delete(_In_ switch_hash_t *hash, _In_z_ const char *key)
Delete data from a hash based on desired key.
switch_status_t
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_ivr_digit_stream_parser_destroy ( switch_ivr_digit_stream_parser_t parser)

Destroy a digit stream parser object.

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

Definition at line 2277 of file switch_ivr.c.

References switch_core_destroy_memory_pool, switch_core_hash_destroy(), and SWITCH_STATUS_FALSE.

2278 {
2280 
2281  if (parser != NULL) {
2282  if (parser->hash != NULL) {
2283  switch_core_hash_destroy(&parser->hash);
2284  parser->hash = NULL;
2285  }
2286  /* free the memory pool if we created it */
2287  if (parser->pool_auto_created && parser->pool != NULL) {
2288  status = switch_core_destroy_memory_pool(&parser->pool);
2289  }
2290  }
2291 
2292  return status;
2293 }
switch_status_t switch_core_hash_destroy(_Inout_ switch_hash_t **hash)
Destroy an existing hash table.
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:640
switch_status_t
Common return values.
switch_memory_pool_t * pool
Definition: switch_ivr.c:2223
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
parsera pointer to the parser object created by switch_ivr_digit_stream_parser_new
streama stream to write data to
digita 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 2382 of file switch_ivr.c.

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

2383 {
2384  void *result = NULL;
2385  switch_size_t len;
2386 
2387  switch_assert(parser);
2388  switch_assert(stream);
2389  switch_assert(stream->digits);
2390 
2391  len = strlen(stream->digits);
2392 
2393  /* handle new digit arrivals */
2394  if (digit) {
2395  /* if it's not a terminator digit, add it to the collected digits */
2396  if (digit != parser->terminator) {
2397  /* if collected digits length >= the max length of the keys
2398  * in the hash table, then left shift the digit string
2399  */
2400  if (len > 0 && parser->maxlen != 0 && len >= parser->maxlen) {
2401  char *src = stream->digits + 1;
2402  char *dst = stream->digits;
2403 
2404  while (*src) {
2405  *(dst++) = *(src++);
2406  }
2407  *dst = digit;
2408  } else {
2409  *(stream->digits + (len++)) = digit;
2410  *(stream->digits + len) = '\0';
2411  stream->last_digit_time = switch_micro_time_now() / 1000;
2412  }
2413  }
2414  }
2415 
2416  /* don't allow collected digit string testing if there are varying sized keys until timeout */
2417  if (parser->maxlen - parser->minlen > 0 && (switch_micro_time_now() / 1000) - stream->last_digit_time < parser->digit_timeout_ms) {
2418  len = 0;
2419  }
2420  /* if we have digits to test */
2421  if (len) {
2422  result = switch_core_hash_find(parser->hash, stream->digits);
2423  /* if we matched the digit string, or this digit is the terminator
2424  * reset the collected digits for next digit string
2425  */
2426  if (result != NULL || parser->terminator == digit) {
2427  *stream->digits = '\0';
2428  }
2429  }
2430 
2431 
2432  return result;
2433 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:310
void * switch_core_hash_find(_In_ switch_hash_t *hash, _In_z_ const char *key)
Retrieve data from a given hash.
switch_time_t last_digit_time
Definition: switch_ivr.c:2234
uintptr_t switch_size_t
#define switch_assert(expr)
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
poolthe pool to use for the new hash
parsera pointer to the object pointer
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2237 of file switch_ivr.c.

References memset(), pool, 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.

2238 {
2240 
2241  if (parser != NULL) {
2242  int pool_auto_created = 0;
2243 
2244  /* if the caller didn't provide a pool, make one */
2245  if (pool == NULL) {
2247  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "created a memory pool\n");
2248  if (pool != NULL) {
2249  pool_auto_created = 1;
2250  }
2251  }
2252  /* if we have a pool, make a parser object */
2253  if (pool != NULL) {
2255  }
2256  /* if we have parser object, initialize it for the caller */
2257  if (pool && *parser != NULL) {
2258  memset(*parser, 0, sizeof(switch_ivr_digit_stream_parser_t));
2259  (*parser)->pool_auto_created = pool_auto_created;
2260  (*parser)->pool = pool;
2261  (*parser)->digit_timeout_ms = 1000;
2262  switch_core_hash_init(&(*parser)->hash);
2263 
2264  status = SWITCH_STATUS_SUCCESS;
2265  } else {
2266  status = SWITCH_STATUS_MEMERR;
2267  /* if we can't create a parser object,clean up the pool if we created it */
2268  if (pool != NULL && pool_auto_created) {
2270  }
2271  }
2272  }
2273 
2274  return status;
2275 }
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
#define SWITCH_CHANNEL_LOG
#define switch_core_hash_init(_hash)
Definition: switch_core.h:1390
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:640
switch_memory_pool_t * pool
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:682
switch_status_t
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
memset(buf, 0, buflen)
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
parsera pointer to the parser object created by switch_ivr_digit_stream_parser_new
digitsa string of digits to associate with an action
dataconsumer data attached to this digit string
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2325 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.

2326 {
2328 
2329  if (parser != NULL && digits != NULL && *digits && parser->hash != NULL) {
2330 
2331  status = switch_core_hash_insert(parser->hash, digits, data);
2332  if (status == SWITCH_STATUS_SUCCESS) {
2333  switch_size_t len = strlen(digits);
2334 
2335  /* if we don't have a terminator, then we have to try and
2336  * figure out when a digit set is completed, therefore we
2337  * keep track of the min and max digit lengths
2338  */
2339 
2340  if (len > parser->buflen) {
2341  parser->buflen = len;
2342  }
2343 
2344  if (parser->terminator == '\0') {
2345  if (len > parser->maxlen) {
2346  parser->maxlen = len;
2347  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "max len %u\n", (uint32_t) parser->maxlen);
2348  }
2349  if (parser->minlen == 0 || len < parser->minlen) {
2350  parser->minlen = len;
2351  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "min len %u\n", (uint32_t) parser->minlen);
2352  }
2353  } else {
2354  /* since we have a terminator, reset min and max */
2355  parser->minlen = 0;
2356  parser->maxlen = 0;
2357  }
2358  }
2359  }
2360  if (status != SWITCH_STATUS_SUCCESS) {
2361  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to add hash for '%s'\n", digits);
2362  }
2363 
2364  return status;
2365 }
#define SWITCH_CHANNEL_LOG
uintptr_t switch_size_t
switch_status_t
Common return values.
#define switch_core_hash_insert(_h, _k, _d)
Definition: switch_core.h:1410
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
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
parsera pointer to the parser object created by switch_ivr_digit_stream_parser_new
digitthe terminator digit
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2448 of file switch_ivr.c.

References SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

2449 {
2451 
2452  if (parser != NULL) {
2453  parser->terminator = digit;
2454  /* since we have a terminator, reset min and max */
2455  parser->minlen = 0;
2456  parser->maxlen = 0;
2457  status = SWITCH_STATUS_SUCCESS;
2458  }
2459 
2460  return status;
2461 }
switch_status_t
Common return values.
switch_status_t switch_ivr_digit_stream_reset ( switch_ivr_digit_stream_t stream)

Reset the collected digit stream to nothing.

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

Definition at line 2435 of file switch_ivr.c.

References switch_assert, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

2436 {
2438  switch_assert(stream);
2439  switch_assert(stream->digits);
2440 
2441  *stream->digits = '\0';
2442  stream->last_digit_time = 0;
2443  status = SWITCH_STATUS_SUCCESS;
2444 
2445  return status;
2446 }
switch_time_t last_digit_time
Definition: switch_ivr.c:2234
switch_status_t
Common return values.
#define switch_assert(expr)
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
sessionthe session to displace
filefilename
limittime limit in ms
flagsm (mux) l (loop) or r(read session instead of write session)
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 912 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, switch_directories::base_dir, switch_file_handle::channels, displace_helper_t::fh, displace_helper_t::file, switch_codec_implementation::iananame, displace_helper_t::loop, displace_helper_t::mux, switch_codec_implementation::number_of_channels, read_displace_callback(), switch_file_handle::samplerate, 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_FALSE, 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_true(), SWITCH_URL_SEPARATOR, write_displace_callback(), and zstr.

913 {
916  switch_status_t status;
917  time_t to = 0;
918  char *ext;
919  const char *prefix;
920  displace_helper_t *dh;
921  const char *p;
922  switch_bool_t hangup_on_error = SWITCH_FALSE;
923  switch_codec_implementation_t read_impl = { 0 };
924  switch_core_session_get_read_impl(session, &read_impl);
925 
926  if ((p = switch_channel_get_variable(channel, "DISPLACE_HANGUP_ON_ERROR"))) {
927  hangup_on_error = switch_true(p);
928  }
929 
930  if (zstr(file)) {
931  return SWITCH_STATUS_FALSE;
932  }
933 
934  if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
935  return SWITCH_STATUS_FALSE;
936  }
937 
938  if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
939  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not displace session. Media not enabled on channel\n");
940  return SWITCH_STATUS_FALSE;
941  }
942 
943  if ((bug = switch_channel_get_private(channel, file))) {
944  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only 1 of the same file per channel please!\n");
945  return SWITCH_STATUS_FALSE;
946  }
947 
948  if (!(dh = switch_core_session_alloc(session, sizeof(*dh)))) {
949  return SWITCH_STATUS_MEMERR;
950  }
951 
952  if (!(prefix = switch_channel_get_variable(channel, "sound_prefix"))) {
953  prefix = SWITCH_GLOBAL_dirs.base_dir;
954  }
955 
956  if (!strstr(file, SWITCH_URL_SEPARATOR)) {
957  if (!switch_is_file_path(file)) {
958  char *tfile = NULL;
959  char *e;
960 
961  if (*file == '[') {
962  tfile = switch_core_session_strdup(session, file);
963  if ((e = switch_find_end_paren(tfile, '[', ']'))) {
964  *e = '\0';
965  file = e + 1;
966  } else {
967  tfile = NULL;
968  }
969  }
970 
971  file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
972  }
973  if ((ext = strrchr(file, '.'))) {
974  ext++;
975  } else {
976  ext = read_impl.iananame;
977  file = switch_core_session_sprintf(session, "%s.%s", file, ext);
978  }
979  }
980 
981  dh->fh.channels = read_impl.number_of_channels;
982  dh->fh.samplerate = read_impl.actual_samples_per_second;
983  dh->file = switch_core_session_strdup(session, file);
984 
985  if (switch_core_file_open(&dh->fh,
986  file,
987  read_impl.number_of_channels,
989  if (hangup_on_error) {
992  }
993  return SWITCH_STATUS_GENERR;
994  }
995 
996  if (limit) {
997  to = switch_epoch_time_now(NULL) + limit;
998  }
999 
1000  if (flags && strchr(flags, 'm')) {
1001  dh->mux++;
1002  }
1003 
1004  if (flags && strchr(flags, 'l')) {
1005  dh->loop++;
1006  }
1007 
1008  if (flags && strchr(flags, 'r')) {
1009  status = switch_core_media_bug_add(session, "displace", file,
1011  } else {
1012  status = switch_core_media_bug_add(session, "displace", file,
1014  }
1015 
1016  if (status != SWITCH_STATUS_SUCCESS) {
1017  switch_core_file_close(&dh->fh);
1018  return status;
1019  }
1020 
1021  switch_channel_set_private(channel, file, bug);
1022 
1023  return SWITCH_STATUS_SUCCESS;
1024 }
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
char * switch_core_session_sprintf(_In_ switch_core_session_t *session, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the session ...
#define SWITCH_CHANNEL_SESSION_LOG(x)
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
char * switch_find_end_paren(const char *s, char open, char close)
Definition: switch_utils.c:661
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
#define switch_core_file_open(_fh, _file_path, _channels, _rate, _flags, _pool)
Open a media file using file format modules.
Definition: switch_core.h:1865
switch_bool_t
Definition: switch_types.h:405
#define SWITCH_URL_SEPARATOR
Definition: switch_types.h:124
switch_status_t switch_core_file_close(_In_ switch_file_handle_t *fh)
Close an open file handle.
static switch_bool_t read_displace_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session, _In_ const char *function, _In_ const char *target, _In_ switch_media_bug_callback_t callback, _In_opt_ void *user_data, _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug)
Add a media bug to the session.
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
#define zstr(x)
Definition: switch_utils.h:281
switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:122
switch_file_handle_t fh
#define switch_channel_get_variable(_c, _v)
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:60
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
static switch_bool_t switch_is_file_path(const char *file)
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:321
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
static switch_bool_t write_displace_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
#define switch_channel_media_up(_channel)
switch_media_bug_t * bug
switch_status_t switch_ivr_eavesdrop_exec_all ( switch_core_session_t session,
const char *  app,
const char *  arg 
)

Definition at line 1832 of file switch_ivr_async.c.

References exec_cb_data::caller, exec_cb(), switch_core_media_bug_exec_all(), switch_core_session_alloc, switch_core_session_strdup, exec_cb_data::val, and exec_cb_data::var.

1833 {
1834  struct exec_cb_data *data = NULL;
1835 
1836  data = switch_core_session_alloc(session, sizeof(*data));
1837  data->var = switch_core_session_strdup(session, app);
1838  data->val = switch_core_session_strdup(session, arg);
1839  data->caller = session;
1840 
1841  return switch_core_media_bug_exec_all(session, "eavesdrop", exec_cb, data);
1842 }
switch_core_session_t * caller
static void exec_cb(switch_media_bug_t *bug, void *user_data)
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_status_t switch_core_media_bug_exec_all(switch_core_session_t *orig_session, const char *function, switch_media_bug_exec_cb_t cb, void *user_data)
switch_status_t switch_ivr_eavesdrop_pop_eavesdropper ( switch_core_session_t session,
switch_core_session_t **  sessionp 
)

Definition at line 1773 of file switch_ivr_async.c.

References eavesdrop_pvt::eavesdropper, ep, 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.

1774 {
1775  switch_media_bug_t *bug;
1777 
1778  if (switch_core_media_bug_pop(session, "eavesdrop", &bug) == SWITCH_STATUS_SUCCESS) {
1780 
1781  if (ep && ep->eavesdropper && ep->eavesdropper != session) {
1783  *sessionp = ep->eavesdropper;
1785  status = SWITCH_STATUS_SUCCESS;
1786  }
1787  }
1788 
1789 
1790  return status;
1791 }
void * switch_core_media_bug_get_user_data(_In_ switch_media_bug_t *bug)
Obtain private data from a media bug.
switch_status_t switch_core_session_read_lock(_In_ switch_core_session_t *session)
Acquire a read lock on the session.
uint32_t switch_core_media_bug_set_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag)
switch_core_session_t * eavesdropper
switch_status_t switch_core_media_bug_pop(switch_core_session_t *orig_session, const char *function, switch_media_bug_t **pop)
static const char * ep
Definition: switch_json.c:36
switch_status_t
Common return values.
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
sessionour session
uuidthe uuid of the session to spy on
require_groupgroup name to use to limit by group
flagstweak read-mux, write-mux and dtmf
Returns
SWITCH_STATUS_SUCESS if all is well

Definition at line 1866 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, buf, eavesdrop_pvt::buffer, 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, CF_BRIDGE_ORIGINATOR, CF_BRIDGED, CF_VIDEO, switch_core_session::channel, switch_frame::codec, switch_frame::data, eavesdrop_pvt::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, eavesdrop_callback(), eavesdrop_pvt::eavesdropper, ED_BRIDGE_READ, ED_BRIDGE_WRITE, ED_COPY_DISPLAY, ED_DTMF, ED_MUX_READ, ED_MUX_WRITE, ep, eavesdrop_pvt::flags, switch_core_session_message::from, switch_codec::implementation, switch_core_session_message::message_id, switch_codec_implementation::microseconds_per_packet, eavesdrop_pvt::mutex, switch_codec_implementation::number_of_channels, eavesdrop_pvt::r_buffer, eavesdrop_pvt::r_mutex, switch_frame::rate, eavesdrop_pvt::read_impl, switch_frame::samples, SFF_CNG, SMBF_NO_PAUSE, SMBF_READ_PING, SMBF_READ_REPLACE, SMBF_READ_STREAM, SMBF_READ_VIDEO_PING, SMBF_READ_VIDEO_STREAM, SMBF_SPY_VIDEO_STREAM, SMBF_SPY_VIDEO_STREAM_BLEG, SMBF_THREAD_LOCK, SMBF_WRITE_REPLACE, SMBF_WRITE_STREAM, SMBF_WRITE_VIDEO_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_ack, switch_channel_media_up, switch_channel_pre_answer, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_state_change_pending(), switch_channel_test_flag(), switch_channel_up, 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_clear_flag(), switch_core_media_bug_remove(), switch_core_media_bug_set_flag(), switch_core_media_bug_test_flag(), 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_request_video_refresh(), 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_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), switch_media_bug_parse_spy_fmt(), switch_media_bug_set_spy_fmt(), SWITCH_MESSAGE_INDICATE_BRIDGE, SWITCH_MESSAGE_INDICATE_DISPLAY, SWITCH_MESSAGE_INDICATE_UNBRIDGE, SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ, switch_mutex_init(), SWITCH_MUTEX_NESTED, switch_mux_channels(), 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_true(), switch_yield, eavesdrop_pvt::tread_impl, eavesdrop_pvt::w_buffer, eavesdrop_pvt::w_mutex, and zstr.

1868 {
1869  switch_core_session_t *tsession;
1872  int codec_initialized = 0;
1873  const char *name, *num;
1874 
1875  if ((tsession = switch_core_session_locate(uuid))) {
1876  struct eavesdrop_pvt *ep = NULL;
1877  switch_media_bug_t *bug = NULL;
1878  switch_channel_t *tchannel = switch_core_session_get_channel(tsession);
1879  switch_frame_t *read_frame, write_frame = { 0 };
1880  switch_codec_t codec = { 0 };
1881  int16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE / 2];
1882  uint32_t tlen;
1883  const char *macro_name = "eavesdrop_announce";
1884  const char *id_name = NULL;
1886  switch_core_session_message_t msg = { 0 };
1887  char cid_buf[1024] = "";
1888  switch_caller_profile_t *cp = NULL;
1889  uint32_t sanity = 600;
1890  switch_media_bug_flag_t read_flags = 0, write_flags = 0;
1891  const char *vval;
1892  int buf_size = 0;
1893 
1894  if (!switch_channel_media_up(channel)) {
1895  goto end;
1896  }
1897 
1898  while(switch_channel_state_change_pending(tchannel) || !switch_channel_media_up(tchannel)) {
1899  switch_yield(10000);
1900  if (!--sanity) break;
1901  }
1902 
1903  if (!switch_channel_media_up(tchannel)) {
1904  goto end;
1905  }
1906 
1907  switch_core_session_get_read_impl(tsession, &tread_impl);
1909 
1910  if ((id_name = switch_channel_get_variable(tchannel, "eavesdrop_announce_id"))) {
1911  const char *tmp = switch_channel_get_variable(tchannel, "eavesdrop_announce_macro");
1912  if (tmp) {
1913  macro_name = tmp;
1914  }
1915 
1916  switch_ivr_phrase_macro(session, macro_name, id_name, NULL, NULL);
1917  }
1918 
1919 
1920  if (!zstr(require_group)) {
1921  int argc, i;
1922  int ok = 0;
1923  char *argv[10] = { 0 };
1924  char *data;
1925 
1926  const char *group_name = switch_channel_get_variable(tchannel, "eavesdrop_group");
1927  /* If we don't have a group, then return */
1928  if (!group_name) {
1929  status = SWITCH_STATUS_BREAK;
1930  goto end;
1931  }
1932  /* Separate the group */
1933  data = strdup(group_name);
1934  if ((argc = switch_separate_string(data, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
1935  for (i = 0; i < argc; i++) {
1936  /* If one of the group matches, then ok */
1937  if (argv[i] && !strcmp(argv[i], require_group)) {
1938  ok = 1;
1939  }
1940  }
1941  }
1942  switch_safe_free(data);
1943  /* If we didn't find any match, then end */
1944  if (!ok) {
1945  status = SWITCH_STATUS_BREAK;
1946  goto end;
1947  }
1948  }
1949 
1950 
1951  ep = switch_core_session_alloc(session, sizeof(*ep));
1952 
1953  tlen = tread_impl.decoded_bytes_per_packet;
1954 
1955 
1957  goto end;
1958  }
1959 
1960 
1961  if (switch_core_codec_init(&codec,
1962  "L16",
1963  NULL,
1964  NULL,
1965  tread_impl.actual_samples_per_second,
1966  tread_impl.microseconds_per_packet / 1000,
1967  tread_impl.number_of_channels,
1970  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
1971  switch_core_session_rwunlock(tsession);
1972  goto end;
1973  }
1974 
1976 
1977  ep->read_impl = read_impl;
1978  ep->tread_impl = tread_impl;
1979 
1980  codec_initialized = 1;
1981 
1982  switch_core_session_set_read_codec(session, &codec);
1983  write_frame.codec = &codec;
1984  write_frame.data = buf;
1985  write_frame.buflen = sizeof(buf);
1986  write_frame.rate = codec.implementation->actual_samples_per_second;
1987 
1988  /* Make sure that at least one leg is bridged, default to both */
1989  if (! (flags & (ED_BRIDGE_READ | ED_BRIDGE_WRITE))) {
1991  }
1992 
1993  buf_size = codec.implementation->decoded_bytes_per_packet * 10;
1994 
1995  ep->eavesdropper = session;
1996  ep->flags = flags;
1998  switch_buffer_create_dynamic(&ep->buffer, buf_size, buf_size, buf_size);
2000 
2002  switch_buffer_create_dynamic(&ep->w_buffer, buf_size, buf_size, buf_size);
2004 
2006  switch_buffer_create_dynamic(&ep->r_buffer, buf_size, buf_size, buf_size);
2008 
2009  if (flags & ED_BRIDGE_READ) {
2010  read_flags = SMBF_READ_STREAM | SMBF_READ_REPLACE;
2011  }
2012 
2013  if (flags & ED_BRIDGE_WRITE) {
2014  write_flags = SMBF_WRITE_STREAM | SMBF_WRITE_REPLACE;
2015  }
2016 
2018  if ((vval = switch_channel_get_variable(session->channel, "eavesdrop_show_listener_video"))) {
2019  if (switch_true(vval) || !strcasecmp(vval, "aleg") || !strcasecmp(vval, "bleg") || !strcasecmp(vval, "both")) {
2020  read_flags |= SMBF_SPY_VIDEO_STREAM;
2021  }
2022  if (switch_true(vval) || !strcasecmp(vval, "bleg") || !strcasecmp(vval, "both")) {
2023  read_flags |= SMBF_SPY_VIDEO_STREAM_BLEG;
2024  }
2025  }
2026 
2027  if ((vval = switch_channel_get_variable(session->channel, "eavesdrop_concat_video")) && switch_true(vval)) {
2028  read_flags |= SMBF_READ_VIDEO_STREAM;
2029  read_flags |= SMBF_WRITE_VIDEO_STREAM;
2030  } else {
2031  read_flags |= SMBF_READ_VIDEO_PING;
2032  }
2033  } else {
2034  read_flags &= ~SMBF_READ_VIDEO_PING;
2035  read_flags &= ~SMBF_READ_VIDEO_STREAM;
2036  read_flags &= ~SMBF_WRITE_VIDEO_STREAM;
2037  read_flags &= ~SMBF_SPY_VIDEO_STREAM;
2038  read_flags &= ~SMBF_SPY_VIDEO_STREAM_BLEG;
2039  }
2040 
2041 
2042  if (switch_core_media_bug_add(tsession, "eavesdrop", uuid,
2043  eavesdrop_callback, ep, 0,
2044  read_flags | write_flags | SMBF_READ_PING | SMBF_THREAD_LOCK | SMBF_NO_PAUSE,
2045  &bug) != SWITCH_STATUS_SUCCESS) {
2046  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot attach bug\n");
2047  goto end;
2048  }
2049 
2050  if ((vval = switch_channel_get_variable(session->channel, "eavesdrop_video_spy_fmt"))) {
2052  }
2053 
2054  msg.from = __FILE__;
2055 
2056  /* Tell the channel we are going to be in a bridge */
2058  switch_core_session_receive_message(session, &msg);
2059  cp = switch_channel_get_caller_profile(tchannel);
2060 
2061  name = cp->caller_id_name;
2062  num = cp->caller_id_number;
2063 
2064  if (flags & ED_COPY_DISPLAY) {
2066  name = cp->callee_id_name;
2067  num = cp->callee_id_number;
2068  } else {
2069  name = cp->caller_id_name;
2070  num = cp->caller_id_number;
2071  }
2072  }
2073 
2074  sanity = 300;
2075  while(switch_channel_up(channel) && !switch_channel_media_ack(channel) && --sanity) {
2076  switch_yield(10000);
2077  }
2078 
2079 
2080  switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", name, num);
2081  msg.string_arg = cid_buf;
2083  switch_core_session_receive_message(session, &msg);
2084 
2085  if (switch_channel_test_flag(tchannel, CF_VIDEO)) {
2086 
2088 
2089  switch_core_session_receive_message(tsession, &msg);
2090  }
2091 
2092  while (switch_channel_up_nosig(tchannel) && switch_channel_ready(channel)) {
2093  uint32_t len = sizeof(buf);
2094  switch_event_t *event = NULL;
2095  char *fcommand = NULL;
2096  char db[2] = "";
2097  int vid_bug = 0, vid_dual = 0;
2098 
2099  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2100 
2101  if (!SWITCH_READ_ACCEPTABLE(status)) {
2102  goto end_loop;
2103  }
2104 
2106  char *command = switch_event_get_header(event, "eavesdrop-command");
2107  if (command) {
2108  fcommand = switch_core_session_strdup(session, command);
2109  }
2110  switch_event_destroy(&event);
2111  }
2112 
2113  if ((flags & ED_DTMF) && switch_channel_has_dtmf(channel)) {
2114  switch_dtmf_t dtmf = { 0 };
2115  switch_channel_dequeue_dtmf(channel, &dtmf);
2116  db[0] = dtmf.digit;
2117  fcommand = db;
2118  }
2119 
2122  vid_dual = 1;
2123  }
2124 
2125  if (vid_dual || switch_core_media_bug_test_flag(bug, SMBF_READ_VIDEO_PING)) {
2126  vid_bug = 1;
2127  }
2128 
2129  if (fcommand) {
2130  char *d;
2131  for (d = fcommand; *d; d++) {
2132  int z = 1;
2133 
2134  switch (*d) {
2135  case '1':
2138  if (vid_bug) {
2142  }
2143  break;
2144  case '2':
2147  if (vid_bug) {
2151  }
2152  break;
2153  case '3':
2156  if (vid_bug) {
2160  }
2161  break;
2162 
2163  case '4':
2165  break;
2166  case '5':
2168  break;
2169  case '6':
2171  break;
2172  case '0':
2175  if (vid_bug) {
2179  }
2180  break;
2181  case '*':
2182  goto end_loop;
2183  default:
2184  z = 0;
2185  break;
2186 
2187  }
2188 
2189  if (z) {
2190  if (ep->r_buffer) {
2194  }
2195 
2196  if (ep->w_buffer) {
2200  }
2201  }
2202  }
2203  }
2204 
2205  if (!switch_test_flag(read_frame, SFF_CNG)) {
2207  switch_buffer_zwrite(ep->r_buffer, read_frame->data, read_frame->datalen);
2209 
2211  switch_buffer_zwrite(ep->w_buffer, read_frame->data, read_frame->datalen);
2213  }
2214 
2215  if (len > tlen) {
2216  len = tlen;
2217  }
2218 
2219  if (switch_buffer_inuse(ep->buffer) >= len) {
2221  while (switch_buffer_inuse(ep->buffer) >= len) {
2222  int tchanged = 0, changed = 0;
2223 
2224  write_frame.datalen = (uint32_t) switch_buffer_read(ep->buffer, buf, len);
2225  write_frame.samples = write_frame.datalen / 2;
2226 
2227 
2228  switch_core_session_get_read_impl(tsession, &tread_impl);
2230 
2231  if (tread_impl.number_of_channels != ep->tread_impl.number_of_channels ||
2233  tchanged = 1;
2234  }
2235 
2238  changed = 1;
2239  }
2240 
2241  if (changed || tchanged) {
2242 
2243  if (changed) {
2245  "SPYING CHANNEL CODEC CHANGE FROM %dhz@%dc to %dhz@%dc\n",
2250  }
2251 
2252  if (tchanged) {
2254  "SPYED CHANNEL CODEC CHANGE FROM %dhz@%dc to %dhz@%dc\n",
2257  tread_impl.actual_samples_per_second,
2258  tread_impl.number_of_channels);
2259 
2260  tlen = tread_impl.decoded_bytes_per_packet;
2261 
2262  if (len > tlen) {
2263  len = tlen;
2264  }
2265 
2266  switch_core_codec_destroy(&codec);
2267 
2268  if (switch_core_codec_init(&codec,
2269  "L16",
2270  NULL,
2271  NULL,
2272  tread_impl.actual_samples_per_second,
2273  tread_impl.microseconds_per_packet / 1000,
2274  tread_impl.number_of_channels,
2277  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
2278  switch_core_session_rwunlock(tsession);
2279  goto end;
2280  }
2281  }
2282 
2283  ep->read_impl = read_impl;
2284  ep->tread_impl = tread_impl;
2285  }
2286 
2287 
2289  uint32_t rlen = write_frame.datalen / 2 / ep->tread_impl.number_of_channels;
2290 
2291  switch_mux_channels((int16_t *) write_frame.data, rlen, ep->tread_impl.number_of_channels, ep->read_impl.number_of_channels);
2292  write_frame.datalen = rlen * 2 * ep->read_impl.number_of_channels;
2293  write_frame.samples = write_frame.datalen / 2;
2294  }
2295 
2296  if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
2297  break;
2298  }
2299  }
2301  }
2302 
2303  }
2304 
2305  end_loop:
2306 
2307  /* Tell the channel we are no longer going to be in a bridge */
2309  switch_core_session_receive_message(session, &msg);
2310 
2311 
2312 
2313  end:
2314 
2315  if (codec_initialized)
2316  switch_core_codec_destroy(&codec);
2317 
2318  if (bug) {
2319  switch_core_media_bug_remove(tsession, &bug);
2320  }
2321 
2322  if (ep) {
2323  if (ep->buffer) {
2325  }
2326 
2327  if (ep->r_buffer) {
2329  }
2330 
2331  if (ep->w_buffer) {
2333  }
2334  }
2335 
2336  switch_core_session_rwunlock(tsession);
2337  status = SWITCH_STATUS_SUCCESS;
2338 
2340  }
2341 
2342  return status;
2343 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
Call Specific Data.
Definition: switch_caller.h:73
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_size_t switch_buffer_zwrite(_In_ switch_buffer_t *buffer, _In_bytecount_(datalen) const void *data, _In_ switch_size_t datalen)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
switch_size_t switch_buffer_read(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available. Remove read data fr...
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
#define switch_channel_up(_channel)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
switch_status_t switch_core_session_set_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec)
Assign the read codec to a given session.
switch_buffer_t * r_buffer
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
void switch_media_bug_set_spy_fmt(switch_media_bug_t *bug, switch_vid_spy_fmt_t spy_fmt)
uint32_t switch_core_media_bug_set_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag)
switch_mutex_t * w_mutex
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session, _In_ const char *function, _In_ const char *target, _In_ switch_media_bug_callback_t callback, _In_opt_ void *user_data, _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug)
Add a media bug to the session.
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_core_session_t * eavesdropper
static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
#define zstr(x)
Definition: switch_utils.h:281
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:655
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:59
switch_byte_t switch_byte_t * buf
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
switch_channel_t * channel
uint32_t datalen
Definition: switch_frame.h:57
switch_codec_implementation_t tread_impl
const char * callee_id_number
Definition: switch_caller.h:89
void switch_buffer_lock(_In_ switch_buffer_t *buffer)
switch_codec_implementation_t read_impl
uint32_t rate
Definition: switch_frame.h:63
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
const char * caller_id_name
Definition: switch_caller.h:79
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:270
uint32_t switch_core_media_bug_clear_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag)
void switch_buffer_zero(_In_ switch_buffer_t *buffer)
Remove all data from the buffer.
switch_buffer_t * w_buffer
An abstraction of a data frame.
Definition: switch_frame.h:43
switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug)
Remove a media bug from the session.
switch_vid_spy_fmt_t switch_media_bug_parse_spy_fmt(const char *name)
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
void switch_buffer_add_mutex(_In_ switch_buffer_t *buffer, _In_ switch_mutex_t *mutex)
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
void switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t orig_channels, uint32_t channels)
switch_status_t switch_core_session_request_video_refresh(switch_core_session_t *session)
static const char * ep
Definition: switch_json.c:36
switch_status_t
Common return values.
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
void switch_buffer_unlock(_In_ switch_buffer_t *buffer)
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
int switch_channel_state_change_pending(switch_channel_t *channel)
uint32_t samples
Definition: switch_frame.h:61
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
switch_mutex_t * r_mutex
#define switch_channel_media_ack(_channel)
const char * caller_id_number
Definition: switch_caller.h:81
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
switch_buffer_t * buffer
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_ivr_phrase_macro(session, macro_name, data, lang, args)
Definition: switch_ivr.h:903
uint32_t switch_media_bug_flag_t
uint32_t switch_core_media_bug_test_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag)
Test for the existance of a flag on an media bug.
#define switch_channel_up_nosig(_channel)
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
void switch_event_destroy(switch_event_t **event)
Destroy an event.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
switch_mutex_t * mutex
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
#define switch_channel_media_up(_channel)
const char * callee_id_name
Definition: switch_caller.h:87
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_status_t switch_ivr_eavesdrop_update_display ( switch_core_session_t session,
const char *  name,
const char *  number 
)

Definition at line 1845 of file switch_ivr_async.c.

References exec_cb_data::caller, 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, SWITCH_STATUS_FALSE, exec_cb_data::val, and exec_cb_data::var.

1846 {
1847  struct exec_cb_data *data = NULL;
1850 
1851  data = switch_core_session_alloc(session, sizeof(*data));
1852  data->var = switch_core_session_strdup(session, name);
1853  data->val = switch_core_session_strdup(session, number);
1854  data->caller = session;
1855 
1856  if (!switch_channel_test_app_flag_key("EAVESDROP", channel, 1)) {
1857  switch_channel_set_app_flag_key("EAVESDROP", channel, 1);
1858  status = switch_core_media_bug_exec_all(session, "eavesdrop", display_exec_cb, data);
1859  switch_channel_clear_app_flag_key("EAVESDROP", channel, 1);
1860  }
1861 
1862  return status;
1863 }
switch_core_session_t * caller
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void switch_channel_clear_app_flag_key(const char *app, switch_channel_t *channel, uint32_t flags)
static void display_exec_cb(switch_media_bug_t *bug, void *user_data)
void switch_channel_set_app_flag_key(const char *app, switch_channel_t *channel, uint32_t flags)
switch_status_t
Common return values.
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_status_t switch_core_media_bug_exec_all(switch_core_session_t *orig_session, const char *function, switch_media_bug_exec_cb_t cb, void *user_data)
int switch_channel_test_app_flag_key(const char *app, switch_channel_t *channel, uint32_t flags)
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 1454 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_CAUSE_NO_ANSWER, SWITCH_CAUSE_NO_PICKUP, SWITCH_CAUSE_SUCCESS, switch_channel_cause2str(), switch_channel_clear_flag(), switch_channel_get_caller_profile(), switch_channel_get_variable, switch_channel_handle_cause(), 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_set_variable, 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, enterprise_originate_handle_t::thread, ent_originate_ringback::thread, switch_event_header::value, and zstr.

Referenced by switch_ivr_originate().

1465 {
1466  int x_argc = 0;
1467  char *x_argv[MAX_PEERS] = { 0 };
1468  enterprise_originate_handle_t *hp = NULL, handles[MAX_PEERS] = { {0} };
1469  int i;
1470  switch_caller_profile_t *cp = NULL;
1471  switch_channel_t *channel = NULL;
1472  char *data;
1474  switch_threadattr_t *thd_attr = NULL;
1475  int running = 0, over = 0;
1478  switch_event_header_t *hi = NULL;
1479  struct ent_originate_ringback rb_data = { 0 };
1480  const char *ringback_data = NULL;
1481  switch_event_t *var_event = NULL;
1482  int getcause = 1;
1483 
1484  *cause = SWITCH_CAUSE_SUCCESS;
1485 
1487 
1488  if (zstr(bridgeto)) {
1490  getcause = 0;
1492  }
1493 
1494  data = switch_core_strdup(pool, bridgeto);
1495 
1496  if (session) {
1497  switch_caller_profile_t *cpp = NULL;
1498  channel = switch_core_session_get_channel(session);
1499  if ((cpp = switch_channel_get_caller_profile(channel))) {
1500  cp = switch_caller_profile_dup(pool, cpp);
1501  }
1502  }
1503 
1504  if (ovars) {
1505  var_event = ovars;
1506  } else {
1508  abort();
1509  }
1510  }
1511 
1512  if (session) {
1513  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ent_originate_aleg_uuid", switch_core_session_get_uuid(session));
1514  }
1515 
1516  if (channel) {
1517  const char *tmp_var = NULL;
1518 
1520 
1521  if ((tmp_var = switch_channel_get_variable(channel, "effective_ani"))) {
1522  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_ani", tmp_var);
1523  }
1524 
1525  if ((tmp_var = switch_channel_get_variable(channel, "effective_aniii"))) {
1526  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_aniii", tmp_var);
1527  }
1528 
1529  if ((tmp_var = switch_channel_get_variable(channel, "effective_caller_id_name"))) {
1530  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_name", tmp_var);
1531  }
1532 
1533  if ((tmp_var = switch_channel_get_variable(channel, "effective_caller_id_number"))) {
1534  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_number", tmp_var);
1535  }
1536  }
1537 
1538  /* strip leading spaces */
1539  while (data && *data && *data == ' ') {
1540  data++;
1541  }
1542 
1543  /* extract channel variables, allowing multiple sets of braces */
1544  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing ultra-global variables\n");
1545  while (*data == '<') {
1546  char *parsed = NULL;
1547 
1548  if (switch_event_create_brackets(data, '<', '>', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
1549  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
1551  }
1552 
1553  data = parsed;
1554  }
1555 
1556  /* strip leading spaces (again) */
1557  while (data && *data && *data == ' ') {
1558  data++;
1559  }
1560 
1561  if (ovars && ovars != var_event) {
1562  for (hi = ovars->headers; hi; hi = hi->next) {
1564  }
1565  }
1566 
1567  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
1568 
1569  if (!(x_argc = switch_separate_string_string(data, SWITCH_ENT_ORIGINATE_DELIM, x_argv, MAX_PEERS))) {
1571  getcause = 0;
1573  }
1574 
1575  switch_threadattr_create(&thd_attr, pool);
1577 
1578  for (i = 0; i < x_argc; i++) {
1579  handles[i].session = session;
1580  handles[i].bleg = NULL;
1581  handles[i].cause = 0;
1582  handles[i].cancel_cause = 0;
1583  handles[i].bridgeto = x_argv[i];
1584  handles[i].timelimit_sec = timelimit_sec;
1585  handles[i].table = table;
1586  handles[i].cid_name_override = cid_name_override;
1587  handles[i].cid_num_override = cid_num_override;
1588  handles[i].caller_profile_override = cp;
1589  switch_event_dup(&handles[i].ovars, var_event);
1590  handles[i].flags = flags;
1591  switch_mutex_init(&handles[i].mutex, SWITCH_MUTEX_NESTED, pool);
1592  switch_mutex_lock(handles[i].mutex);
1593  switch_thread_create(&handles[i].thread, thd_attr, enterprise_originate_thread, &handles[i], pool);
1594  }
1595 
1596  if (channel && !switch_channel_test_flag(channel, CF_PROXY_MODE) && !switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
1597  if (switch_channel_test_flag(channel, CF_ANSWERED)) {
1598  ringback_data = switch_channel_get_variable(channel, "transfer_ringback");
1599  }
1600 
1601  if (!ringback_data) {
1602  ringback_data = switch_channel_get_variable(channel, "ringback");
1603  }
1604 
1605  if (ringback_data || switch_channel_media_ready(channel)) {
1606  rb_data.ringback_data = ringback_data;
1607  rb_data.session = session;
1608  rb_data.running = 1;
1609  if (!switch_channel_media_ready(channel)) {
1611  goto done;
1612  }
1613  }
1614  switch_thread_create(&rb_data.thread, thd_attr, enterprise_originate_ringback_thread, &rb_data, pool);
1615  }
1616  }
1617 
1618 
1619  for (;;) {
1620  running = 0;
1621  over = 0;
1622 
1623  if (channel && !switch_channel_ready(channel)) {
1624  break;
1625  }
1626 
1627  if (cancel_cause && *cancel_cause > 0) {
1628  break;
1629  }
1630 
1631  for (i = 0; i < x_argc; i++) {
1632 
1633 
1634  if (handles[i].done == 0) {
1635  running++;
1636  } else if (handles[i].done == 1) {
1637  if (handles[i].status == SWITCH_STATUS_SUCCESS) {
1638  handles[i].done = 2;
1639  hp = &handles[i];
1640  goto done;
1641  } else {
1642  handles[i].done = -1;
1643  }
1644  } else {
1645  over++;
1646  }
1647 
1648  switch_yield(10000);
1649  }
1650 
1651  if (!running || over == x_argc) {
1652  break;
1653  }
1654  }
1655 
1656 
1657  done:
1658 
1659  if (hp) {
1660  *cause = hp->cause;
1661  getcause = 0;
1662  status = hp->status;
1663  *bleg = hp->bleg;
1665  switch_thread_join(&tstatus, hp->thread);
1667  }
1668 
1669  for (i = 0; i < x_argc; i++) {
1670  if (hp == &handles[i]) {
1671  continue;
1672  }
1673 
1674  if (cancel_cause && *cancel_cause > 0) {
1675  handles[i].cancel_cause = *cancel_cause;
1676  } else {
1677  handles[i].cancel_cause = SWITCH_CAUSE_LOSE_RACE;
1678  }
1679  }
1680 
1681  for (i = 0; i < x_argc; i++) {
1682 
1683  if (hp == &handles[i]) {
1684  continue;
1685  }
1686 
1687  if (channel && handles[i].cause && handles[i].cause != SWITCH_CAUSE_SUCCESS) {
1688  switch_channel_handle_cause(channel, handles[i].cause);
1689  }
1690 
1691  switch_mutex_unlock(handles[i].mutex);
1692 
1693  if (getcause && *cause != handles[i].cause && handles[i].cause != SWITCH_CAUSE_LOSE_RACE && handles[i].cause != SWITCH_CAUSE_NO_PICKUP) {
1694  *cause = handles[i].cause;
1695  getcause++;
1696  }
1697 
1698  switch_thread_join(&tstatus, handles[i].thread);
1699  switch_event_destroy(&handles[i].ovars);
1700  }
1701 
1702  if (channel && rb_data.thread) {
1704  switch_thread_join(&tstatus, rb_data.thread);
1706  }
1707 
1708 
1709  end:
1710 
1711  if (getcause == 1 && *cause == SWITCH_CAUSE_SUCCESS) {
1712  *cause = SWITCH_CAUSE_NO_ANSWER;
1713  }
1714 
1715  if (channel) {
1716  if (*cause == SWITCH_CAUSE_SUCCESS) {
1717  switch_channel_set_variable(channel, "originate_disposition", "success");
1718  } else {
1719  switch_channel_set_variable(channel, "originate_disposition", "failure");
1720  switch_channel_set_variable(channel, "hangup_cause", switch_channel_cause2str(*cause));
1721  }
1722  }
1723 
1724 
1725  if (var_event && var_event != ovars) {
1726  switch_event_destroy(&var_event);
1727  }
1728 
1730 
1731  return status;
1732 
1733 }
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
#define SWITCH_CHANNEL_SESSION_LOG(x)
Call Specific Data.
Definition: switch_caller.h:73
const char * switch_channel_cause2str(_In_ switch_call_cause_t cause)
return a cause string for a given cause
unsigned int switch_separate_string_string(char *buf, char *delim, _Post_count_(return) char **array, unsigned int arraylen)
switch_status_t switch_event_create_brackets(char *data, char a, char b, char c, switch_event_t **event, char **new_data, switch_bool_t dup)
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:660
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:640
switch_memory_pool_t * pool
static void *SWITCH_THREAD_FUNC enterprise_originate_thread(switch_thread_t *thread, void *obj)
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
An event Header.
Definition: switch_event.h:65
#define switch_channel_media_ready(_channel)
static void *SWITCH_THREAD_FUNC enterprise_originate_ringback_thread(switch_thread_t *thread, void *obj)
switch_status_t switch_event_dup(switch_event_t **event, switch_event_t *todup)
Duplicate an event.
static switch_thread_t * thread
Definition: switch_log.c:279
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
#define zstr(x)
Definition: switch_utils.h:281
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:290
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1255
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
void switch_channel_process_export(switch_channel_t *channel, switch_channel_t *peer_channel, switch_event_t *var_event, const char *export_varname)
#define switch_channel_get_variable(_c, _v)
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:551
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
switch_core_session_t * session
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:270
#define SWITCH_ENT_ORIGINATE_DELIM
Definition: switch_types.h:46
#define MAX_PEERS
static switch_status_t switch_event_create_plain(switch_event_t **event, switch_event_types_t event_id)
Definition: switch_event.h:385
static int32_t running
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_mutex_t * mutex
switch_status_t
Common return values.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:256
struct switch_event_header * next
Definition: switch_event.h:76
#define switch_channel_set_flag(_c, _f)
switch_caller_profile_t * switch_caller_profile_dup(_In_ switch_memory_pool_t *pool, _In_ switch_caller_profile_t *tocopy)
Duplicate an existing caller profile object.
struct apr_pool_t switch_memory_pool_t
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:642
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:675
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_channel_set_variable(_channel, _var, _val)
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
switch_event_header_t * headers
Definition: switch_event.h:90
#define SWITCH_EXPORT_VARS_VARIABLE
Definition: switch_types.h:194
void switch_channel_handle_cause(switch_channel_t *channel, switch_call_cause_t cause)
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
sessionthe session to get the data from.
json_cdrpointer to the json object
Returns
SWITCH_STATUS_SUCCESS if successful
Note
on success the json object must be freed

Definition at line 3177 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, cJSON_AddItemToArray(), cJSON_AddItemToObject(), cJSON_CreateArray(), 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::hold_accum, switch_channel_timetable::hungup, switch_channel_timetable::last_hold, switch_app_log::next, switch_caller_profile::next, switch_caller_application::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_get_switchname(), switch_core_get_uuid(), switch_core_session_get_app_log(), switch_core_session_get_channel(), switch_ivr_set_json_call_stats(), switch_ivr_set_json_chan_vars(), switch_ivr_set_json_profile_data(), SWITCH_MEDIA_TYPE_AUDIO, SWITCH_MEDIA_TYPE_VIDEO, 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(), and switch_ivr_originate().

3178 {
3179  cJSON *cdr = cJSON_CreateObject();
3181  switch_caller_profile_t *caller_profile;
3182  cJSON *variables, *j_main_cp, *j_caller_profile, *j_caller_extension, *j_caller_extension_apps, *j_times, *j_application,
3183  *j_callflow, *j_profile, *j_inner_extension, *j_app_log, *j_apps, *j_o, *j_o_profiles, *j_channel_data, *callStats;
3184  switch_app_log_t *app_log;
3185  char tmp[512], *f;
3186 
3189  j_channel_data = cJSON_CreateObject();
3190 
3191  cJSON_AddItemToObject(cdr, "channel_data", j_channel_data);
3192 
3194  cJSON_AddItemToObject(j_channel_data, "direction", cJSON_CreateString(switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"));
3195 
3196  switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel));
3197  cJSON_AddItemToObject(j_channel_data, "state_number", cJSON_CreateString((char *) tmp));
3198 
3199  if ((f = switch_channel_get_flag_string(channel))) {
3200  cJSON_AddItemToObject(j_channel_data, "flags", cJSON_CreateString((char *) f));
3201  free(f);
3202  }
3203 
3204  if ((f = switch_channel_get_cap_string(channel))) {
3205  cJSON_AddItemToObject(j_channel_data, "caps", cJSON_CreateString((char *) f));
3206  free(f);
3207  }
3208 
3209  callStats = cJSON_CreateObject();
3210  cJSON_AddItemToObject(cdr, "callStats", callStats);
3213 
3214  variables = cJSON_CreateObject();
3215  cJSON_AddItemToObject(cdr, "variables", variables);
3216  switch_ivr_set_json_chan_vars(variables, channel, urlencode);
3217 
3218 
3219  if ((app_log = switch_core_session_get_app_log(session))) {
3220  switch_app_log_t *ap;
3221 
3222  j_app_log = cJSON_CreateObject();
3223  j_apps = cJSON_CreateArray();
3224 
3225  cJSON_AddItemToObject(cdr, "app_log", j_app_log);
3226  cJSON_AddItemToObject(j_app_log, "applications", j_apps);
3227 
3228  for (ap = app_log; ap; ap = ap->next) {
3229  j_application = cJSON_CreateObject();
3230 
3231  cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->app));
3232  cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(ap->arg));
3233 
3234  cJSON_AddItemToArray(j_apps, j_application);
3235  }
3236  }
3237 
3238 
3239  caller_profile = switch_channel_get_caller_profile(channel);
3240 
3241  j_callflow = cJSON_CreateArray();
3242  cJSON_AddItemToObject(cdr, "callflow", j_callflow);
3243 
3244  while (caller_profile) {
3245 
3246  j_profile = cJSON_CreateObject();
3247 
3248  if (!zstr(caller_profile->dialplan)) {
3249  cJSON_AddItemToObject(j_profile, "dialplan", cJSON_CreateString((char *)caller_profile->dialplan));
3250  }
3251 
3252  if (!zstr(caller_profile->profile_index)) {
3253  cJSON_AddItemToObject(j_profile, "profile_index", cJSON_CreateString((char *)caller_profile->profile_index));
3254  }
3255 
3256  if (caller_profile->caller_extension) {
3258 
3259  j_caller_extension = cJSON_CreateObject();
3260  j_caller_extension_apps = cJSON_CreateArray();
3261 
3262  cJSON_AddItemToObject(j_profile, "extension", j_caller_extension);
3263 
3264  cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(caller_profile->caller_extension->extension_name));
3265  cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(caller_profile->caller_extension->extension_number));
3266  cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps);
3267 
3268  if (caller_profile->caller_extension->current_application) {
3269  cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(caller_profile->caller_extension->current_application->application_name));
3270  }
3271 
3272  for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
3273  j_application = cJSON_CreateObject();
3274 
3275  cJSON_AddItemToArray(j_caller_extension_apps, j_application);
3276 
3277  if (ap == caller_profile->caller_extension->current_application) {
3278  cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true"));
3279  }
3280  cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name));
3281  cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)));
3282  }
3283 
3284  if (caller_profile->caller_extension->children) {
3285  switch_caller_profile_t *cp = NULL;
3286  j_inner_extension = cJSON_CreateArray();
3287  cJSON_AddItemToObject(j_caller_extension, "sub_extensions", j_inner_extension);
3288  for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {
3289 
3290  if (!cp->caller_extension) {
3291  continue;
3292  }
3293 
3294  j_caller_extension = cJSON_CreateObject();
3295  cJSON_AddItemToArray(j_inner_extension, j_caller_extension);
3296 
3297  cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(cp->caller_extension->extension_name));
3298  cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(cp->caller_extension->extension_number));
3299 
3300  cJSON_AddItemToObject(j_caller_extension, "dialplan", cJSON_CreateString((char *)cp->dialplan));
3301 
3304  }
3305 
3306  j_caller_extension_apps = cJSON_CreateArray();
3307  cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps);
3308  for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
3309  j_application = cJSON_CreateObject();
3310  cJSON_AddItemToArray(j_caller_extension_apps, j_application);
3311 
3312  if (ap == cp->caller_extension->current_application) {
3313  cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true"));
3314  }
3315  cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name));
3316  cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)));
3317  }
3318  }
3319  }
3320  }
3321 
3322  j_main_cp = cJSON_CreateObject();
3323  cJSON_AddItemToObject(j_profile, "caller_profile", j_main_cp);
3324 
3325  switch_ivr_set_json_profile_data(j_main_cp, caller_profile);
3326 
3327  if (caller_profile->originator_caller_profile) {
3328  switch_caller_profile_t *cp = NULL;
3329 
3330  j_o = cJSON_CreateObject();
3331  cJSON_AddItemToObject(j_main_cp, "originator", j_o);
3332 
3333  j_o_profiles = cJSON_CreateArray();
3334  cJSON_AddItemToObject(j_o, "originator_caller_profiles", j_o_profiles);
3335 
3336  for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
3337  j_caller_profile = cJSON_CreateObject();
3338  cJSON_AddItemToArray(j_o_profiles, j_caller_profile);
3339 
3340  switch_ivr_set_json_profile_data(j_caller_profile, cp);
3341  }
3342  }
3343 
3344  if (caller_profile->originatee_caller_profile) {
3345  switch_caller_profile_t *cp = NULL;
3346 
3347  j_o = cJSON_CreateObject();
3348  cJSON_AddItemToObject(j_main_cp, "originatee", j_o);
3349 
3350  j_o_profiles = cJSON_CreateArray();
3351  cJSON_AddItemToObject(j_o, "originatee_caller_profiles", j_o_profiles);
3352 
3353  for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {
3354  j_caller_profile = cJSON_CreateObject();
3355  cJSON_AddItemToArray(j_o_profiles, j_caller_profile);
3356 
3357  switch_ivr_set_json_profile_data(j_caller_profile, cp);
3358  }
3359  }
3360 
3361  if (caller_profile->times) {
3362 
3363  j_times = cJSON_CreateObject();
3364  cJSON_AddItemToObject(j_profile, "times", j_times);
3365 
3366  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
3367  cJSON_AddItemToObject(j_times, "created_time", cJSON_CreateString(tmp));
3368 
3369  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
3370  cJSON_AddItemToObject(j_times, "profile_created_time", cJSON_CreateString(tmp));
3371 
3372  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
3373  cJSON_AddItemToObject(j_times, "progress_time", cJSON_CreateString(tmp));
3374 
3375  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
3376  cJSON_AddItemToObject(j_times, "progress_media_time", cJSON_CreateString(tmp));
3377 
3378  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
3379  cJSON_AddItemToObject(j_times, "answered_time", cJSON_CreateString(tmp));
3380 
3381  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
3382  cJSON_AddItemToObject(j_times, "bridged_time", cJSON_CreateString(tmp));
3383 
3384  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->last_hold);
3385  cJSON_AddItemToObject(j_times, "last_hold_time", cJSON_CreateString(tmp));
3386 
3387  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum);
3388  cJSON_AddItemToObject(j_times, "hold_accum_time", cJSON_CreateString(tmp));
3389 
3390  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
3391  cJSON_AddItemToObject(j_times, "hangup_time", cJSON_CreateString(tmp));
3392 
3393  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
3394  cJSON_AddItemToObject(j_times, "resurrect_time", cJSON_CreateString(tmp));
3395 
3396  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->transferred);
3397  cJSON_AddItemToObject(j_times, "transfer_time", cJSON_CreateString(tmp));
3398 
3399  }
3400  cJSON_AddItemToArray(j_callflow, j_profile);
3401  caller_profile = caller_profile->next;
3402  }
3403 
3404  *json_cdr = cdr;
3405 
3406  return SWITCH_STATUS_SUCCESS;
3407 
3408 }
char * switch_channel_get_cap_string(switch_channel_t *channel)
const char * switch_core_get_switchname(void)
Definition: switch_core.c:349
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
cJSON * cJSON_CreateObject(void)
Definition: switch_json.c:544
Call Specific Data.
Definition: switch_caller.h:73
struct switch_caller_profile * originatee_caller_profile
static void switch_ivr_set_json_profile_data(cJSON *json, switch_caller_profile_t *caller_profile)
Definition: switch_ivr.c:3055
An Abstract Representation of a dialplan Application.
struct switch_caller_profile * next
const char * switch_channel_state_name(_In_ switch_channel_state_t state)
Render the name of the provided state enum.
const char * dialplan
Definition: switch_caller.h:77
char * switch_channel_get_flag_string(switch_channel_t *channel)
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
#define zstr(x)
Definition: switch_utils.h:281
struct switch_caller_application * next
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
char * switch_core_get_uuid(void)
Retrieve the unique identifier from the core.
Definition: switch_core.c:482
void cJSON_AddItemToArray(cJSON *array, cJSON *item)
Definition: switch_json.c:519
switch_caller_application_t * applications
struct switch_caller_profile * children
#define SWITCH_TIME_T_FMT
switch_time_t profile_created
const char * profile_index
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
Definition: switch_json.c:520
struct switch_caller_profile * originator_caller_profile
switch_caller_application_t * current_application
cJSON * cJSON_CreateString(const char *string)
Definition: switch_json.c:542
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
switch_call_direction_t switch_channel_direction(switch_channel_t *channel)
switch_app_log_t * switch_core_session_get_app_log(_In_ switch_core_session_t *session)
struct switch_channel_timetable * times
cJSON * cJSON_CreateArray(void)
Definition: switch_json.c:543
static void switch_ivr_set_json_chan_vars(cJSON *json, switch_channel_t *channel, switch_bool_t urlencode)
Definition: switch_ivr.c:3146
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
void switch_ivr_set_json_call_stats(cJSON *json, switch_core_session_t *session, switch_media_type_t type)
Definition: switch_ivr.c:3076
switch_time_t progress_media
struct switch_app_log * next
Definition: switch_core.h:62
struct switch_caller_extension * caller_extension
switch_status_t switch_ivr_generate_xml_cdr ( switch_core_session_t session,
switch_xml_t xml_cdr 
)

Generate an XML CDR report.

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

Definition at line 2713 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_hold_record_s::next, switch_caller_profile::next, switch_caller_application::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_hold_record(), switch_channel_get_state(), switch_channel_state_name(), switch_core_get_switchname(), switch_core_get_uuid(), switch_core_session_get_app_log(), switch_core_session_get_channel(), switch_ivr_set_xml_call_stats(), switch_ivr_set_xml_chan_vars(), switch_ivr_set_xml_profile_data(), SWITCH_MEDIA_TYPE_AUDIO, SWITCH_MEDIA_TYPE_VIDEO, 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(), process_device_hup(), switch_core_recovery_track(), switch_core_session_reporting_state(), switch_ivr_multi_threaded_bridge(), and switch_ivr_originate().

2714 {
2716  switch_caller_profile_t *caller_profile;
2717  switch_xml_t variables, cdr, x_main_cp, x_caller_profile, x_caller_extension, x_times, time_tag,
2718  x_application, x_callflow, x_inner_extension, x_apps, x_o, x_channel_data, x_field, xhr, x_hold;
2719  switch_app_log_t *app_log;
2720  char tmp[512], *f;
2721  int cdr_off = 0, v_off = 0, cd_off = 0;
2722  switch_hold_record_t *hold_record = switch_channel_get_hold_record(channel), *hr;
2723 
2724  if (*xml_cdr) {
2725  cdr = *xml_cdr;
2726  } else {
2727  if (!(cdr = switch_xml_new("cdr"))) {
2728  return SWITCH_STATUS_SUCCESS;
2729  }
2730  }
2731 
2732  switch_xml_set_attr_d(cdr, "core-uuid", switch_core_get_uuid());
2733  switch_xml_set_attr_d(cdr, "switchname", switch_core_get_switchname());
2734 
2735  if (!(x_channel_data = switch_xml_add_child_d(cdr, "channel_data", cdr_off++))) {
2736  goto error;
2737  }
2738 
2739  x_field = switch_xml_add_child_d(x_channel_data, "state", cd_off++);
2741 
2742  x_field = switch_xml_add_child_d(x_channel_data, "direction", cd_off++);
2743  switch_xml_set_txt_d(x_field, switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
2744 
2745  x_field = switch_xml_add_child_d(x_channel_data, "state_number", cd_off++);
2746  switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel));
2747  switch_xml_set_txt_d(x_field, tmp);
2748 
2749  if ((f = switch_channel_get_flag_string(channel))) {
2750  x_field = switch_xml_add_child_d(x_channel_data, "flags", cd_off++);
2751  switch_xml_set_txt_d(x_field, f);
2752  free(f);
2753  }
2754 
2755  if ((f = switch_channel_get_cap_string(channel))) {
2756  x_field = switch_xml_add_child_d(x_channel_data, "caps", cd_off++);
2757  switch_xml_set_txt_d(x_field, f);
2758  free(f);
2759  }
2760 
2761  if (!(variables = switch_xml_add_child_d(cdr, "call-stats", cdr_off++))) {
2762  goto error;
2763  }
2764 
2765  switch_ivr_set_xml_call_stats(variables, session, v_off, SWITCH_MEDIA_TYPE_AUDIO);
2766  switch_ivr_set_xml_call_stats(variables, session, v_off, SWITCH_MEDIA_TYPE_VIDEO);
2767 
2768 
2769  if (!(variables = switch_xml_add_child_d(cdr, "variables", cdr_off++))) {
2770  goto error;
2771  }
2772 
2773  switch_ivr_set_xml_chan_vars(variables, channel, v_off);
2774 
2775 
2776  if ((app_log = switch_core_session_get_app_log(session))) {
2777  int app_off = 0;
2778  switch_app_log_t *ap;
2779 
2780  if (!(x_apps = switch_xml_add_child_d(cdr, "app_log", cdr_off++))) {
2781  goto error;
2782  }
2783  for (ap = app_log; ap; ap = ap->next) {
2784  char tmp[128];
2785 
2786  if (!(x_application = switch_xml_add_child_d(x_apps, "application", app_off++))) {
2787  goto error;
2788  }
2789 
2790  switch_xml_set_attr_d(x_application, "app_name", ap->app);
2791  switch_xml_set_attr_d(x_application, "app_data", ap->arg);
2792 
2793  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, ap->stamp);
2794  switch_xml_set_attr_d_buf(x_application, "app_stamp", tmp);
2795  }
2796  }
2797 
2798  if (hold_record) {
2799  int cf_off = 0;
2800 
2801  if (!(xhr = switch_xml_add_child_d(cdr, "hold-record", cdr_off++))) {
2802  goto error;
2803  }
2804 
2805  for (hr = hold_record; hr; hr = hr->next) {
2806  char *t = tmp;
2807  if (!(x_hold = switch_xml_add_child_d(xhr, "hold", cf_off++))) {
2808  goto error;
2809  }
2810 
2811  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, hr->on);
2812  switch_xml_set_attr_d(x_hold, "on", t);
2813 
2814  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, hr->off);
2815  switch_xml_set_attr_d(x_hold, "off", t);
2816 
2817  if (hr->uuid) {
2818  switch_xml_set_attr_d(x_hold, "bridged-to", hr->uuid);
2819  }
2820 
2821 
2822  }
2823 
2824 
2825  }
2826 
2827 
2828 
2829  caller_profile = switch_channel_get_caller_profile(channel);
2830 
2831  while (caller_profile) {
2832  int cf_off = 0;
2833  int cp_off = 0;
2834 
2835  if (!(x_callflow = switch_xml_add_child_d(cdr, "callflow", cdr_off++))) {
2836  goto error;
2837  }
2838 
2839  if (!zstr(caller_profile->dialplan)) {
2840  switch_xml_set_attr_d(x_callflow, "dialplan", caller_profile->dialplan);
2841  }
2842 
2843  if (!zstr(caller_profile->uuid_str)) {
2844  switch_xml_set_attr_d(x_callflow, "unique-id", caller_profile->uuid_str);
2845  }
2846 
2847  if (!zstr(caller_profile->clone_of)) {
2848  switch_xml_set_attr_d(x_callflow, "clone-of", caller_profile->clone_of);
2849  }
2850 
2851  if (!zstr(caller_profile->profile_index)) {
2852  switch_xml_set_attr_d(x_callflow, "profile_index", caller_profile->profile_index);
2853  }
2854 
2855  if (caller_profile->caller_extension) {
2857  int app_off = 0;
2858 
2859  if (!(x_caller_extension = switch_xml_add_child_d(x_callflow, "extension", cf_off++))) {
2860  goto error;
2861  }
2862 
2863  switch_xml_set_attr_d(x_caller_extension, "name", caller_profile->caller_extension->extension_name);
2864  switch_xml_set_attr_d(x_caller_extension, "number", caller_profile->caller_extension->extension_number);
2865  if (caller_profile->caller_extension->current_application) {
2866  switch_xml_set_attr_d(x_caller_extension, "current_app", caller_profile->caller_extension->current_application->application_name);
2867  }
2868 
2869  for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
2870  if (!(x_application = switch_xml_add_child_d(x_caller_extension, "application", app_off++))) {
2871  goto error;
2872  }
2873  if (ap == caller_profile->caller_extension->current_application) {
2874  switch_xml_set_attr_d(x_application, "last_executed", "true");
2875  }
2876  switch_xml_set_attr_d(x_application, "app_name", ap->application_name);
2877  switch_xml_set_attr_d(x_application, "app_data", ap->application_data);
2878  }
2879 
2880  if (caller_profile->caller_extension->children) {
2881  switch_caller_profile_t *cp = NULL;
2882  int i_off = 0, i_app_off = 0;
2883  for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {
2884 
2885  if (!cp->caller_extension) {
2886  continue;
2887  }
2888  if (!(x_inner_extension = switch_xml_add_child_d(x_caller_extension, "sub_extensions", app_off++))) {
2889  goto error;
2890  }
2891 
2892  if (!(x_caller_extension = switch_xml_add_child_d(x_inner_extension, "extension", i_off++))) {
2893  goto error;
2894  }
2895  switch_xml_set_attr_d(x_caller_extension, "name", cp->caller_extension->extension_name);
2896  switch_xml_set_attr_d(x_caller_extension, "number", cp->caller_extension->extension_number);
2897  switch_xml_set_attr_d(x_caller_extension, "dialplan", cp->dialplan);
2899  switch_xml_set_attr_d(x_caller_extension, "current_app", cp->caller_extension->current_application->application_name);
2900  }
2901 
2902  for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
2903  if (!(x_application = switch_xml_add_child_d(x_caller_extension, "application", i_app_off++))) {
2904  goto error;
2905  }
2906  if (ap == cp->caller_extension->current_application) {
2907  switch_xml_set_attr_d(x_application, "last_executed", "true");
2908  }
2909  switch_xml_set_attr_d(x_application, "app_name", ap->application_name);
2910  switch_xml_set_attr_d(x_application, "app_data", ap->application_data);
2911  }
2912  }
2913  }
2914  }
2915 
2916  if (!(x_main_cp = switch_xml_add_child_d(x_callflow, "caller_profile", cf_off++))) {
2917  goto error;
2918  }
2919 
2920  cp_off += switch_ivr_set_xml_profile_data(x_main_cp, caller_profile, 0);
2921 
2922  if (caller_profile->origination_caller_profile) {
2923  switch_caller_profile_t *cp = NULL;
2924  int off = 0;
2925  if (!(x_o = switch_xml_add_child_d(x_main_cp, "origination", cp_off++))) {
2926  goto error;
2927  }
2928 
2929  for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) {
2930  if (!(x_caller_profile = switch_xml_add_child_d(x_o, "origination_caller_profile", off++))) {
2931  goto error;
2932  }
2933  switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
2934  }
2935  }
2936 
2937  if (caller_profile->originator_caller_profile) {
2938  switch_caller_profile_t *cp = NULL;
2939  int off = 0;
2940  if (!(x_o = switch_xml_add_child_d(x_main_cp, "originator", cp_off++))) {
2941  goto error;
2942  }
2943 
2944  for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
2945  if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originator_caller_profile", off++))) {
2946  goto error;
2947  }
2948  switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
2949  }
2950  }
2951 
2952  if (caller_profile->originatee_caller_profile) {
2953  switch_caller_profile_t *cp = NULL;
2954  int off = 0;
2955  if (!(x_o = switch_xml_add_child_d(x_main_cp, "originatee", cp_off++))) {
2956  goto error;
2957  }
2958  for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {
2959  if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originatee_caller_profile", off++))) {
2960  goto error;
2961  }
2962  switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
2963  }
2964  }
2965 
2966  if (caller_profile->times) {
2967  int t_off = 0;
2968  if (!(x_times = switch_xml_add_child_d(x_callflow, "times", cf_off++))) {
2969  goto error;
2970  }
2971  if (!(time_tag = switch_xml_add_child_d(x_times, "created_time", t_off++))) {
2972  goto error;
2973  }
2974  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
2975  switch_xml_set_txt_d(time_tag, tmp);
2976 
2977  if (!(time_tag = switch_xml_add_child_d(x_times, "profile_created_time", t_off++))) {
2978  goto error;
2979  }
2980  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
2981  switch_xml_set_txt_d(time_tag, tmp);
2982 
2983  if (!(time_tag = switch_xml_add_child_d(x_times, "progress_time", t_off++))) {
2984  goto error;
2985  }
2986  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
2987  switch_xml_set_txt_d(time_tag, tmp);
2988 
2989 
2990  if (!(time_tag = switch_xml_add_child_d(x_times, "progress_media_time", t_off++))) {
2991  goto error;
2992  }
2993  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
2994  switch_xml_set_txt_d(time_tag, tmp);
2995 
2996  if (!(time_tag = switch_xml_add_child_d(x_times, "answered_time", t_off++))) {
2997  goto error;
2998  }
2999  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
3000  switch_xml_set_txt_d(time_tag, tmp);
3001 
3002  if (!(time_tag = switch_xml_add_child_d(x_times, "bridged_time", t_off++))) {
3003  goto error;
3004  }
3005  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
3006  switch_xml_set_txt_d(time_tag, tmp);
3007 
3008  if (!(time_tag = switch_xml_add_child_d(x_times, "last_hold_time", t_off++))) {
3009  goto error;
3010  }
3011  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->last_hold);
3012  switch_xml_set_txt_d(time_tag, tmp);
3013 
3014  if (!(time_tag = switch_xml_add_child_d(x_times, "hold_accum_time", t_off++))) {
3015  goto error;
3016  }
3017  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum);
3018  switch_xml_set_txt_d(time_tag, tmp);
3019 
3020  if (!(time_tag = switch_xml_add_child_d(x_times, "hangup_time", t_off++))) {
3021  goto error;
3022  }
3023  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
3024  switch_xml_set_txt_d(time_tag, tmp);
3025 
3026  if (!(time_tag = switch_xml_add_child_d(x_times, "resurrect_time", t_off++))) {
3027  goto error;
3028  }
3029  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
3030  switch_xml_set_txt_d(time_tag, tmp);
3031 
3032  if (!(time_tag = switch_xml_add_child_d(x_times, "transfer_time", t_off++))) {
3033  goto error;
3034  }
3035  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->transferred);
3036  switch_xml_set_txt_d(time_tag, tmp);
3037  }
3038 
3039  caller_profile = caller_profile->next;
3040  }
3041 
3042  *xml_cdr = cdr;
3043 
3044  return SWITCH_STATUS_SUCCESS;
3045 
3046  error:
3047 
3048  if (cdr) {
3049  switch_xml_free(cdr);
3050  }
3051 
3052  return SWITCH_STATUS_FALSE;
3053 }
char * switch_channel_get_cap_string(switch_channel_t *channel)
switch_time_t stamp
Definition: switch_core.h:61
const char * switch_core_get_switchname(void)
Definition: switch_core.c:349
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
int switch_ivr_set_xml_profile_data(switch_xml_t xml, switch_caller_profile_t *caller_profile, int off)
Definition: switch_ivr.c:2463
Call Specific Data.
Definition: switch_caller.h:73
struct switch_hold_record_s * next
Definition: switch_core.h:76
switch_hold_record_t * switch_channel_get_hold_record(switch_channel_t *channel)
struct switch_caller_profile * originatee_caller_profile
#define switch_xml_add_child_d(xml, name, off)
wrapper for switch_xml_add_child() that strdup()s name
Definition: switch_xml.h:269
An Abstract Representation of a dialplan Application.
A representation of an XML tree.
Definition: switch_xml.h:76
struct switch_caller_profile * next
const char * switch_channel_state_name(_In_ switch_channel_state_t state)
Render the name of the provided state enum.
const char * dialplan
Definition: switch_caller.h:77
char * switch_channel_get_flag_string(switch_channel_t *channel)
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
int switch_ivr_set_xml_call_stats(switch_xml_t xml, switch_core_session_t *session, int off, switch_media_type_t type)
Definition: switch_ivr.c:2579
#define zstr(x)
Definition: switch_utils.h:281
struct switch_caller_application * next
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
char * switch_core_get_uuid(void)
Retrieve the unique identifier from the core.
Definition: switch_core.c:482
switch_caller_application_t * applications
switch_xml_t switch_xml_new(_In_opt_z_ const char *name)
returns a new empty switch_xml structure with the given root tag name
struct switch_caller_profile * children
#define SWITCH_TIME_T_FMT
struct switch_caller_profile * origination_caller_profile
switch_time_t profile_created
const char * profile_index
struct switch_caller_profile * originator_caller_profile
switch_caller_application_t * current_application
#define switch_xml_set_attr_d_buf(xml, name, value)
Definition: switch_xml.h:302
#define switch_xml_set_txt_d(xml, txt)
wrapper for switch_xml_set_txt() that strdup()s txt \ sets the character content for the given tag an...
Definition: switch_xml.h:283
switch_call_direction_t switch_channel_direction(switch_channel_t *channel)
switch_app_log_t * switch_core_session_get_app_log(_In_ switch_core_session_t *session)
struct switch_channel_timetable * times
int switch_ivr_set_xml_chan_vars(switch_xml_t xml, switch_channel_t *channel, int off)
Definition: switch_ivr.c:2689
#define switch_xml_set_attr_d(xml, name, value)
Wrapper for switch_xml_set_attr() that strdup()s name/value. Value cannot be NULL.
Definition: switch_xml.h:299
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
switch_time_t progress_media
struct switch_app_log * next
Definition: switch_core.h:62
struct switch_caller_extension * caller_extension
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 979 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, arg_recursion_check_start, arg_recursion_check_stop, switch_frame::buflen, CF_BREAK, teletone_generation_session::channels, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, memset(), switch_codec_implementation::microseconds_per_packet, teletone_generation_session::rate, 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(), teletone_run(), and switch_frame::user_data.

Referenced by enterprise_originate_ringback_thread().

980 {
982  switch_dtmf_t dtmf = { 0 };
983  switch_buffer_t *audio_buffer;
984  switch_frame_t *read_frame = NULL;
985  switch_codec_t write_codec = { 0 };
986  switch_frame_t write_frame = { 0 };
989  switch_codec_implementation_t read_impl = { 0 };
990  switch_core_session_get_read_impl(session, &read_impl);
991 
993  return SWITCH_STATUS_FALSE;
994  }
995 
996  if (switch_core_codec_init(&write_codec,
997  "L16",
998  NULL,
999  NULL,
1000  read_impl.actual_samples_per_second,
1001  read_impl.microseconds_per_packet / 1000,
1004 
1005  return SWITCH_STATUS_FALSE;
1006  }
1007 
1009 
1010  memset(&ts, 0, sizeof(ts));
1011  write_frame.codec = &write_codec;
1012  write_frame.data = data;
1013  write_frame.buflen = sizeof(data);
1014 
1015  switch_buffer_create_dynamic(&audio_buffer, 512, 1024, 0);
1016  teletone_init_session(&ts, 0, teletone_handler, audio_buffer);
1017  ts.rate = read_impl.actual_samples_per_second;
1018  ts.channels = 1;
1019  teletone_run(&ts, script);
1020 
1021  if (loops) {
1022  switch_buffer_set_loops(audio_buffer, loops);
1023  }
1024 
1025  for (;;) {
1026  switch_status_t status;
1027 
1028  if (!switch_channel_ready(channel)) {
1029  status = SWITCH_STATUS_FALSE;
1030  break;
1031  }
1032 
1033  if (switch_channel_test_flag(channel, CF_BREAK)) {
1035  status = SWITCH_STATUS_BREAK;
1036  break;
1037  }
1038 
1039  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1040 
1041  if (!SWITCH_READ_ACCEPTABLE(status)) {
1042  break;
1043  }
1044 
1045  if (args && args->dmachine) {
1046  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1047  break;
1048  }
1049  }
1050 
1051  if (args && (args->read_frame_callback)) {
1052  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
1053  break;
1054  }
1055  }
1056 
1057  switch_ivr_parse_all_events(session);
1058 
1059  if (args) {
1060  /*
1061  dtmf handler function you can hook up to be executed when a digit is dialed during gentones
1062  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
1063  */
1064  if (switch_channel_has_dtmf(channel)) {
1065  if (!args->input_callback && !args->buf && !args->dmachine) {
1066  status = SWITCH_STATUS_BREAK;
1067  break;
1068  }
1069  switch_channel_dequeue_dtmf(channel, &dtmf);
1070 
1071  if (args->dmachine) {
1072  char ds[2] = {dtmf.digit, '\0'};
1073  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
1074  break;
1075  }
1076  }
1077 
1078  if (args->input_callback) {
1079  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
1080  } else if (args->buf) {
1081  *((char *) args->buf) = dtmf.digit;
1082  status = SWITCH_STATUS_BREAK;
1083  }
1084  }
1085 
1086  if (args->input_callback) {
1087  switch_event_t *event;
1088 
1090  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
1091  if (ostatus != SWITCH_STATUS_SUCCESS) {
1092  status = ostatus;
1093  }
1094  switch_event_destroy(&event);
1095  }
1096  }
1097 
1098  if (status != SWITCH_STATUS_SUCCESS) {
1099  break;
1100  }
1101  }
1102 
1103  if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(audio_buffer, write_frame.data, read_impl.decoded_bytes_per_packet)) <= 0) {
1104  break;
1105  }
1106 
1107  write_frame.samples = write_frame.datalen / 2;
1108 
1110  break;
1111  }
1112  }
1113 
1114  switch_core_codec_destroy(&write_codec);
1115  switch_buffer_destroy(&audio_buffer);
1117 
1119 
1120  return SWITCH_STATUS_SUCCESS;
1121 }
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
#define arg_recursion_check_stop(_args)
int teletone_destroy_session(teletone_generation_session_t *ts)
Free the buffer allocated by a tone generation session.
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
uint8_t switch_byte_t
Definition: switch_types.h:246
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
int teletone_run(teletone_generation_session_t *ts, const char *cmd)
Execute a tone generation script and call callbacks after each instruction.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
int teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data)
Initilize a tone generation session.
uint32_t buflen
Definition: switch_frame.h:59
uint32_t datalen
Definition: switch_frame.h:57
void switch_buffer_set_loops(_In_ switch_buffer_t *buffer, _In_ int32_t loops)
Assign a number of loops to read.
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
switch_size_t switch_buffer_read_loop(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data endlessly from a switch_buffer_t.
static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map)
switch_input_callback_function_t input_callback
An abstraction of a data frame.
Definition: switch_frame.h:43
#define arg_recursion_check_start(_args)
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
switch_read_frame_callback_function_t read_frame_callback
switch_status_t
Common return values.
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
uint32_t samples
Definition: switch_frame.h:61
An abstraction to store a tone generation session.
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
A table of settings and callbacks that define a paticular implementation of a codec.
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
memset(buf, 0, buflen)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_ivr_dmachine_t * dmachine
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
sessionthe session to hold
messageoptional message
mohplay music-on-hold
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1449 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_event_set_data(), switch_channel_get_hold_music(), switch_channel_get_partner_uuid(), switch_channel_set_flag, switch_core_session_get_channel(), switch_core_session_receive_message, SWITCH_EVENT_CHANNEL_HOLD, switch_event_create, switch_event_fire, switch_ivr_broadcast(), SWITCH_MESSAGE_INDICATE_HOLD, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_hold_toggle_uuid(), and switch_ivr_hold_uuid().

1450 {
1451  switch_core_session_message_t msg = { 0 };
1453  const char *stream;
1454  const char *other_uuid;
1455  switch_event_t *event;
1456 
1458  msg.string_arg = message;
1459  msg.from = __FILE__;
1460 
1461  switch_channel_set_flag(channel, CF_HOLD);
1463 
1464  switch_core_session_receive_message(session, &msg);
1465 
1466  if (moh && (stream = switch_channel_get_hold_music(channel))) {
1467  if ((other_uuid = switch_channel_get_partner_uuid(channel))) {
1468  switch_ivr_broadcast(other_uuid, stream, SMF_ECHO_ALEG | SMF_LOOP);
1469  }
1470  }
1471 
1473  switch_channel_event_set_data(channel, event);
1474  switch_event_fire(&event);
1475  }
1476 
1477 
1478  return SWITCH_STATUS_SUCCESS;
1479 }
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
switch_status_t switch_ivr_broadcast(const char *uuid, const char *path, switch_media_flag_t flags)
Signal the session to broadcast audio.
Representation of an event.
Definition: switch_event.h:80
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
const char * switch_channel_get_hold_music(switch_channel_t *channel)
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
#define switch_channel_set_flag(_c, _f)
switch_status_t switch_ivr_hold_toggle_uuid ( const char *  uuid,
const char *  message,
switch_bool_t  moh 
)

Toggles channel hold state of session.

Parameters
uuidthe uuid of the session to hold
messageoptional message
mohplay music-on-hold
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1493 of file switch_ivr.c.

References CCS_ACTIVE, CCS_HELD, switch_channel_get_callstate(), switch_core_session_get_channel(), switch_core_session_locate, switch_core_session_rwunlock(), switch_ivr_hold(), switch_ivr_unhold(), and SWITCH_STATUS_SUCCESS.

1494 {
1496  switch_channel_t *channel;
1497  switch_channel_callstate_t callstate;
1498 
1499  if ((session = switch_core_session_locate(uuid))) {
1500  if ((channel = switch_core_session_get_channel(session))) {
1501  callstate = switch_channel_get_callstate(channel);
1502 
1503  if (callstate == CCS_ACTIVE) {
1504  switch_ivr_hold(session, message, moh);
1505  } else if (callstate == CCS_HELD) {
1506  switch_ivr_unhold(session);
1507  }
1508  }
1510  }
1511 
1512  return SWITCH_STATUS_SUCCESS;
1513 }
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.
Definition: switch_ivr.c:1449
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_core_session_t * session
switch_channel_callstate_t
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_status_t switch_ivr_unhold(switch_core_session_t *session)
Signal the session with a protocol specific unhold message.
Definition: switch_ivr.c:1515
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
switch_channel_callstate_t switch_channel_get_callstate(switch_channel_t *channel)
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
uuidthe uuid of the session to hold
messageoptional message
mohplay music-on-hold
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1481 of file switch_ivr.c.

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

Referenced by switch_core_media_toggle_hold().

1482 {
1484 
1485  if ((session = switch_core_session_locate(uuid))) {
1486  switch_ivr_hold(session, message, moh);
1488  }
1489 
1490  return SWITCH_STATUS_SUCCESS;
1491 }
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.
Definition: switch_ivr.c:1449
switch_core_session_t * session
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
switch_status_t switch_ivr_inband_dtmf_generate_session ( switch_core_session_t session,
switch_bool_t  read_stream 
)

Start generating DTMF inband.

Parameters
sessionthe session to generate on
read_streamtrue 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 3465 of file switch_ivr_async.c.

References inband_dtmf_generate_callback(), switch_inband_dtmf_generate_t::read, switch_inband_dtmf_generate_t::session, 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.

3466 {
3468  switch_media_bug_t *bug;
3469  switch_status_t status;
3471 
3472  if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
3473  return SWITCH_STATUS_FALSE;
3474  }
3475 
3476  if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
3477  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not install inband dtmf generate. Media not enabled on channel\n");
3478  return status;
3479  }
3480 
3481  if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
3482  return SWITCH_STATUS_MEMERR;
3483  }
3484 
3485  pvt->session = session;
3486  pvt->read = !!read_stream;
3487 
3488  if ((status = switch_core_media_bug_add(session, "inband_dtmf_generate", NULL,
3491  return status;
3492  }
3493 
3494  switch_channel_set_private(channel, "dtmf_generate", bug);
3495 
3496  return SWITCH_STATUS_SUCCESS;
3497 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
switch_core_session_t * session
static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session, _In_ const char *function, _In_ const char *target, _In_ switch_media_bug_callback_t callback, _In_opt_ void *user_data, _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug)
Add a media bug to the session.
switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_core_session_t * session
switch_status_t
Common return values.
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
#define switch_channel_media_up(_channel)
switch_status_t switch_ivr_inband_dtmf_session ( switch_core_session_t session)

Start looking for DTMF inband.

Parameters
sessionthe session to start looking
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3229 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, switch_inband_dtmf_t::dtmf_detect, inband_dtmf_callback(), switch_inband_dtmf_t::session, SMBF_NO_PAUSE, SMBF_ONE_ONLY, 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().

3230 {
3232  switch_media_bug_t *bug;
3233  switch_status_t status;
3234  switch_inband_dtmf_t *pvt;
3235  switch_codec_implementation_t read_impl = { 0 };
3236 
3237  switch_core_session_get_read_impl(session, &read_impl);
3238 
3239  if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
3240  return SWITCH_STATUS_MEMERR;
3241  }
3242 
3244 
3245  pvt->session = session;
3246 
3247 
3249  return SWITCH_STATUS_FALSE;
3250  }
3251 
3252  if ((status = switch_core_media_bug_add(session, "inband_dtmf", NULL,
3254  return status;
3255  }
3256 
3257  switch_channel_set_private(channel, "dtmf", bug);
3258 
3259  return SWITCH_STATUS_SUCCESS;
3260 }
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session, _In_ const char *function, _In_ const char *target, _In_ switch_media_bug_callback_t callback, _In_opt_ void *user_data, _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug)
Add a media bug to the session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_core_session_t * session
switch_core_session_t * session
static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
teletone_dtmf_detect_state_t dtmf_detect
switch_status_t
Common return values.
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
void teletone_dtmf_detect_init(teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate)
Initilize a DTMF detection state object.
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
uuidthe uuid of the session to request
flagsflags to influence behaviour (SMF_REBRIDGE to rebridge the call in media mode)
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1674 of file switch_ivr.c.

References CF_BRIDGE_ORIGINATOR, CF_BRIDGED, CF_EARLY_MEDIA, CF_MEDIA_ACK, CF_MEDIA_SET, CF_MEDIA_TRANS, CF_PROXY_MODE, CF_REQ_MEDIA, switch_core_session_message::from, switch_core_session_message::message_id, switch_core_session_message::numeric_arg, SMF_IMMEDIATE, SMF_REBRIDGE, SMF_REPLYONLY_A, SMF_REPLYONLY_B, switch_assert, switch_channel_clear_flag(), switch_channel_clear_state_handler(), switch_channel_get_name(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, 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_INUSE, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_yield.

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

1675 {
1676  const char *other_uuid = NULL;
1677  switch_channel_t *channel, *other_channel = NULL;
1678  switch_core_session_t *session, *other_session;
1679  switch_core_session_message_t msg = { 0 };
1681  uint8_t swap = 0;
1682  switch_frame_t *read_frame = NULL;
1683 
1685  msg.from = __FILE__;
1686 
1687  if ((session = switch_core_session_locate(uuid))) {
1688  channel = switch_core_session_get_channel(session);
1689 
1690  if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) {
1692  return SWITCH_STATUS_INUSE;
1693  }
1694 
1696 
1697  if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
1698  swap = 1;
1699  }
1700 
1701  if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
1702  status = SWITCH_STATUS_SUCCESS;
1703 
1704  /* If we had early media in bypass mode before, it is no longer relevant */
1705  if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
1706  switch_core_session_message_t msg2 = { 0 };
1707 
1709  msg2.from = __FILE__;
1710  switch_core_session_receive_message(session, &msg2);
1711  }
1712 
1713  if ((flags & SMF_REPLYONLY_A)) {
1714  msg.numeric_arg = 1;
1715  }
1716 
1718  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't re-establsh media on %s\n", switch_channel_get_name(channel));
1720  return SWITCH_STATUS_GENERR;
1721  }
1722 
1723  if ((flags & SMF_REPLYONLY_B)) {
1724  msg.numeric_arg = 1;
1725  } else {
1726  msg.numeric_arg = 0;
1727  }
1728 
1729  if ((flags & SMF_IMMEDIATE)) {
1731  switch_yield(250000);
1732  } else {
1733  switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1734  switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1735  switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1736  switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1737  }
1738 
1739  if ((flags & SMF_REBRIDGE)
1741  && (other_session = switch_core_session_locate(other_uuid))) {
1742  other_channel = switch_core_session_get_channel(other_session);
1743  switch_assert(other_channel != NULL);
1744  switch_core_session_receive_message(other_session, &msg);
1745  switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1746  switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1747  switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1748  switch_core_session_read_frame(other_session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1749  switch_channel_clear_state_handler(other_channel, NULL);
1750  switch_core_session_rwunlock(other_session);
1751  }
1752  if (other_channel) {
1753  switch_channel_clear_state_handler(channel, NULL);
1754  }
1755  }
1756 
1759 
1760  if (other_channel) {
1761  if (swap) {
1762  switch_ivr_uuid_bridge(other_uuid, uuid);
1763  } else {
1764  switch_ivr_uuid_bridge(uuid, other_uuid);
1765  }
1766  switch_channel_wait_for_flag(channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
1767  switch_channel_wait_for_flag(other_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
1768  }
1769  }
1770 
1771  return status;
1772 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:201
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
void switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
clear a state handler table from a given channel
#define switch_channel_get_variable(_c, _v)
switch_core_session_t * session
switch_status_t switch_ivr_uuid_bridge(const char *originator_uuid, const char *originatee_uuid)
Bridge two existing sessions.
An abstraction of a data frame.
Definition: switch_frame.h:43
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_status_t
Common return values.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_channel_set_flag(_c, _f)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_assert(expr)
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
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
sessionone session
peer_sessionthe other session
dtmf_callbacka callback for messages and dtmf
session_datadata to pass to the DTMF callback for session
peer_session_datadata to pass to the DTMF callback for peer_session
Returns
SWITCH_STATUS_SUCCESS if all is well

Referenced by bridge(), and fs_switch_ivr_originate().

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
uuidthe uuid of the session to request
flagsflags to influence behaviour (SMF_REBRIDGE to rebridge the call in no_media mode)
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1880 of file switch_ivr.c.

References CF_BRIDGE_ORIGINATOR, CF_MEDIA_ACK, CF_MEDIA_SET, CF_MEDIA_TRANS, CF_PROXY_MODE, CF_REDIRECT, CF_REQ_MEDIA, CF_RESET, CF_SECURE, CS_HIBERNATE, CS_PARK, switch_core_session_message::from, switch_core_session_message::message_id, SMF_FORCE, SMF_REBRIDGE, SWITCH_BRIDGE_VARIABLE, switch_channel_clear_flag(), switch_channel_get_name(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, 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_LOG_ERROR, switch_log_printf(), SWITCH_MESSAGE_INDICATE_NOMEDIA, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_INUSE, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_yield.

Referenced by media_thread_run(), and switch_ivr_parse_event().

1881 {
1882  const char *other_uuid;
1883  switch_channel_t *channel, *other_channel = NULL;
1884  switch_core_session_t *session, *other_session = NULL;
1885  switch_core_session_message_t msg = { 0 };
1887  uint8_t swap = 0;
1888 
1890  msg.from = __FILE__;
1891 
1892  if ((session = switch_core_session_locate(uuid))) {
1893 
1894  status = SWITCH_STATUS_SUCCESS;
1895  channel = switch_core_session_get_channel(session);
1896 
1897  if (switch_channel_test_flag(channel, CF_SECURE)) {
1900  "Cannot bypass %s due to secure connection.\n", switch_channel_get_name(channel));
1901  return SWITCH_STATUS_FALSE;
1902  }
1903 
1904  if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) {
1906  return SWITCH_STATUS_INUSE;
1907  }
1908 
1910 
1911  if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
1912  swap = 1;
1913  }
1914 
1917 
1918  if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_PROXY_MODE)) {
1919  if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
1920  (other_session = switch_core_session_locate(other_uuid))) {
1921  other_channel = switch_core_session_get_channel(other_session);
1922 
1923  switch_channel_set_flag(other_channel, CF_RESET);
1924  switch_channel_set_flag(other_channel, CF_REDIRECT);
1925 
1926  if (!switch_core_session_in_thread(session)) {
1928  }
1929  switch_channel_set_state(other_channel, CS_PARK);
1930  if (switch_core_session_in_thread(session)) {
1931  switch_yield(100000);
1932  } else {
1933  switch_channel_wait_for_state(other_channel, channel, CS_PARK);
1934  }
1935  switch_core_session_receive_message(other_session, &msg);
1936  switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1937  //switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1938  switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1939  }
1940 
1941  switch_core_session_receive_message(session, &msg);
1942 
1943  if (other_channel) {
1944  if (!switch_core_session_in_thread(session)) {
1945  switch_channel_wait_for_state(channel, NULL, CS_PARK);
1946  switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1947  switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1948  switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1949  }
1950 
1951  if (swap) {
1952  switch_ivr_signal_bridge(other_session, session);
1953  } else {
1954  switch_ivr_signal_bridge(session, other_session);
1955  }
1956 
1957  if (switch_core_session_in_thread(session)) {
1958  switch_yield(100000);
1959  } else {
1960  switch_channel_wait_for_state(other_channel, channel, CS_HIBERNATE);
1961  }
1962 
1963  if (!switch_core_session_in_thread(session)) {
1964  switch_channel_wait_for_state(channel, other_channel, CS_HIBERNATE);
1965  }
1966  switch_core_session_rwunlock(other_session);
1967  }
1968  }
1969 
1972  }
1973 
1974 
1975 
1976  return status;
1977 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
#define switch_channel_get_variable(_c, _v)
switch_core_session_t * session
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:199
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_status_t
Common return values.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_channel_set_flag(_c, _f)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
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.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_bool_t switch_core_session_in_thread(switch_core_session_t *session)
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
sessionoriginating session
blegB leg session
causea pointer to hold call cause
bridgetothe desired remote callstring
timelimit_sectimeout in seconds for outgoing call
tableoptional state handler table to install on the channel
cid_name_overrideoverride the caller id name
cid_num_overrideoverride the caller id number
caller_profile_overrideoverride the entire calling caller profile
ovarsvariables to be set on the outgoing channel
flagsflags 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 1900 of file switch_ivr_originate.c.

References switch_caller_profile::ani, switch_caller_profile::aniii, ringback::asis, ringback::audio_buffer, originate_global_t::bridge_early_media, buf, early_state::buffer, switch_frame::buflen, 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, originate_status_t::caller_profile, originate_global_t::caller_profile_override, originate_global_t::cancel_timeout, CF_ANSWERED, CF_BLOCK_STATE, CF_BRIDGED, CF_CONSUME_ON_ORIGINATE, CF_DISABLE_RINGBACK, CF_EARLY_MEDIA, CF_INTERCEPT, CF_INTERCEPTED, CF_LAZY_ATTENDED_TRANSFER, CF_NO_PRESENCE, CF_ORIGINATING, CF_ORIGINATOR, CF_PROXY_MEDIA, CF_PROXY_MODE, CF_REDIRECT, CF_RING_READY, CF_TIMESTAMP_SET, CF_TRANSFER, CF_XFER_ZOMBIE, CF_ZRTP_PASSTHRU_REQ, switch_caller_profile::chan_name, switch_file_handle::channels, check_channel_status(), check_per_channel_timeouts(), originate_global_t::check_vars, cJSON_Delete(), cJSON_PrintUnformatted(), switch_frame::codec, originate_global_t::confirm_timeout, originate_global_t::continue_on_timeout, CS_HANGUP, CS_REPORTING, CS_RESET, CS_ROUTING, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_caller_profile::destination_number, switch_dtmf_t::digit, originate_status_t::down_session, originate_global_t::early_ok, early_thread_run(), switch_codec_implementation::encoded_bytes_per_packet, originate_global_t::error_file, originate_global_t::ethread, ringback::fh, originate_global_t::file, switch_caller_profile::flags, switch_core_session_message::from, switch_event::headers, originate_global_t::hups, originate_global_t::idx, IDX_CANCEL, IDX_KEY_CANCEL, IDX_NADA, IDX_TIMEOUT, IDX_XFER, originate_global_t::ignore_early_media, originate_global_t::ignore_ring_ready, switch_codec::implementation, originate_global_t::instant_ringback, originate_global_t::key, MAX_PEERS, memset(), switch_core_session_message::message_id, originate_global_t::monitor_early_media_fail, originate_global_t::monitor_early_media_ring, early_state::mutex, ringback::mux_buf, switch_event_header::name, switch_event_header::next, switch_codec_implementation::number_of_channels, early_state::oglobals, early_state::originate_status, originate_status_t::peer_channel, peer_eligible, originate_status_t::peer_session, originate_status_t::per_channel_delay_start, originate_status_t::per_channel_progress_timelimit_sec, originate_status_t::per_channel_timelimit_sec, switch_caller_profile::pool, originate_global_t::pool, originate_global_t::progress, QUOTED_ESC_COMMA, early_state::ready, originate_global_t::return_ring_ready, originate_global_t::ring_ready, early_state::ringback, originate_global_t::ringback_ok, switch_frame::samples, switch_codec_implementation::samples_per_packet, originate_global_t::sending_ringback, originate_global_t::sent_ring, originate_global_t::session, setup_ringback(), ringback::silence, SMF_NONE, SOF_FORKED_DIAL, SOF_NO_EFFECTIVE_ANI, SOF_NO_EFFECTIVE_ANIII, SOF_NO_EFFECTIVE_CID_NAME, SOF_NO_EFFECTIVE_CID_NUM, SOF_NO_LIMITS, SOF_NOBLOCK, SOF_NONE, switch_file_handle::speed, switch_assert, SWITCH_B_SDP_VARIABLE, SWITCH_BLANK_STRING, switch_buffer_create_dynamic(), switch_buffer_destroy(), switch_buffer_inuse(), switch_buffer_peek(), switch_buffer_read(), switch_buffer_read_loop(), switch_buffer_toss(), SWITCH_BYPASS_MEDIA_VARIABLE, SWITCH_CALL_TIMEOUT_VARIABLE, switch_caller_profile_clone(), switch_caller_profile_dup(), switch_caller_profile_new(), SWITCH_CAUSE_ATTENDED_TRANSFER, SWITCH_CAUSE_CALL_REJECTED, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION, SWITCH_CAUSE_INVALID_PROFILE, SWITCH_CAUSE_LOSE_RACE, SWITCH_CAUSE_NO_ANSWER, SWITCH_CAUSE_NONE, SWITCH_CAUSE_NORMAL_UNSPECIFIED, SWITCH_CAUSE_ORIGINATOR_CANCEL, SWITCH_CAUSE_PICKED_OFF, SWITCH_CAUSE_PROGRESS_TIMEOUT, SWITCH_CAUSE_SUCCESS, SWITCH_CAUSE_USER_BUSY, switch_channel_add_state_handler(), switch_channel_add_variable_var_check(), switch_channel_answer, switch_channel_api_on(), SWITCH_CHANNEL_API_ON_ORIGINATE_VARIABLE, SWITCH_CHANNEL_API_ON_POST_ORIGINATE_VARIABLE, SWITCH_CHANNEL_API_ON_PRE_ORIGINATE_VARIABLE, switch_channel_audio_sync, switch_channel_caller_extension_masquerade(), switch_channel_cause2str(), SWITCH_CHANNEL_CHANNEL_LOG, switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_down_nosig, switch_channel_execute_on(), SWITCH_CHANNEL_EXECUTE_ON_ORIGINATE_VARIABLE, SWITCH_CHANNEL_EXECUTE_ON_POST_ORIGINATE_VARIABLE, SWITCH_CHANNEL_EXECUTE_ON_PRE_ORIGINATE_VARIABLE, switch_channel_get_caller_profile(), switch_channel_get_cause(), switch_channel_get_name(), switch_channel_get_state(), switch_channel_get_variable, switch_channel_hangup, switch_channel_has_dtmf(), switch_channel_media_ready, switch_channel_pass_callee_id(), switch_channel_pre_answer, switch_channel_process_export(), switch_channel_ready, switch_channel_restart(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_set_name(), switch_channel_set_originatee_caller_profile(), switch_channel_set_private(), switch_channel_set_profile_var(), switch_channel_set_timestamps(), switch_channel_set_variable, switch_channel_set_variable_var_check(), switch_channel_state_change_pending(), switch_channel_test_flag(), switch_channel_up_nosig, switch_channel_variable_first(), switch_channel_variable_last(), switch_channel_wait_for_state_timeout(), switch_cond_next(), switch_copy_string(), switch_core_codec_destroy(), switch_core_codec_ready(), switch_core_destroy_memory_pool, switch_core_file_close(), switch_core_file_read(), switch_core_file_seek(), switch_core_get_variable(), switch_core_media_bug_transfer_recordings(), switch_core_new_memory_pool, switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_get_uuid(), switch_core_session_locate, switch_core_session_outgoing_channel(), switch_core_session_read_frame(), switch_core_session_read_lock(), switch_core_session_receive_message, switch_core_session_reset(), switch_core_session_running(), switch_core_session_rwunlock(), switch_core_session_sprintf(), switch_core_session_thread_launch(), switch_core_session_write_frame(), switch_core_strdup, SWITCH_CPF_HIDE_NAME, SWITCH_CPF_HIDE_NUMBER, SWITCH_CPF_NONE, SWITCH_CPF_SCREEN, SWITCH_DEFAULT_CLID_NAME, SWITCH_DEFAULT_CLID_NUMBER, SWITCH_ENT_ORIGINATE_DELIM, switch_epoch_time_now(), switch_event_add_header_string(), SWITCH_EVENT_CHANNEL_DATA, switch_event_create_brackets(), switch_event_create_plain(), switch_event_del_header, switch_event_destroy(), switch_event_dup(), switch_event_get_header, switch_event_merge(), SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE, switch_false(), switch_find_end_paren(), switch_generate_sln_silence(), switch_goto_status, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, SWITCH_HOLDING_UUID_VARIABLE, SWITCH_IO_FLAG_NONE, switch_ivr_enterprise_originate(), switch_ivr_generate_json_cdr(), switch_ivr_generate_xml_cdr(), switch_ivr_media(), switch_ivr_parse_all_events(), switch_ivr_session_transfer(), switch_ivr_sleep(), switch_ivr_stop_tone_detect_session(), switch_ivr_uuid_bridge(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, SWITCH_LOG_NOTICE, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS, switch_mutex_init(), switch_mutex_lock(), SWITCH_MUTEX_NESTED, switch_mutex_unlock(), SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE, switch_process_import(), SWITCH_PROXY_MEDIA_VARIABLE, SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, switch_safe_free, switch_sanitize_number(), switch_separate_string(), switch_set_flag, SWITCH_SIGNAL_BOND_VARIABLE, switch_snprintf(), SWITCH_SOFT_HOLDING_UUID_VARIABLE, SWITCH_STACK_BOTTOM, SWITCH_STACK_PUSH, SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, switch_str_nil, switch_strchr_strict(), switch_stristr(), switch_thread_create(), switch_thread_join(), SWITCH_THREAD_STACKSIZE, switch_threadattr_create(), switch_threadattr_stacksize_set(), SWITCH_TRUE, switch_true(), switch_xml_free(), switch_xml_toxml(), switch_yield, switch_zmalloc, SWITCH_ZRTP_PASSTHRU_VARIABLE, originate_status_t::tagged, teletone_destroy_session(), ringback::ts, early_state::ttl, UNQUOTED_ESC_COMMA, switch_caller_profile::uuid, switch_event_header::value, wait_for_cause(), and zstr.

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

1910 {
1911  originate_status_t originate_status[MAX_PEERS] = { {0} };
1912  switch_originate_flag_t dftflags = SOF_NONE, myflags = dftflags;
1913  char *pipe_names[MAX_PEERS] = { 0 };
1914  char *data = NULL;
1916  switch_channel_t *caller_channel = NULL;
1917  char *peer_names[MAX_PEERS] = { 0 };
1918  switch_core_session_t *new_session = NULL, *peer_session = NULL;
1919  switch_caller_profile_t *new_profile = NULL, *caller_caller_profile;
1920  char *chan_type = NULL, *chan_data;
1921  switch_channel_t *peer_channel = NULL;
1922  ringback_t ringback = { 0 };
1923  time_t start;
1924  switch_frame_t *read_frame = NULL;
1925  int r = 0, i, and_argc = 0, or_argc = 0;
1926  int32_t sleep_ms = 1000, try = 0, retries = 1;
1927  switch_codec_t write_codec = { 0 };
1928  switch_frame_t write_frame = { 0 };
1929  char *odata, *var;
1931  switch_call_cause_t force_reason = SWITCH_CAUSE_NONE;
1932  uint8_t to = 0;
1933  char *var_val;
1934  const char *ringback_data = NULL;
1935  switch_event_t *var_event = NULL;
1936  int8_t fail_on_single_reject = 0;
1937  int8_t hangup_on_single_reject = 0;
1938  char *fail_on_single_reject_var = NULL;
1939  char *loop_data = NULL;
1940  uint32_t progress_timelimit_sec = 0;
1941  const char *cid_tmp, *lc;
1942  originate_global_t oglobals = { 0 };
1943  int cdr_total = 0;
1944  int local_clobber = 0;
1945  const char *cancel_key = NULL;
1946  const char *holding = NULL;
1947  const char *soft_holding = NULL;
1948  early_state_t early_state = { 0 };
1949  int read_packet = 0;
1950  int check_reject = 1;
1951  switch_codec_implementation_t read_impl = { 0 };
1952  const char *ani_override = NULL;
1953  const char *aniii_override = NULL;
1954  const char *ent_aleg_uuid = NULL;
1955  switch_core_session_t *a_session = session, *l_session = NULL;
1956 
1957  if (session) {
1958  caller_channel = switch_core_session_get_channel(session);
1959 
1960  if (switch_false(switch_channel_get_variable(caller_channel, "preserve_originated_vars"))) {
1961  switch_channel_set_variable(caller_channel, "originated_legs", NULL);
1962  switch_channel_set_variable(caller_channel, "originate_causes", NULL);
1963  }
1964  }
1965 
1966 
1967  if (strstr(bridgeto, SWITCH_ENT_ORIGINATE_DELIM)) {
1968  return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override,
1969  caller_profile_override, ovars, flags, cancel_cause);
1970  }
1971 
1972  oglobals.check_vars = SWITCH_TRUE;
1973  oglobals.ringback_ok = 1;
1974  oglobals.bridge_early_media = -1;
1975  oglobals.file = NULL;
1976  oglobals.error_file = NULL;
1977  switch_core_new_memory_pool(&oglobals.pool);
1978 
1979  if (caller_profile_override) {
1980  oglobals.caller_profile_override = switch_caller_profile_dup(oglobals.pool, caller_profile_override);
1981  } else if (session) {
1983 
1984  if (cp) {
1985  oglobals.caller_profile_override = switch_caller_profile_dup(oglobals.pool, cp);
1986  }
1987  }
1988 
1989  if (session) {
1990  const char *to_var, *bypass_media = NULL, *proxy_media = NULL, *zrtp_passthru = NULL;
1991  switch_channel_set_flag(caller_channel, CF_ORIGINATOR);
1992  oglobals.session = session;
1993 
1996 
1997  switch_core_session_get_read_impl(session, &read_impl);
1998 
1999  if ((to_var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
2000  timelimit_sec = atoi(to_var);
2001  }
2002 
2003  proxy_media = switch_channel_get_variable(caller_channel, SWITCH_PROXY_MEDIA_VARIABLE);
2004  bypass_media = switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_VARIABLE);
2005  zrtp_passthru = switch_channel_get_variable(caller_channel, SWITCH_ZRTP_PASSTHRU_VARIABLE);
2006 
2007  if (!zstr(proxy_media)) {
2008  if (switch_true(proxy_media)) {
2009  switch_channel_set_flag(caller_channel, CF_PROXY_MEDIA);
2010  } else if (switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
2011  switch_channel_clear_flag(caller_channel, CF_PROXY_MEDIA);
2012  }
2013  }
2014 
2015  if (!zstr(zrtp_passthru)) {
2016  if (switch_true(zrtp_passthru)) {
2018  } else if (switch_channel_test_flag(caller_channel, CF_ZRTP_PASSTHRU_REQ)) {
2020  }
2021  }
2022 
2023  if (bypass_media && switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
2024  switch_core_session_message_t msg = { 0 };
2025 
2027  msg.from = __FILE__;
2028  switch_core_session_receive_message(session, &msg);
2029  }
2030 
2031 
2032  if (!zstr(bypass_media) && !switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
2033  if (switch_true(bypass_media)) {
2034  switch_channel_set_flag(caller_channel, CF_PROXY_MODE);
2035  } else if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
2036  if (!switch_channel_test_flag(caller_channel, CF_ANSWERED) && switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
2037  switch_channel_set_variable(caller_channel, SWITCH_B_SDP_VARIABLE, NULL);
2038  switch_channel_answer(caller_channel);
2040  "Must answer channel %s due to SIP PARADOX\n", switch_channel_get_name(caller_channel));
2041  }
2042  switch_channel_set_variable(caller_channel, SWITCH_B_SDP_VARIABLE, NULL);
2044  }
2045  }
2046 
2047  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
2049  "Channel is already up, delaying proxy mode 'till both legs are answered.\n");
2050  switch_channel_set_variable(caller_channel, "bypass_media_after_bridge", "true");
2052  switch_channel_clear_flag(caller_channel, CF_PROXY_MODE);
2053  }
2054  }
2055 
2056  if (timelimit_sec <= 0) {
2057  timelimit_sec = 60;
2058  }
2059 
2060 
2061  oglobals.idx = IDX_NADA;
2062  oglobals.early_ok = 1;
2063 
2064  *bleg = NULL;
2065 
2067  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2068 
2069  odata = strdup(bridgeto);
2070 
2071  if (!odata) {
2072  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error!\n");
2073  status = SWITCH_STATUS_MEMERR;
2074  goto done;
2075  }
2076 
2077  data = odata;
2078 
2079 
2080  /* Some channel are created from an originating channel and some aren't so not all outgoing calls have a way to get params
2081  so we will normalize dialstring params and channel variables (when there is an originator) into an event that we
2082  will use as a pseudo hash to consult for params as needed.
2083  */
2084 
2085  if (ovars) {
2086  var_event = ovars;
2087  } else {
2089  abort();
2090  }
2091  }
2092 
2093  ent_aleg_uuid = switch_event_get_header(var_event, "ent_originate_aleg_uuid");
2094 
2095  if (caller_channel) {
2096  switch_channel_process_export(caller_channel, NULL, var_event, SWITCH_EXPORT_VARS_VARIABLE);
2097  }
2098 
2099  /* strip leading spaces */
2100  while (data && *data && *data == ' ') {
2101  data++;
2102  }
2103 
2104  if ((ovars && switch_true(switch_event_get_header(ovars,"origination_nested_vars"))) ||
2105  (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "origination_nested_vars")))
2106  || switch_true(switch_core_get_variable("origination_nested_vars")) || switch_stristr("origination_nested_vars=true", data)) {
2107  oglobals.check_vars = SWITCH_FALSE;
2108  }
2109 
2110 
2111  /* extract channel variables, allowing multiple sets of braces */
2112  if (*data == '<') {
2113  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing ultra-global variables\n");
2114  while (*data == '<') {
2115  char *parsed = NULL;
2116 
2117  if (switch_event_create_brackets(data, '<', '>', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
2118  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
2120  }
2121 
2122  data = parsed;
2123  }
2124  }
2125 
2126  /* extract channel variables, allowing multiple sets of braces */
2127  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing global variables\n");
2128  while (*data == '{') {
2129  char *parsed = NULL;
2130 
2131  if (switch_event_create_brackets(data, '{', '}', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
2132  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
2134  }
2135 
2136  data = parsed;
2137  }
2138 
2139 
2140  /* strip leading spaces (again) */
2141  while (data && *data && *data == ' ') {
2142  data++;
2143  }
2144 
2145  if (zstr(data)) {
2146  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "No origination URL specified!\n");
2147  status = SWITCH_STATUS_GENERR;
2148  goto done;
2149  }
2150 
2151  if (!(flags & SOF_NOBLOCK) && var_event && (var = switch_event_get_header(var_event, "originate_delay_start"))) {
2152  int tmp = atoi(var);
2153  if (tmp > 0) {
2154  while (tmp && (!cancel_cause || *cancel_cause == 0)) {
2155  switch_cond_next();
2156  tmp--;
2157  }
2158  }
2159  }
2160 
2161  if (oglobals.session) {
2163  const char *cdr_total_var;
2164  const char *cdr_var;
2165  const char *json_cdr_var;
2166 
2167  if ((cdr_var = switch_channel_get_variable(caller_channel, "failed_xml_cdr_prefix"))) {
2168  char buf[128] = "";
2169  switch_snprintf(buf, sizeof(buf), "%s_total", cdr_var);
2170  if ((cdr_total_var = switch_channel_get_variable(caller_channel, buf))) {
2171  int tmp = atoi(cdr_total_var);
2172  if (tmp > 0) {
2173  cdr_total = tmp;
2174  }
2175  }
2176  }
2177 
2178  if ((json_cdr_var = switch_channel_get_variable(caller_channel, "failed_json_cdr_prefix"))) {
2179  char buf[128] = "";
2180  switch_snprintf(buf, sizeof(buf), "%s_total", json_cdr_var);
2181  if ((cdr_total_var = switch_channel_get_variable(caller_channel, buf))) {
2182  int tmp = atoi(cdr_total_var);
2183  if (tmp > 0) {
2184  cdr_total = tmp;
2185  }
2186  }
2187  }
2188 
2189  /* Copy all the missing applicable channel variables from A-leg into the event */
2190  if ((hi = switch_channel_variable_first(caller_channel))) {
2191  for (; hi; hi = hi->next) {
2192  int ok = 0;
2193  if (!strcasecmp((char *) hi->name, "group_confirm_key")) {
2194  ok = 1;
2195  } else if (!strcasecmp((char *) hi->name, "group_confirm_file")) {
2196  ok = 1;
2197  } else if (!strcasecmp((char *) hi->name, "group_confirm_read_timeout")) {
2198  ok = 1;
2199  } else if (!strcasecmp((char *) hi->name, "group_confirm_cancel_timeout")) {
2200  ok = 1;
2201  } else if (!strcasecmp((char *) hi->name, "forked_dial")) {
2202  ok = 1;
2203  } else if (!strcasecmp((char *) hi->name, "fail_on_single_reject")) {
2204  ok = 1;
2205  } else if (!strcasecmp((char *) hi->name, "hangup_on_single_reject")) {
2206  ok = 1;
2207  } else if (!strcasecmp((char *) hi->name, "ignore_early_media")) {
2208  ok = 1;
2209  } else if (!strcasecmp((char *) hi->name, "bridge_early_media")) {
2210  ok = 1;
2211  } else if (!strcasecmp((char *) hi->name, "originate_continue_on_timeout")) {
2212  ok = 1;
2213  } else if (!strcasecmp((char *) hi->name, "ignore_ring_ready")) {
2214  ok = 1;
2215  } else if (!strcasecmp((char *) hi->name, "monitor_early_media_ring")) {
2216  ok = 1;
2217  } else if (!strcasecmp((char *) hi->name, "monitor_early_media_ring_total")) {
2218  ok = 1;
2219  } else if (!strcasecmp((char *) hi->name, "monitor_early_media_fail")) {
2220  ok = 1;
2221  } else if (!strcasecmp((char *) hi->name, "return_ring_ready")) {
2222  ok = 1;
2223  } else if (!strcasecmp((char *) hi->name, "ring_ready")) {
2224  ok = 1;
2225  } else if (!strcasecmp((char *) hi->name, "instant_ringback")) {
2226  ok = 1;
2227  } else if (!strcasecmp((char *) hi->name, "progress_timeout")) {
2228  ok = 1;
2229  } else if (!strcasecmp((char *) hi->name, "language")) {
2230  ok = 1;
2231  }
2232 
2233  if (ok && !switch_event_get_header(var_event, hi->name)) {
2234  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, (char *) hi->name, (char *) hi->value);
2235  }
2236  }
2237  switch_channel_variable_last(caller_channel);
2238  }
2239  /*
2240  if ((hi = switch_channel_variable_first(caller_channel))) {
2241  for (; hi; hi = switch_core_hash_next(&hi)) {
2242  switch_core_hash_this(hi, &vvar, NULL, &vval);
2243  if (vvar && vval) {
2244  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, (void *) vvar, (char *) vval);
2245  }
2246  }
2247  switch_channel_variable_last(caller_channel);
2248  }
2249  */
2250  }
2251 
2252  if (caller_channel) { /* ringback is only useful when there is an originator */
2253  ringback_data = NULL;
2254  cancel_key = switch_channel_get_variable(caller_channel, "origination_cancel_key");
2255 
2256  if (switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
2257  ringback_data = switch_channel_get_variable(caller_channel, "transfer_ringback");
2258  }
2259 
2260  if (!ringback_data) {
2261  ringback_data = switch_channel_get_variable(caller_channel, "ringback");
2262  }
2263 
2264  switch_channel_set_variable(caller_channel, "originate_disposition", "failure");
2265  switch_channel_set_variable(caller_channel, "DIALSTATUS", "INVALIDARGS");
2266 
2267  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
2268  ringback_data = NULL;
2269  }
2270  }
2271 #if 0
2272  /* changing behaviour ignore_early_media=true must also be explicitly set for previous behaviour */
2273  if (ringback_data) {
2274  oglobals.early_ok = 0;
2275  }
2276 #endif
2277 
2278  if (switch_true(switch_event_get_header(var_event, "group_confirm_cancel_timeout"))) {
2279  oglobals.cancel_timeout = SWITCH_TRUE;
2280  }
2281 
2282  if ((var = switch_event_get_header(var_event, "group_confirm_key"))) {
2283  switch_copy_string(oglobals.key, var, sizeof(oglobals.key));
2284  if ((var = switch_event_get_header(var_event, "group_confirm_file"))) {
2285  oglobals.file = strdup(var);
2286  }
2287  if ((var = switch_event_get_header(var_event, "group_confirm_error_file"))) {
2288  oglobals.error_file = strdup(var);
2289  }
2290  if ((var = switch_event_get_header(var_event, "group_confirm_read_timeout"))) {
2291  int tmp = atoi(var);
2292 
2293  if (tmp >= 0) {
2294  oglobals.confirm_timeout = tmp;
2295  }
2296 
2297  }
2298  }
2299  /* When using the AND operator, the fail_on_single_reject flag may be set in order to indicate that a single
2300  rejections should terminate the attempt rather than a timeout, answer, or rejection by all.
2301  If the value is set to 'true' any fail cause will end the attempt otherwise it can contain a comma (,) separated
2302  list of cause names which should be considered fatal
2303  */
2304  if ((var = switch_event_get_header(var_event, "hangup_on_single_reject"))) {
2305  hangup_on_single_reject = switch_true(var);
2306  }
2307 
2308  if ((var = switch_event_get_header(var_event, "fail_on_single_reject")) || hangup_on_single_reject) {
2309  if (var) {
2310  fail_on_single_reject_var = strdup(var);
2311  }
2312 
2313  if (switch_true(var)) {
2314  fail_on_single_reject = 1;
2315  } else {
2316  fail_on_single_reject = -1;
2317  }
2318  }
2319 
2320  if ((!zstr(oglobals.file)) && (!strcmp(oglobals.file, "undef"))) {
2321  switch_safe_free(oglobals.file);
2322  oglobals.file = NULL;
2323  }
2324  if ((!zstr(oglobals.error_file)) && (!strcmp(oglobals.error_file, "undef"))) {
2325  switch_safe_free(oglobals.error_file);
2326  oglobals.error_file = NULL;
2327  }
2328 
2329  if ((var_val = switch_event_get_header(var_event, "bridge_early_media"))) {
2330  if (switch_true(var_val)) {
2331  oglobals.early_ok = 0;
2332  oglobals.ignore_early_media = 3;
2333  }
2334  }
2335 
2336  if ((var_val = switch_event_get_header(var_event, "ignore_early_media"))) {
2337  if (switch_true(var_val)) {
2338  oglobals.early_ok = 0;
2339  oglobals.ignore_early_media = 1;
2340  } else if (!strcmp(var_val, "consume")) {
2341  oglobals.early_ok = 0;
2342  oglobals.ignore_early_media = 4;
2343  } else if (!strcmp(var_val, "ring_ready")) {
2344  oglobals.early_ok = 0;
2345  oglobals.ignore_early_media = 2;
2346  }
2347  }
2348 
2349  if ((var_val = switch_event_get_header(var_event, "originate_continue_on_timeout")) && switch_true(var_val)) {
2350  oglobals.continue_on_timeout = 1;
2351  }
2352 
2353  if ((var_val = switch_event_get_header(var_event, "ignore_ring_ready")) && switch_true(var_val)) {
2354  oglobals.ignore_ring_ready = 1;
2355  }
2356 
2357  if ((var_val = switch_event_get_header(var_event, "monitor_early_media_ring"))) {
2358  oglobals.early_ok = 0;
2359  oglobals.monitor_early_media_ring = 1;
2360  }
2361 
2362  if ((var_val = switch_event_get_header(var_event, "monitor_early_media_fail"))) {
2363  oglobals.early_ok = 0;
2364  oglobals.monitor_early_media_fail = 1;
2365  }
2366 
2367  if ((var_val = switch_event_get_header(var_event, "return_ring_ready")) && switch_true(var_val)) {
2368  oglobals.return_ring_ready = 1;
2369  }
2370 
2371  if ((var_val = switch_event_get_header(var_event, "ring_ready")) && switch_true(var_val)) {
2372  oglobals.ring_ready = 1;
2373  }
2374 
2375  if ((var_val = switch_event_get_header(var_event, "instant_ringback")) && switch_true(var_val)) {
2376  oglobals.instant_ringback = 1;
2377  }
2378 
2379  if ((var_val = switch_event_get_header(var_event, "originate_timeout"))) {
2380  int tmp = atoi(var_val);
2381  if (tmp > 0) {
2382  timelimit_sec = (uint32_t) tmp;
2383  }
2384  }
2385 
2386  if ((var_val = switch_event_get_header(var_event, "progress_timeout"))) {
2387  int tmp = atoi(var_val);
2388  if (tmp > 0) {
2389  progress_timelimit_sec = (uint32_t) tmp;
2390  }
2391  }
2392 
2393  if ((var_val = switch_event_get_header(var_event, "originate_retries")) && switch_true(var_val)) {
2394  int32_t tmp;
2395  tmp = atoi(var_val);
2396  if (tmp > 0 && tmp < 101) {
2397  retries = tmp;
2398  } else {
2400  "Invalid originate_retries setting of %d ignored, value must be between 1 and 100\n", tmp);
2401  }
2402  }
2403 
2404  if ((var_val = switch_event_get_header(var_event, "originate_retry_sleep_ms")) && switch_true(var_val)) {
2405  int32_t tmp;
2406  tmp = atoi(var_val);
2407  if (tmp >= 500 && tmp <= 60000) {
2408  sleep_ms = tmp;
2409  } else {
2411  "Invalid originate_retry_sleep_ms setting of %d ignored, value must be between 500 and 60000\n", tmp);
2412  }
2413  }
2414 
2415  /* variable to force ANI / ANIII */
2416  ani_override = switch_event_get_header(var_event, "origination_ani");
2417  aniii_override = switch_event_get_header(var_event, "origination_aniii");
2418 
2419  if ((cid_tmp = switch_event_get_header(var_event, "origination_caller_id_name"))) {
2420  cid_name_override = cid_tmp;
2421  }
2422 
2423  if (cid_name_override) {
2424  if (!cid_tmp) {
2425  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_name", cid_name_override);
2426  }
2427  } else {
2428  cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
2429  }
2430 
2431  if ((cid_tmp = switch_event_get_header(var_event, "origination_caller_id_number"))) {
2432  cid_num_override = cid_tmp;
2433  }
2434 
2435  if (cid_num_override) {
2436  if (!cid_tmp) {
2437  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_number", cid_num_override);
2438  }
2439  } else {
2440  cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
2441  }
2442 
2443  if (flags & SOF_NO_LIMITS) {
2444  dftflags |= SOF_NO_LIMITS;
2445  }
2446 
2447  if (ani_override) {
2448  dftflags |= SOF_NO_EFFECTIVE_ANI;
2449  }
2450 
2451  if (aniii_override) {
2452  dftflags |= SOF_NO_EFFECTIVE_ANIII;
2453  }
2454 
2455  if (cid_num_override) {
2456  dftflags |= SOF_NO_EFFECTIVE_CID_NUM;
2457  }
2458 
2459  if (cid_name_override) {
2460  dftflags |= SOF_NO_EFFECTIVE_CID_NAME;
2461  }
2462 
2463  if (!progress_timelimit_sec) {
2464  progress_timelimit_sec = timelimit_sec;
2465  }
2466 
2467  for (try = 0; try < retries; try++) {
2468  switch_safe_free(loop_data);
2469  loop_data = strdup(data);
2470  switch_assert(loop_data);
2471  or_argc = switch_separate_string(loop_data, '|', pipe_names, (sizeof(pipe_names) / sizeof(pipe_names[0])));
2472 
2473  if ((flags & SOF_NOBLOCK) && or_argc > 1) {
2474  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Only calling the first element in the list in this mode.\n");
2475  or_argc = 1;
2476  }
2477 
2478  for (r = 0; r < or_argc && (!cancel_cause || *cancel_cause == 0); r++) {
2479  char *p, *end = NULL;
2480  int q = 0, alt = 0;
2481 
2482  check_reject = 1;
2483 
2484  oglobals.hups = 0;
2485 
2486  reason = SWITCH_CAUSE_NONE;
2487  memset(peer_names, 0, sizeof(peer_names));
2488  peer_session = NULL;
2489  memset(originate_status, 0, sizeof(originate_status));
2490  new_profile = NULL;
2491  new_session = NULL;
2492  chan_type = NULL;
2493  chan_data = NULL;
2494  peer_channel = NULL;
2495  start = 0;
2496  read_frame = NULL;
2497  oglobals.ringback_ok = 1;
2498  var = NULL;
2499  to = 0;
2500  oglobals.sent_ring = 0;
2501  oglobals.progress = 0;
2502  myflags = dftflags;
2503 
2504 
2505  if (try > 0) {
2506  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Originate attempt %d/%d in %d ms\n", try + 1, retries,
2507  sleep_ms);
2508  if (caller_channel) {
2509  switch_ivr_sleep(oglobals.session, sleep_ms, SWITCH_TRUE, NULL);
2510  if (!switch_channel_ready(caller_channel)) {
2511  status = SWITCH_STATUS_FALSE;
2512  /* set try and retries to 0 */
2513  try = 0;
2514  retries = 0;
2515  goto done;
2516  }
2517  } else {
2518  switch_yield(sleep_ms * 1000);
2519  }
2520  }
2521 
2522  p = pipe_names[r];
2523 
2524  while (p && *p) {
2525  if (*p == '[') {
2526  end = switch_find_end_paren(p, '[', ']');
2527  if (*(p+1) == '^' && *(p + 2) == '^') {
2528  alt = 1;
2529  } else {
2530  alt = 0;
2531  }
2532  q = 0;
2533  }
2534 
2535  if (*p == '\'') {
2536  q = !q;
2537  }
2538 
2539  if (end && p < end && *p == ',' && *(p-1) != '\\') {
2540 
2541  if (q || alt) {
2542  *p = QUOTED_ESC_COMMA;
2543  } else {
2544  *p = UNQUOTED_ESC_COMMA;
2545  }
2546  }
2547 
2548  if (p == end) {
2549  end = switch_strchr_strict(p, '[', " ");
2550  }
2551 
2552  p++;
2553  }
2554 
2555  and_argc = switch_separate_string(pipe_names[r], ',', peer_names, (sizeof(peer_names) / sizeof(peer_names[0])));
2556 
2557  if ((flags & SOF_NOBLOCK) && and_argc > 1) {
2558  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Only calling the first element in the list in this mode.\n");
2559  and_argc = 1;
2560  }
2561 
2562  for (i = 0; i < and_argc; i++) {
2563  const char *current_variable;
2564  switch_event_t *local_var_event = NULL, *originate_var_event = NULL;
2565 
2566  end = NULL;
2567 
2568  chan_type = peer_names[i];
2569 
2570 
2571  /* strip leading spaces */
2572  while (chan_type && *chan_type && *chan_type == ' ') {
2573  chan_type++;
2574  }
2575 
2576  /* extract channel variables, allowing multiple sets of braces */
2577 
2578  if (*chan_type == '[') {
2580  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing session specific variables\n");
2581  }
2582 
2583  while (*chan_type == '[') {
2584  char *parsed = NULL;
2585  char *bend = switch_find_end_paren(chan_type, '[', ']');
2586 
2587  for (p = chan_type + 1; p && p < bend && *p; p++) {
2588  if (*p == QUOTED_ESC_COMMA) {
2589  *p = ',';
2590  }
2591  }
2592 
2593  if (switch_event_create_brackets(chan_type, '[', ']', UNQUOTED_ESC_COMMA,
2594  &local_var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
2595  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
2597  }
2598 
2599  if (chan_type == parsed) {
2600  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
2602  } else {
2603  chan_type = parsed;
2604  }
2605  }
2606 
2607 
2608  /* strip leading spaces (again) */
2609  while (chan_type && *chan_type && *chan_type == ' ') {
2610  chan_type++;
2611  }
2612 
2613  if ((chan_data = strchr(chan_type, '/')) != 0) {
2614  *chan_data = '\0';
2615  chan_data++;
2616  }
2617 
2618  if (oglobals.session) {
2619  if (!switch_channel_ready(caller_channel)) {
2620  status = SWITCH_STATUS_FALSE;
2621  goto done;
2622  }
2623 
2624  if ((caller_caller_profile = oglobals.caller_profile_override)) {
2625  new_profile = switch_caller_profile_dup(oglobals.pool, caller_caller_profile);
2626  } else {
2627  new_profile = switch_caller_profile_new(oglobals.pool,
2628  NULL,
2629  NULL,
2630  cid_name_override, cid_num_override, NULL, ani_override, aniii_override, NULL, __FILE__, NULL, chan_data);
2631  }
2632 
2633  new_profile->uuid = SWITCH_BLANK_STRING;
2634  new_profile->chan_name = SWITCH_BLANK_STRING;
2635  new_profile->destination_number = switch_core_strdup(new_profile->pool, chan_data);
2636 
2637  if (ani_override) {
2638  new_profile->ani = switch_core_strdup(new_profile->pool, ani_override);
2639  }
2640  if (aniii_override) {
2641  new_profile->aniii = switch_core_strdup(new_profile->pool, aniii_override);
2642  }
2643  if (cid_name_override) {
2644  new_profile->caller_id_name = switch_core_strdup(new_profile->pool, cid_name_override);
2645  }
2646  if (cid_num_override) {
2647  new_profile->caller_id_number = switch_core_strdup(new_profile->pool, cid_num_override);
2648  }
2649  } else {
2650  if (oglobals.caller_profile_override) {
2651  new_profile = switch_caller_profile_dup(oglobals.pool, oglobals.caller_profile_override);
2652  new_profile->destination_number = switch_core_strdup(new_profile->pool, switch_str_nil(chan_data));
2653  new_profile->uuid = SWITCH_BLANK_STRING;
2654  new_profile->chan_name = SWITCH_BLANK_STRING;
2655  } else {
2656  if (!cid_name_override) {
2657  cid_name_override = SWITCH_DEFAULT_CLID_NAME;
2658  }
2659  if (!cid_num_override) {
2660  cid_num_override = SWITCH_DEFAULT_CLID_NUMBER;
2661  }
2662 
2663  new_profile = switch_caller_profile_new(oglobals.pool,
2664  NULL,
2665  NULL,
2666  cid_name_override, cid_num_override, NULL, ani_override, aniii_override, NULL, __FILE__, NULL, chan_data);
2667  }
2668  }
2669 
2670  if (zstr(new_profile->destination_number)) {
2671  new_profile->destination_number = switch_core_strdup(new_profile->pool, "service");
2672  }
2673 
2674  new_profile->callee_id_name = switch_core_strdup(new_profile->pool, "Outbound Call");
2675  new_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(new_profile->pool, new_profile->destination_number));
2676 
2677  originate_status[i].caller_profile = NULL;
2678  originate_status[i].peer_channel = NULL;
2679  originate_status[i].peer_session = NULL;
2680 
2681  new_session = NULL;
2682 
2683  if (and_argc > 1 || or_argc > 1) {
2684  myflags |= SOF_FORKED_DIAL;
2685  }
2686 
2687  if (var_event) {
2688  const char *vvar;
2689  if ((vvar = switch_event_get_header(var_event, "forked_dial")) && switch_true(vvar)) {
2690  myflags |= SOF_FORKED_DIAL;
2691  }
2692  if ((vvar = switch_event_get_header(var_event, "no_throttle_limits")) && switch_true(vvar)) {
2693  myflags |= SOF_NO_LIMITS;
2694  }
2695  }
2696 
2697 
2698  /* Valid in both {} and [] with [] taking precedence */
2699 
2700  /* make a special var event with mixture of the {} and the [] vars to pass down as global vars to the outgoing channel
2701  so if something like the user channel does another originate our options will be passed down properly
2702  */
2703 
2704  switch_event_dup(&originate_var_event, var_event);
2705 
2706  if (local_var_event) {
2707  switch_event_merge(originate_var_event, local_var_event);
2708  }
2709 
2710  if ((current_variable = switch_event_get_header(originate_var_event, "origination_ani"))) {
2711  new_profile->ani = switch_core_strdup(new_profile->pool, current_variable);
2712  myflags |= SOF_NO_EFFECTIVE_ANI;
2713  }
2714 
2715  if ((current_variable = switch_event_get_header(originate_var_event, "origination_aniii"))) {
2716  new_profile->aniii = switch_core_strdup(new_profile->pool, current_variable);
2717  myflags |= SOF_NO_EFFECTIVE_ANIII;
2718  }
2719 
2720  if ((current_variable = switch_event_get_header(originate_var_event, "origination_caller_id_number"))) {
2721  new_profile->caller_id_number = switch_core_strdup(new_profile->pool, current_variable);
2722  myflags |= SOF_NO_EFFECTIVE_CID_NUM;
2723  }
2724 
2725  if ((current_variable = switch_event_get_header(originate_var_event, "origination_caller_id_name"))) {
2726  new_profile->caller_id_name = switch_core_strdup(new_profile->pool, current_variable);
2727  myflags |= SOF_NO_EFFECTIVE_CID_NAME;
2728  }
2729 
2730  if ((current_variable = switch_event_get_header(originate_var_event, "origination_privacy"))) {
2731  new_profile->flags = SWITCH_CPF_NONE;
2732 
2733  if (switch_stristr("screen", current_variable)) {
2734  switch_set_flag(new_profile, SWITCH_CPF_SCREEN);
2735  }
2736 
2737  if (switch_stristr("hide_name", current_variable)) {
2738  switch_set_flag(new_profile, SWITCH_CPF_HIDE_NAME);
2739  }
2740 
2741  if (switch_stristr("hide_number", current_variable)) {
2743  }
2744  }
2745 
2746  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "originate_early_media", oglobals.early_ok ? "true" : "false");
2747 
2748 
2749  if (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "push_channel_name"))) {
2750  char *new_name = switch_core_session_sprintf(session, "%s__B", switch_channel_get_name(caller_channel));
2751  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_channel_name", new_name);
2752  new_name = switch_core_session_sprintf(session, "_%s", switch_channel_get_name(caller_channel));
2753  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "sip_h_X-FS-Channel-Name", new_name);
2754  }
2755 
2756 
2757  reason = switch_core_session_outgoing_channel(oglobals.session, originate_var_event, chan_type,
2758  new_profile, &new_session, NULL, myflags, cancel_cause);
2759  switch_event_destroy(&originate_var_event);
2760 
2761  if (reason != SWITCH_CAUSE_SUCCESS) {
2762  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Cannot create outgoing channel of type [%s] cause: [%s]\n",
2763  chan_type, switch_channel_cause2str(reason));
2764  if (local_var_event) switch_event_destroy(&local_var_event);
2765 
2766  if (fail_on_single_reject_var) {
2767  const char *cause_str = switch_channel_cause2str(reason);
2768  int neg = *fail_on_single_reject_var == '!';
2769  int pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
2770 
2771  if (neg) {
2772  pos = !pos;
2773  }
2774 
2775  check_reject = 0;
2776 
2777  if (fail_on_single_reject == 1 || pos) {
2778  force_reason = reason;
2779  status = SWITCH_STATUS_FALSE;
2780  goto outer_for;
2781  }
2782  }
2783  continue;
2784  }
2785 
2787  status = SWITCH_STATUS_FALSE;
2788  if (local_var_event) switch_event_destroy(&local_var_event);
2789  goto done;
2790  }
2791 
2792  originate_status[i].peer_channel = switch_core_session_get_channel(new_session);
2793  originate_status[i].caller_profile = switch_channel_get_caller_profile(originate_status[i].peer_channel);
2794  originate_status[i].peer_session = new_session;
2795 
2796  switch_channel_set_flag(originate_status[i].peer_channel, CF_ORIGINATING);
2797 
2798  if (caller_channel) {
2799  switch_channel_set_variable(originate_status[i].peer_channel, "call_uuid", switch_channel_get_variable(caller_channel, "call_uuid"));
2800  }
2801 
2802 
2803  if (local_var_event) {
2804  const char *device_id = switch_event_get_header(local_var_event, "device_id");
2805  switch_channel_set_profile_var(originate_status[i].peer_channel, "device_id", device_id);
2806  }
2807 
2808  if ((lc = switch_event_get_header(var_event, "local_var_clobber"))) {
2809  local_clobber = switch_true(lc);
2810  }
2811 
2812  if (switch_channel_test_flag(originate_status[i].peer_channel, CF_NO_PRESENCE)) {
2813  if (var_event) {
2814  switch_event_del_header(var_event, "presence_id");
2815  }
2816  if (local_var_event) {
2817  switch_event_del_header(local_var_event, "presence_id");
2818  }
2819  }
2820 
2821 
2822  if (local_clobber) {
2823  if (var_event) {
2824  switch_event_header_t *header;
2825  /* install the vars from the {} params */
2826  for (header = var_event->headers; header; header = header->next) {
2827  switch_channel_set_variable_var_check(originate_status[i].peer_channel, header->name, header->value, oglobals.check_vars);
2828  }
2829  }
2830  }
2831 
2832  /* copy local originate vars to the channel */
2833  if (local_var_event) {
2834  switch_event_header_t *header;
2835  for (header = local_var_event->headers; header; header = header->next) {
2836  switch_channel_set_variable_var_check(originate_status[i].peer_channel, header->name, header->value, oglobals.check_vars);
2837  }
2838  switch_event_destroy(&local_var_event);
2839  }
2840 
2841  if (!local_clobber) {
2842  if (var_event) {
2843  switch_event_header_t *header;
2844  /* install the vars from the {} params */
2845  for (header = var_event->headers; header; header = header->next) {
2846  switch_channel_set_variable_var_check(originate_status[i].peer_channel, header->name, header->value, oglobals.check_vars);
2847  }
2848  }
2849  }
2850 
2851  if (originate_status[i].peer_channel) {
2852  const char *vvar;
2853 
2854  if (switch_true(switch_channel_get_variable(originate_status[i].peer_channel, "leg_required"))) {
2855  originate_status[i].tagged = 1;
2856  }
2857 
2858  if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "origination_channel_name"))) {
2859  switch_channel_set_name(originate_status[i].peer_channel, vvar);
2860  }
2861 
2862  if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "origination_callee_id_name"))) {
2863  switch_channel_set_profile_var(originate_status[i].peer_channel, "callee_id_name", vvar);
2864  }
2865 
2866  if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "origination_callee_id_number"))) {
2867  switch_channel_set_profile_var(originate_status[i].peer_channel, "callee_id_number", vvar);
2868  }
2869 
2870  if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "leg_timeout"))) {
2871  int val = atoi(vvar);
2872 
2873  if (val > 0) {
2874  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg timeout to %d\n",
2875  switch_channel_get_name(originate_status[i].peer_channel), val);
2876  originate_status[i].per_channel_timelimit_sec = (uint32_t) val;
2877  }
2878  }
2879 
2880  if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "leg_progress_timeout"))) {
2881  int val = atoi(vvar);
2882  if (val > 0) {
2883  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg progress timeout to %d\n",
2884  switch_channel_get_name(originate_status[i].peer_channel), val);
2885  originate_status[i].per_channel_progress_timelimit_sec = (uint32_t) val;
2886  }
2887  }
2888 
2889  if ((vvar = switch_channel_get_variable(originate_status[i].peer_channel, "leg_delay_start"))) {
2890  int val = atoi(vvar);
2891  if (val > 0) {
2892  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg delay start to %d\n",
2893  switch_channel_get_name(originate_status[i].peer_channel), val);
2894  originate_status[i].per_channel_delay_start = (uint32_t) val;
2895 
2896  if (originate_status[i].per_channel_progress_timelimit_sec != 0) {
2897  originate_status[i].per_channel_progress_timelimit_sec += originate_status[i].per_channel_delay_start;
2898  }
2899 
2900  if (originate_status[i].per_channel_timelimit_sec != 0) {
2901  originate_status[i].per_channel_timelimit_sec += originate_status[i].per_channel_delay_start;
2902  }
2903  }
2904  }
2905 
2906  if (!zstr(ent_aleg_uuid)) {
2907  l_session = switch_core_session_locate(ent_aleg_uuid);
2908  a_session = l_session;
2909  }
2910 
2911  if (a_session) {
2912  switch_channel_t *channel = switch_core_session_get_channel(a_session);
2913  char *val =
2914  switch_core_session_sprintf(a_session, "%s;%s;%s",
2915  switch_core_session_get_uuid(originate_status[i].peer_session),
2916  switch_str_nil(switch_channel_get_variable(originate_status[i].peer_channel, "callee_id_name")),
2917  switch_str_nil(switch_channel_get_variable(originate_status[i].peer_channel, "callee_id_number")));
2918 
2919 
2920  switch_channel_set_variable(originate_status[i].peer_channel, "originating_leg_uuid", switch_core_session_get_uuid(a_session));
2921 
2922  switch_channel_add_variable_var_check(channel, "originated_legs", val, SWITCH_FALSE, SWITCH_STACK_PUSH);
2923 
2924  }
2925 
2926  if (l_session) {
2927  switch_core_session_rwunlock(l_session);
2928  l_session = NULL;
2929  }
2930 
2932  switch_channel_api_on(originate_status[i].peer_channel, SWITCH_CHANNEL_API_ON_ORIGINATE_VARIABLE);
2933  }
2934 
2935  if (table) {
2936  switch_channel_add_state_handler(originate_status[i].peer_channel, table);
2937  }
2938 
2939  if (oglobals.monitor_early_media_ring || oglobals.monitor_early_media_fail || oglobals.ignore_early_media == 4) {
2940  switch_channel_set_flag(originate_status[i].peer_channel, CF_CONSUME_ON_ORIGINATE);
2941  }
2942 
2943  switch_channel_add_state_handler(originate_status[i].peer_channel, &originate_state_handlers);
2944 
2945  if ((flags & SOF_NOBLOCK) && originate_status[i].peer_session) {
2946  status = SWITCH_STATUS_SUCCESS;
2947  *bleg = originate_status[i].peer_session;
2948  *cause = SWITCH_CAUSE_SUCCESS;
2949  goto outer_for;
2950  }
2951 
2952  if (!switch_core_session_running(originate_status[i].peer_session)) {
2953  if (originate_status[i].per_channel_delay_start) {
2954  switch_channel_set_flag(originate_status[i].peer_channel, CF_BLOCK_STATE);
2955  }
2956  switch_core_session_thread_launch(originate_status[i].peer_session);
2957  }
2958  }
2959 
2960  switch_epoch_time_now(&start);
2961 
2962  for (;;) {
2963  uint32_t valid_channels = 0;
2964  for (i = 0; i < and_argc; i++) {
2965  int state;
2966  time_t elapsed;
2967 
2968  if (!originate_status[i].peer_channel) {
2969  continue;
2970  }
2971 
2972  state = switch_channel_get_state(originate_status[i].peer_channel);
2973 
2974  if (state < CS_HANGUP) {
2975  valid_channels++;
2976  } else {
2977  continue;
2978  }
2979 
2980  if (state >= CS_ROUTING) {
2981  goto endfor1;
2982  }
2983 
2984  if (caller_channel && !switch_channel_ready(caller_channel)) {
2985  goto notready;
2986  }
2987 
2988  elapsed = switch_epoch_time_now(NULL) - start;
2989 
2990  if (elapsed > (time_t) timelimit_sec) {
2991  to++;
2992  oglobals.idx = IDX_TIMEOUT;
2993  goto notready;
2994  }
2995 
2996  if (!oglobals.sent_ring && !oglobals.ignore_ring_ready &&
2997  !oglobals.progress && (progress_timelimit_sec && elapsed > (time_t) progress_timelimit_sec)) {
2998  to++;
2999  oglobals.idx = IDX_TIMEOUT;
3000  if (force_reason == SWITCH_CAUSE_NONE) {
3001  force_reason = SWITCH_CAUSE_PROGRESS_TIMEOUT;
3002  }
3003  goto notready;
3004  }
3005 
3006  switch_cond_next();
3007  }
3008 
3009  check_per_channel_timeouts(&oglobals, originate_status, and_argc, start, &force_reason);
3010 
3011 
3012  if (valid_channels == 0) {
3013  status = SWITCH_STATUS_GENERR;
3014  goto done;
3015  }
3016 
3017  }
3018 
3019  endfor1:
3020 
3021  if (caller_channel) {
3022  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) ||
3024  ringback_data = NULL;
3025  }
3026  }
3027 
3028 
3029 #if 0
3030  /* changing behaviour ignore_early_media=true must also be explicitly set for previous behaviour */
3031  if (ringback_data) {
3032  oglobals.early_ok = 0;
3033  }
3034 #endif
3035 
3036  if (ringback_data) {
3037  oglobals.sending_ringback = 1;
3038  } else {
3039  oglobals.ringback_ok = 0;
3040  }
3041 
3042  if (caller_channel) {
3043  soft_holding = switch_channel_get_variable(caller_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
3044  }
3045 
3046  while ((!caller_channel || switch_channel_ready(caller_channel) || switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) &&
3047  check_channel_status(&oglobals, originate_status, and_argc, &force_reason)) {
3048  time_t elapsed = switch_epoch_time_now(NULL) - start;
3049 
3050  read_packet = 0;
3051 
3052  if (cancel_cause && *cancel_cause > 0) {
3053  if (force_reason == SWITCH_CAUSE_NONE) {
3054  force_reason = *cancel_cause;
3055  }
3056  oglobals.idx = IDX_CANCEL;
3057  goto notready;
3058  }
3059 
3060  check_per_channel_timeouts(&oglobals, originate_status, and_argc, start, &force_reason);
3061 
3062  if (oglobals.session) {
3064  }
3065 
3066  if (!oglobals.sent_ring && !oglobals.progress && (progress_timelimit_sec && elapsed > (time_t) progress_timelimit_sec)) {
3067  oglobals.idx = IDX_TIMEOUT;
3068  if (force_reason == SWITCH_CAUSE_NONE) {
3069  force_reason = SWITCH_CAUSE_PROGRESS_TIMEOUT;
3070  }
3071  goto notready;
3072  }
3073 
3074  if ((to = (uint8_t) (elapsed >= (time_t) timelimit_sec)) || (fail_on_single_reject && oglobals.hups)) {
3075  int ok = 0;
3076 
3077  if (fail_on_single_reject_var) {
3078  if (!switch_true(fail_on_single_reject_var)) {
3079  ok = 1;
3080 
3081  for (i = 0; i < and_argc; i++) {
3082  switch_channel_t *pchannel;
3083  const char *cause_str;
3084 
3085  if (!originate_status[i].peer_session) {
3086  continue;
3087  }
3088  pchannel = switch_core_session_get_channel(originate_status[i].peer_session);
3089 
3090  if (switch_channel_down_nosig(pchannel)) {
3091  int neg, pos;
3092  cause_str = switch_channel_cause2str(switch_channel_get_cause(pchannel));
3093  neg = *fail_on_single_reject_var == '!';
3094  pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
3095 
3096  if (neg) {
3097  pos = !pos;
3098  }
3099 
3100  if (pos) {
3101  ok = 0;
3102  break;
3103  }
3104  }
3105  }
3106  }
3107  }
3108  if (!ok) {
3109  oglobals.idx = IDX_TIMEOUT;
3110  goto notready;
3111  }
3112  }
3113 
3114  /* read from the channel while we wait if the audio is up on it */
3115  if (oglobals.session &&
3116  !switch_channel_test_flag(caller_channel, CF_PROXY_MODE) &&
3117  !switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) &&
3118  !switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE) &&
3119  (oglobals.ringback_ok
3120  || (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)))) {
3121 
3123  int silence = 0;
3124 
3125  if (caller_channel && cancel_key) {
3126  if (switch_channel_has_dtmf(caller_channel)) {
3127  switch_dtmf_t dtmf = { 0, 0 };
3128  if (switch_channel_dequeue_dtmf(caller_channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
3129  if (dtmf.digit == *cancel_key) {
3130  oglobals.idx = IDX_KEY_CANCEL;
3131  goto notready;
3132  }
3133  }
3134  }
3135  }
3136 
3137  if (switch_channel_media_ready(caller_channel)) {
3138  tstatus = switch_core_session_read_frame(oglobals.session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
3139  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
3140  if (soft_holding) {
3141  switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
3142  }
3143 
3144  if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
3145  goto do_continue;
3146  }
3147  break;
3148  }
3149 
3150  read_packet++;
3151  } else {
3152  read_frame = NULL;
3153  }
3154 
3155 
3156  if (oglobals.ringback_ok && (oglobals.ring_ready || oglobals.instant_ringback ||
3157  oglobals.sending_ringback > 1 || oglobals.bridge_early_media > -1)) {
3158  if (oglobals.ringback_ok == 1) {
3159  switch_status_t rst;
3160 
3161  rst = setup_ringback(&oglobals, originate_status, and_argc, ringback_data, &ringback, &write_frame, &write_codec);
3162 
3163  if (oglobals.bridge_early_media > -1) {
3164  switch_threadattr_t *thd_attr = NULL;
3167  early_state.oglobals = &oglobals;
3168  early_state.originate_status = originate_status;
3169  early_state.ready = 1;
3170  early_state.ringback = &ringback;
3171  early_state.ttl = and_argc;
3173  switch_buffer_create_dynamic(&early_state.buffer, 1024, 1024, 0);
3174  switch_thread_create(&oglobals.ethread, thd_attr, early_thread_run, &early_state, switch_core_session_get_pool(session));
3175  }
3176 
3177 
3178  switch (rst) {
3179  case SWITCH_STATUS_SUCCESS:
3180  oglobals.ringback_ok++;
3181  break;
3182  case SWITCH_STATUS_FALSE:
3183  goto notready;
3184  break;
3185  case SWITCH_STATUS_BREAK:
3186  status = SWITCH_STATUS_FALSE;
3187  goto done;
3188  break;
3189  default:
3190  ringback_data = NULL;
3191  oglobals.ringback_ok = 0;
3192  oglobals.sending_ringback = 0;
3193  break;
3194  }
3195 
3196  goto do_continue;
3197  }
3198 
3199  if (oglobals.bridge_early_media > -1) {
3200  write_frame.datalen = 0;
3201  switch_mutex_lock(early_state.mutex);
3202  if (ringback.asis) {
3203  uint16_t mlen;
3205  if (buflen > sizeof(uint16_t)) {
3206  switch_buffer_peek(early_state.buffer, &mlen, sizeof(uint16_t));
3207  if (buflen >= (mlen + sizeof(uint16_t))) {
3208  switch_buffer_toss(early_state.buffer, sizeof(uint16_t));
3209  write_frame.datalen = (uint32_t)switch_buffer_read(early_state.buffer, write_frame.data, mlen);
3210  }
3211  }
3212  } else {
3213  if (switch_buffer_inuse(early_state.buffer) >= write_frame.codec->implementation->decoded_bytes_per_packet) {
3214  write_frame.datalen = (uint32_t)switch_buffer_read(early_state.buffer, write_frame.data,
3216  }
3217  }
3218  switch_mutex_unlock(early_state.mutex);
3219  } else if (ringback.fh) {
3220  switch_size_t mlen, olen;
3221  unsigned int pos = 0;
3222 
3223  if (ringback.asis) {
3224  mlen = write_frame.codec->implementation->encoded_bytes_per_packet;
3225  } else {
3226  mlen = write_frame.codec->implementation->samples_per_packet;
3227  }
3228 
3229  olen = mlen;
3230 
3231  //if (ringback.fh->resampler && ringback.fh->resampler->rfactor > 1) {
3232  //olen = (switch_size_t) (olen * ringback.fh->resampler->rfactor);
3233  //}
3234 
3235  switch_core_file_read(ringback.fh, write_frame.data, &olen);
3236 
3237  if (olen == 0) {
3238  olen = mlen;
3239  ringback.fh->speed = 0;
3240  switch_core_file_seek(ringback.fh, &pos, 0, SEEK_SET);
3241  switch_core_file_read(ringback.fh, write_frame.data, &olen);
3242  if (olen == 0) {
3243  break;
3244  }
3245  }
3246  write_frame.datalen = (uint32_t) (ringback.asis ? olen : olen * 2 * ringback.fh->channels);
3247  write_frame.samples = (uint32_t) olen;
3248 
3249  } else if (ringback.audio_buffer) {
3250  if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(ringback.audio_buffer,
3251  write_frame.data,
3252  write_frame.codec->implementation->decoded_bytes_per_packet)) <=
3253  0) {
3254 
3255  if (soft_holding) {
3256  switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
3257  goto do_continue;
3258  }
3259 
3260  break;
3261  }
3262  } else if (ringback.silence) {
3263  silence = ringback.silence;
3264  }
3265  } else {
3266  silence = 600;
3267  }
3268 
3269  if ((ringback.fh || silence || ringback.audio_buffer || oglobals.bridge_early_media > -1) && write_frame.codec && write_frame.codec->implementation && write_frame.datalen) {
3270  if (silence) {
3271  write_frame.datalen = read_impl.decoded_bytes_per_packet;
3272  switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, write_frame.codec->implementation->number_of_channels, silence);
3273  }
3274 
3276  if (soft_holding) {
3277  switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
3278  }
3279  if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
3280  goto do_continue;
3281  }
3282  break;
3283  }
3284  }
3285 
3286  }
3287 
3288  do_continue:
3289 
3290  if (!read_packet) {
3291  switch_yield(20000);
3292  }
3293  }
3294 
3295  notready:
3296 
3297  if (caller_channel) {
3298  holding = switch_channel_get_variable(caller_channel, SWITCH_HOLDING_UUID_VARIABLE);
3300 
3301  if (soft_holding && switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
3302  holding = soft_holding;
3303  soft_holding = NULL;
3305  }
3306  }
3307 
3308  if (caller_channel && !switch_channel_ready(caller_channel) && !switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
3309  oglobals.idx = IDX_CANCEL;
3310  }
3311 
3312  if (oglobals.session && (ringback_data || !(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) ||
3313  switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)))) {
3315  }
3316 
3317  if (holding) {
3318  if (oglobals.idx > IDX_NADA) {
3319  peer_session = originate_status[oglobals.idx].peer_session;
3320  peer_channel = originate_status[oglobals.idx].peer_channel;
3321  originate_status[oglobals.idx].peer_channel = NULL;
3322  } else if (and_argc == 1) {
3323  peer_session = originate_status[0].peer_session;
3324  peer_channel = originate_status[0].peer_channel;
3325  originate_status[0].peer_channel = NULL;
3326  } else {
3327  for (i = 0; i < and_argc; i++) {
3328  if (!peer_eligible(originate_status[i].peer_channel)) {
3329  continue;
3330  }
3331  if (switch_channel_media_ready(originate_status[i].peer_channel)) {
3332  peer_session = originate_status[i].peer_session;
3333  peer_channel = originate_status[i].peer_channel;
3334  originate_status[i].peer_channel = NULL;
3335  goto end_search;
3336  }
3337  }
3338  for (i = 0; i < and_argc; i++) {
3339  if (!peer_eligible(originate_status[i].peer_channel)) {
3340  continue;
3341  }
3342  if (switch_channel_up_nosig(originate_status[i].peer_channel)) {
3343  peer_session = originate_status[i].peer_session;
3344  peer_channel = originate_status[i].peer_channel;
3345  originate_status[i].peer_channel = NULL;
3346  break;
3347  }
3348  }
3349  }
3350 
3351  end_search:
3352 
3353  if (peer_channel && switch_channel_down_nosig(peer_channel)) {
3354  switch_core_session_rwunlock(peer_session);
3355  peer_session = NULL;
3356  peer_channel = NULL;
3357 
3358  }
3359 
3360  if (oglobals.idx == IDX_TIMEOUT || to || oglobals.idx == IDX_KEY_CANCEL || oglobals.idx == IDX_CANCEL ||
3361  (!peer_session && oglobals.idx == IDX_NADA)) {
3362  const char *dest = NULL;
3363  const char *context = NULL;
3364  const char *dialplan = NULL;
3365  switch_core_session_t *holding_session;
3366 
3367  if (caller_channel) {
3368  if (zstr(context)) {
3369  context = switch_channel_get_variable(caller_channel, "context");
3370  }
3371  if (zstr(dialplan)) {
3372  dialplan = switch_channel_get_variable(caller_channel, "dialplan");
3373  }
3374  }
3375 
3376  if (zstr(context)) {
3377  context = "default";
3378  }
3379 
3380  if (zstr(context)) {
3381  dialplan = "XML";
3382  }
3383 
3384  if ((holding_session = switch_core_session_locate(holding))) {
3385  switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
3387 
3388  if (caller_channel) {
3389  if ((mstatus = switch_channel_caller_extension_masquerade(caller_channel, holding_channel, 0)) == SWITCH_STATUS_SUCCESS) {
3390  switch_channel_restart(holding_channel);
3391  }
3392  }
3393 
3394  if (mstatus != SWITCH_STATUS_SUCCESS) {
3395  if (peer_channel) {
3396  dest = switch_channel_get_variable(peer_channel, "destination_number");
3397  context = switch_channel_get_variable(peer_channel, "context");
3398  dialplan = switch_channel_get_variable(peer_channel, "dialplan");
3399  } else if (caller_channel) {
3400  dest = switch_channel_get_variable(caller_channel, "destination_number");
3401  }
3402  if (dest) {
3403  switch_ivr_session_transfer(holding_session, dest, dialplan, context);
3404  }
3405  }
3406 
3407  switch_core_session_rwunlock(holding_session);
3408  holding = NULL;
3409  holding_session = NULL;
3410  }
3411 
3412  if (peer_channel) {
3414  switch_core_session_rwunlock(peer_session);
3415  }
3416  if (force_reason == SWITCH_CAUSE_NONE) {
3417  force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
3418  }
3419  } else if (zstr(soft_holding)) {
3420 
3421  if (peer_channel && switch_channel_ready(peer_channel)) {
3422  switch_core_session_t *holding_session;
3423 
3424  if (force_reason == SWITCH_CAUSE_NONE) {
3425  force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
3426  }
3427 
3428  if ((holding_session = switch_core_session_locate(holding))) {
3430  switch_core_session_rwunlock(holding_session);
3431  }
3433  switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(peer_session));
3434  holding = NULL;
3435  oglobals.idx = IDX_XFER;
3436  if (caller_channel && switch_channel_up_nosig(caller_channel) && !switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
3438  }
3439  caller_channel = NULL;
3440  oglobals.session = NULL;
3441  session = NULL;
3442  switch_core_session_rwunlock(peer_session);
3443  } else {
3444  switch_core_session_t *holding_session;
3445 
3446  if ((holding_session = switch_core_session_locate(holding))) {
3447  switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
3448 
3449  if (caller_channel && switch_channel_ready(caller_channel)) {
3452  holding = NULL;
3453  } else {
3455  }
3456  switch_core_session_rwunlock(holding_session);
3457  }
3458  }
3459  }
3460 
3461  peer_session = NULL;
3462  peer_channel = NULL;
3463  }
3464 
3465  for (i = 0; i < and_argc; i++) {
3466  if (!peer_eligible(originate_status[i].peer_channel)) {
3467  continue;
3468  }
3469 
3470  if (i != oglobals.idx) {
3471  holding = NULL;
3472 
3473  if (oglobals.idx == IDX_TIMEOUT || to) {
3474  reason = SWITCH_CAUSE_NO_ANSWER;
3475  } else {
3476  if (oglobals.idx == IDX_CANCEL) {
3478  } else {
3479  if (and_argc > 1) {
3480  reason = SWITCH_CAUSE_LOSE_RACE;
3481  } else if (!switch_channel_ready(originate_status[i].peer_channel)) {
3482  wait_for_cause(originate_status[i].peer_channel);
3483  if (switch_channel_down_nosig(originate_status[i].peer_channel)) {
3484  reason = switch_channel_get_cause(originate_status[i].peer_channel);
3485  }
3486  } else {
3487  reason = SWITCH_CAUSE_NO_ANSWER;
3488  }
3489  }
3490  }
3491  if (switch_channel_up_nosig(originate_status[i].peer_channel)) {
3492  if (caller_channel && i == 0) {
3495  }
3496 
3497  if (holding && oglobals.idx != IDX_TIMEOUT && oglobals.idx != IDX_KEY_CANCEL && oglobals.idx < 0) {
3498  switch_core_session_t *holding_session;
3499 
3500  if ((holding_session = switch_core_session_locate(holding))) {
3501  switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
3502 
3504 
3505  if (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "recording_follow_transfer"))) {
3506  switch_core_media_bug_transfer_recordings(session, originate_status[i].peer_session);
3507  }
3508 
3509  if (switch_true(switch_channel_get_variable(holding_channel, "recording_follow_transfer"))) {
3510  switch_core_media_bug_transfer_recordings(holding_session, originate_status[i].peer_session);
3511  }
3512 
3513  switch_core_session_rwunlock(holding_session);
3514  }
3515  switch_channel_set_flag(originate_status[i].peer_channel, CF_LAZY_ATTENDED_TRANSFER);
3516  switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(originate_status[i].peer_session));
3517  holding = NULL;
3518  } else {
3519  if (force_reason == SWITCH_CAUSE_LOSE_RACE || reason == SWITCH_CAUSE_LOSE_RACE) {
3520  switch_channel_set_variable(originate_status[i].peer_channel, "group_dial_status", "loser");
3521  }
3522  switch_channel_hangup(originate_status[i].peer_channel, force_reason ? force_reason : reason);
3523  }
3524  }
3525  }
3526  }
3527 
3528 
3529 
3530  if (oglobals.idx > IDX_NADA) {
3531  if ((peer_session = originate_status[oglobals.idx].peer_session)) {
3532  peer_channel = switch_core_session_get_channel(originate_status[oglobals.idx].peer_session);
3533  }
3534  } else {
3535  status = SWITCH_STATUS_FALSE;
3536  if (caller_channel && peer_channel) {
3537  switch_process_import(oglobals.session, peer_channel, "import", NULL);
3538  }
3539  peer_channel = NULL;
3540  goto done;
3541  }
3542 
3543  if (caller_channel) {
3544  if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
3545  switch_channel_pass_callee_id(peer_channel, caller_channel);
3546  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
3547  status = SWITCH_STATUS_SUCCESS;
3548  } else {
3549  status = switch_channel_answer(caller_channel);
3550  }
3551  } else if (switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
3552  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
3553  status = SWITCH_STATUS_SUCCESS;
3554  } else {
3555  switch_channel_pass_callee_id(peer_channel, caller_channel);
3556  status = switch_channel_pre_answer(caller_channel);
3557  }
3558  } else {
3559  status = SWITCH_STATUS_SUCCESS;
3560  }
3561 
3562  if (status != SWITCH_STATUS_SUCCESS) {
3563  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(peer_channel), SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n",
3564  switch_channel_get_name(caller_channel));
3566  }
3567  }
3568 
3569  if (switch_channel_test_flag(peer_channel, CF_ANSWERED) ||
3570  (oglobals.early_ok && switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) ||
3571  (oglobals.return_ring_ready && switch_channel_test_flag(peer_channel, CF_RING_READY))
3572  ) {
3573  *bleg = peer_session;
3574 
3575  if (oglobals.monitor_early_media_ring || oglobals.monitor_early_media_fail) {
3577  switch_channel_set_private(peer_channel, "_oglobals_", NULL);
3578  }
3579 
3580  status = SWITCH_STATUS_SUCCESS;
3581  } else {
3582  status = SWITCH_STATUS_FALSE;
3583  }
3584 
3585  done:
3586 
3587  *cause = SWITCH_CAUSE_NONE;
3588 
3589  if (caller_channel && !switch_channel_ready(caller_channel)) {
3590  status = SWITCH_STATUS_FALSE;
3591  }
3592 
3593  if (status == SWITCH_STATUS_SUCCESS) {
3594  if (caller_channel) {
3595  switch_channel_set_variable(caller_channel, "originate_disposition", "call accepted");
3596  if (peer_channel) {
3597  switch_process_import(oglobals.session, peer_channel, "import", NULL);
3598 
3599  if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
3600  switch_channel_set_variable(caller_channel, "DIALSTATUS", "EARLY");
3601  } else {
3602  switch_channel_set_variable(caller_channel, "DIALSTATUS", "ANSWER");
3603  }
3604 
3605  }
3606  }
3607  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oglobals.session), SWITCH_LOG_DEBUG, "Originate Resulted in Success: [%s]\n",
3608  switch_channel_get_name(peer_channel));
3609  *cause = SWITCH_CAUSE_SUCCESS;
3610 
3611  } else {
3612  const char *cdr_var = NULL;
3613  const char *json_cdr_var = NULL;
3614 
3615  switch_xml_t cdr = NULL;
3616  cJSON *json_cdr = NULL;
3617 
3618  char *json_text;
3619  char *xml_text;
3620  char buf[128] = "", buf2[128] = "";
3621 
3622  if (caller_channel) {
3623  cdr_var = switch_channel_get_variable(caller_channel, "failed_xml_cdr_prefix");
3624  }
3625 
3626  if (caller_channel) {
3627  json_cdr_var = switch_channel_get_variable(caller_channel, "failed_json_cdr_prefix");
3628  }
3629 
3630  if (peer_channel) {
3631  wait_for_cause(peer_channel);
3632  *cause = switch_channel_get_cause(peer_channel);
3633  } else {
3634  for (i = 0; i < and_argc; i++) {
3635  if (!originate_status[i].peer_channel) {
3636  continue;
3637  }
3638  *cause = switch_channel_get_cause(originate_status[i].peer_channel);
3639  break;
3640  }
3641  }
3642 
3643  if (cdr_var) {
3644  for (i = 0; i < and_argc; i++) {
3645  switch_channel_t *channel;
3646 
3647  if (!originate_status[i].peer_session) {
3648  continue;
3649  }
3650 
3651  channel = switch_core_session_get_channel(originate_status[i].peer_session);
3652 
3654 
3655  if (!switch_channel_test_flag(channel, CF_TIMESTAMP_SET)) {
3657  }
3658 
3659  if (switch_ivr_generate_xml_cdr(originate_status[i].peer_session, &cdr) == SWITCH_STATUS_SUCCESS) {
3660  if ((xml_text = switch_xml_toxml(cdr, SWITCH_FALSE))) {
3661  switch_snprintf(buf, sizeof(buf), "%s_%d", cdr_var, ++cdr_total);
3662  switch_channel_set_variable(caller_channel, buf, xml_text);
3663  switch_safe_free(xml_text);
3664  }
3665  switch_xml_free(cdr);
3666  cdr = NULL;
3667  }
3668 
3669  }
3670  switch_snprintf(buf, sizeof(buf), "%s_total", cdr_var);
3671  switch_snprintf(buf2, sizeof(buf2), "%d", cdr_total ? cdr_total : 0);
3672  switch_channel_set_variable(caller_channel, buf, buf2);
3673  }
3674 
3675  if (json_cdr_var) {
3676  for (i = 0; i < and_argc; i++) {
3677  switch_channel_t *channel;
3678 
3679  if (!originate_status[i].peer_session) {
3680  continue;
3681  }
3682 
3683  channel = switch_core_session_get_channel(originate_status[i].peer_session);
3684 
3686 
3687  if (!switch_channel_test_flag(channel, CF_TIMESTAMP_SET)) {
3689  }
3690 
3691  if (switch_ivr_generate_json_cdr(originate_status[i].peer_session, &json_cdr, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
3692  json_text = cJSON_PrintUnformatted(json_cdr);
3693  switch_snprintf(buf, sizeof(buf), "%s_%d", json_cdr_var, ++cdr_total);
3694  switch_channel_set_variable(caller_channel, buf, json_text);
3695  // switch_safe_free(json_text);
3696  cJSON_Delete(json_cdr);
3697  json_cdr = NULL;
3698  }
3699 
3700  }
3701  switch_snprintf(buf, sizeof(buf), "%s_total", json_cdr_var);
3702  switch_snprintf(buf2, sizeof(buf2), "%d", cdr_total ? cdr_total : 0);
3703  switch_channel_set_variable(caller_channel, buf, buf2);
3704  }
3705 
3706  if (caller_channel && switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
3707  *cause = SWITCH_CAUSE_PICKED_OFF;
3708  }
3709 
3710  if (!*cause) {
3711  if (reason) {
3712  *cause = reason;
3713  } else if (caller_channel) {
3714  *cause = switch_channel_get_cause(caller_channel);
3715  } else {
3717  for (i = 0; i < and_argc; i++) {
3718  if (!peer_eligible(originate_status[i].peer_channel)) {
3719  continue;
3720  }
3721 
3722  wait_for_cause(originate_status[i].peer_channel);
3723 
3724  if (switch_channel_down_nosig(originate_status[i].peer_channel)) {
3725  *cause = switch_channel_get_cause(originate_status[i].peer_channel);
3726  break;
3727  }
3728 
3729  }
3730  }
3731  }
3732 
3733  if (*cause == SWITCH_CAUSE_SUCCESS || *cause == SWITCH_CAUSE_NONE) {
3735  }
3736 
3737  if (oglobals.idx == IDX_CANCEL) {
3740  "Originate Cancelled by originator termination Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
3741 
3742  } else if (oglobals.idx == IDX_TIMEOUT) {
3743  *cause = SWITCH_CAUSE_NO_ANSWER;
3744  } else {
3745  if (oglobals.idx == IDX_XFER) {
3747  "Originate Resulted in Attended Transfer Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
3748  } else {
3749 
3751  "Originate Resulted in Error Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
3752  }
3753  }
3754  }
3755 
3756  if (caller_channel) {
3757  switch_channel_set_variable(caller_channel, "originate_disposition", switch_channel_cause2str(*cause));
3758 
3759  switch (*cause) {
3761  switch_channel_set_variable(caller_channel, "DIALSTATUS", "CANCEL");
3762  break;
3764  switch_channel_set_variable(caller_channel, "DIALSTATUS", "BUSY");
3765  break;
3767  switch_channel_set_variable(caller_channel, "DIALSTATUS", "NOANSWER");
3768  break;
3771  switch_channel_set_variable(caller_channel, "DIALSTATUS", "INVALIDARGS");
3772  break;
3774  switch_channel_set_variable(caller_channel, "DIALSTATUS", "DONTCALL");
3775  break;
3776  default:
3777  switch_channel_set_variable(caller_channel, "DIALSTATUS", switch_channel_cause2str(*cause));
3778  break;
3779  }
3780  }
3781 
3782  early_state.ready = 0;
3783 
3784  if (oglobals.ethread) {
3785  switch_status_t st;
3786  switch_thread_join(&st, oglobals.ethread);
3787  }
3788 
3789  if (early_state.buffer) {
3790  switch_buffer_destroy(&early_state.buffer);
3791  }
3792 
3793  if (ringback.fh) {
3794  switch_core_file_close(ringback.fh);
3795  ringback.fh = NULL;
3796  } else if (ringback.audio_buffer) {
3797  teletone_destroy_session(&ringback.ts);
3798  switch_safe_free(ringback.mux_buf);
3800  }
3801 
3802  if (oglobals.session) {
3804  }
3805 
3806  if (switch_core_codec_ready(&write_codec)) {
3807  switch_core_codec_destroy(&write_codec);
3808  }
3809 
3810  for (i = 0; i < and_argc; i++) {
3811  switch_channel_state_t state;
3812  switch_core_session_t *peer_session;
3813  char *val;
3814 
3815  if (!originate_status[i].peer_channel) {
3816  continue;
3817  }
3818 
3819  if (session) {
3820  val = switch_core_session_sprintf(originate_status[i].peer_session, "%s;%s",
3821  switch_core_session_get_uuid(originate_status[i].peer_session),
3822  switch_channel_cause2str(switch_channel_get_cause(originate_status[i].peer_channel)));
3823 
3825  }
3826 
3827  if (status == SWITCH_STATUS_SUCCESS) {
3828  switch_channel_clear_flag(originate_status[i].peer_channel, CF_ORIGINATING);
3829  if (bleg && *bleg && *bleg == originate_status[i].peer_session) {
3830  continue;
3831  }
3832  } else if ((state = switch_channel_get_state(originate_status[i].peer_channel)) < CS_HANGUP &&
3833  switch_channel_test_flag(originate_status[i].peer_channel, CF_ORIGINATING)) {
3834  if (!(state == CS_RESET || switch_channel_test_flag(originate_status[i].peer_channel, CF_TRANSFER) ||
3835  switch_channel_test_flag(originate_status[i].peer_channel, CF_REDIRECT) ||
3836  switch_channel_test_flag(originate_status[i].peer_channel, CF_BRIDGED))) {
3837  if (caller_channel && switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
3838  switch_channel_set_flag(originate_status[i].peer_channel, CF_INTERCEPT);
3839  }
3840  switch_channel_hangup(originate_status[i].peer_channel, *cause);
3841  }
3842  }
3843  switch_channel_clear_flag(originate_status[i].peer_channel, CF_ORIGINATING);
3844 
3845  peer_session = originate_status[i].peer_session;
3846  originate_status[i].down_session = originate_status[i].peer_session;
3847  originate_status[i].peer_session = NULL;
3848  originate_status[i].peer_channel = NULL;
3849 
3850  switch_core_session_rwunlock(peer_session);
3851  }
3852 
3853  if (status == SWITCH_STATUS_SUCCESS || oglobals.idx == IDX_XFER) {
3854  goto outer_for;
3855  } else {
3856  int ok = 1;
3857 
3858  if (fail_on_single_reject && check_reject && !switch_true(fail_on_single_reject_var)) {
3859  for (i = 0; i < and_argc; i++) {
3860  switch_channel_t *pchannel;
3861  const char *cause_str;
3862 
3863  if (!originate_status[i].down_session) {
3864  continue;
3865  }
3866 
3867  pchannel = switch_core_session_get_channel(originate_status[i].down_session);
3868  wait_for_cause(pchannel);
3869 
3870  if (switch_channel_down_nosig(pchannel)) {
3871  int neg, pos;
3872 
3873  cause_str = switch_channel_cause2str(switch_channel_get_cause(pchannel));
3874 
3875  neg = *fail_on_single_reject_var == '!';
3876  pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
3877 
3878  if (neg) {
3879  pos = !pos;
3880  }
3881 
3882  if (pos) {
3883  ok = 0;
3884  break;
3885  }
3886  }
3887  }
3888  }
3889 
3890  if (!ok) {
3891  goto outer_for;
3892  }
3893 
3894  if (to && !oglobals.continue_on_timeout) {
3895  goto outer_for;
3896  }
3897  }
3898  }
3899  }
3900  outer_for:
3901  switch_safe_free(loop_data);
3902  switch_safe_free(odata);
3903  switch_safe_free(oglobals.file);
3904  switch_safe_free(oglobals.error_file);
3905 
3906  if (bleg && status != SWITCH_STATUS_SUCCESS) {
3907  *bleg = NULL;
3908  }
3909 
3910  if (bleg && !*bleg && status == SWITCH_STATUS_SUCCESS) {
3911  status = SWITCH_STATUS_FALSE;
3912  }
3913 
3914  if (bleg && *bleg) {
3916 
3917  if (session && caller_channel) {
3919 
3920  if (peer_profile) {
3921  if ((cloned_profile = switch_caller_profile_clone(session, peer_profile)) != 0) {
3922  switch_channel_set_originatee_caller_profile(caller_channel, cloned_profile);
3923  }
3924  }
3925 
3927  // Now main SWITCH_SIGNAL_BOND_VARIABLE is populated, don't need this one anymore...
3929  }
3930 
3931 
3934 
3935 
3936  while(switch_channel_state_change_pending(bchan)) {
3937  switch_cond_next();
3938  }
3939 
3941 
3942  if (caller_channel) {
3943  switch_channel_audio_sync(caller_channel);
3944  }
3945  }
3946 
3947  if (oglobals.session) {
3949  }
3950 
3951  if (oglobals.session && status == SWITCH_STATUS_SUCCESS) {
3952  switch_ivr_sleep(oglobals.session, 0, SWITCH_TRUE, NULL);
3953  }
3954 
3955  if (var_event && var_event != ovars) {
3956  switch_event_destroy(&var_event);
3957  }
3958 
3959  switch_safe_free(write_frame.data);
3960  switch_safe_free(fail_on_single_reject_var);
3961 
3962  if (force_reason != SWITCH_CAUSE_NONE) {
3963  *cause = force_reason;
3964  }
3965 
3966  if (caller_channel) {
3967 
3970 
3971  switch_channel_clear_flag(caller_channel, CF_ORIGINATOR);
3972  switch_channel_clear_flag(caller_channel, CF_XFER_ZOMBIE);
3973 
3974  if (hangup_on_single_reject) {
3975  switch_channel_hangup(caller_channel, *cause);
3976  }
3977  }
3978 
3979 
3981 
3982  return status;
3983 }
#define SWITCH_DEFAULT_CLID_NUMBER
Definition: switch_types.h:114
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
#define switch_channel_answer(channel)
Answer a channel (initiate/acknowledge a successful connection)
switch_status_t switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix)
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
char * switch_core_session_sprintf(_In_ switch_core_session_t *session, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the session ...
switch_status_t switch_channel_set_profile_var(switch_channel_t *channel, const char *name, const char *val)
Set a variable on a given channel.
#define SWITCH_CHANNEL_SESSION_LOG(x)
Call Specific Data.
Definition: switch_caller.h:73
char * switch_xml_toxml(_In_ switch_xml_t xml, _In_ switch_bool_t prn_header)
Converts an switch_xml structure back to xml in html format. Returns a string of html data that \ mus...
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_status_t switch_channel_set_timestamps(_In_ switch_channel_t *channel)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
switch_size_t switch_buffer_read(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available. Remove read data fr...
switch_memory_pool_t * pool
switch_caller_profile_t * caller_profile
char * switch_find_end_paren(const char *s, char open, char close)
Definition: switch_utils.c:661
#define switch_event_del_header(_e, _h)
Definition: switch_event.h:211
switch_core_session_t * down_session
static char * switch_sanitize_number(char *number)
Definition: switch_utils.h:668
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
const char * switch_channel_cause2str(_In_ switch_call_cause_t cause)
return a cause string for a given cause
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
#define SWITCH_CHANNEL_EXECUTE_ON_PRE_ORIGINATE_VARIABLE
Definition: switch_types.h:155
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.
Definition: switch_ivr.c:127
teletone_generation_session_t ts
switch_channel_t * peer_channel
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
switch_status_t switch_event_create_brackets(char *data, char a, char b, char c, switch_event_t **event, char **new_data, switch_bool_t dup)
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
#define UNQUOTED_ESC_COMMA
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:660
#define SWITCH_CALL_TIMEOUT_VARIABLE
Definition: switch_types.h:169
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:640
Representation of an event.
Definition: switch_event.h:80
switch_status_t switch_core_file_close(_In_ switch_file_handle_t *fh)
Close an open file handle.
#define switch_channel_ready(_channel)
An event Header.
Definition: switch_event.h:65
switch_status_t switch_core_session_read_lock(_In_ switch_core_session_t *session)
Acquire a read lock on the session.
switch_caller_profile_t * switch_caller_profile_clone(_In_ switch_core_session_t *session, _In_ switch_caller_profile_t *tocopy)
Clone an existing caller profile object.
void switch_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t channels, uint32_t divisor)
Generate static noise.
#define SWITCH_PROXY_MEDIA_VARIABLE
Definition: switch_types.h:189
#define switch_channel_media_ready(_channel)
switch_status_t switch_core_file_seek(_In_ switch_file_handle_t *fh, unsigned int *cur_pos, int64_t samples, int whence)
Seek a position in a file.
int teletone_destroy_session(teletone_generation_session_t *ts)
Free the buffer allocated by a tone generation session.
switch_thread_t * ethread
A representation of an XML tree.
Definition: switch_xml.h:76
switch_call_cause_t switch_core_session_outgoing_channel(_In_opt_ switch_core_session_t *session, _In_opt_ switch_event_t *var_event, _In_z_ const char *endpoint_name, _In_ switch_caller_profile_t *caller_profile, _Inout_ switch_core_session_t **new_session, _Inout_ switch_memory_pool_t **pool, _In_ switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
Request an outgoing session spawned from an existing session using a desired endpoing module...
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
switch_status_t switch_core_file_read(_In_ switch_file_handle_t *fh, void *data, switch_size_t *len)
Read media from a file handle.
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)
uint32_t switch_originate_flag_t
Definition: switch_types.h:325
switch_caller_profile_t * switch_caller_profile_new(_In_ switch_memory_pool_t *pool, _In_opt_z_ const char *username, _In_opt_z_ const char *dialplan, _In_opt_z_ const char *caller_id_name, _In_opt_z_ const char *caller_id_number, _In_opt_z_ const char *network_addr, _In_opt_z_ const char *ani, _In_opt_z_ const char *aniii, _In_opt_z_ const char *rdnis, _In_opt_z_ const char *source, _In_opt_z_ const char *context, _In_opt_z_ const char *destination_number)
Create a new caller profile object.
switch_status_t switch_core_media_bug_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session)
originate_status_t * originate_status
switch_status_t switch_event_dup(switch_event_t **event, switch_event_t *todup)
Duplicate an event.
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
switch_event_header_t * switch_channel_variable_first(switch_channel_t *channel)
Start iterating over the entries in the channel variable list.
#define SWITCH_ZRTP_PASSTHRU_VARIABLE
Definition: switch_types.h:190
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.
Definition: switch_ivr.c:1674
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
static void wait_for_cause(switch_channel_t *channel)
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
#define SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE
Definition: switch_types.h:203
#define zstr(x)
Definition: switch_utils.h:281
#define SWITCH_DEFAULT_CLID_NAME
Definition: switch_types.h:113
static char * switch_strchr_strict(const char *in, char find, const char *allowed)
Definition: switch_utils.h:301
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.
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:290
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1255
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:216
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
switch_size_t switch_buffer_toss(_In_ switch_buffer_t *buffer, _In_ switch_size_t datalen)
Remove data from the buffer.
#define SWITCH_CHANNEL_EXECUTE_ON_ORIGINATE_VARIABLE
Definition: switch_types.h:153
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:59
switch_byte_t switch_byte_t * buf
#define SWITCH_SOFT_HOLDING_UUID_VARIABLE
Definition: switch_types.h:171
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
#define switch_channel_audio_sync(_c)
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
uint32_t datalen
Definition: switch_frame.h:57
void switch_event_merge(switch_event_t *event, switch_event_t *tomerge)
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
const char * callee_id_number
Definition: switch_caller.h:89
void switch_channel_process_export(switch_channel_t *channel, switch_channel_t *peer_channel, switch_event_t *var_event, const char *export_varname)
#define peer_eligible(_peer)
switch_status_t switch_channel_add_variable_var_check(switch_channel_t *channel, const char *varname, const char *value, switch_bool_t var_check, switch_stack_t stack)
switch_core_session_t * session
switch_mutex_t * mutex
#define switch_channel_get_variable(_c, _v)
#define SWITCH_BYPASS_MEDIA_VARIABLE
Definition: switch_types.h:188
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:551
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
uint32_t per_channel_progress_timelimit_sec
switch_status_t switch_channel_caller_extension_masquerade(switch_channel_t *orig_channel, switch_channel_t *new_channel, uint32_t offset)
#define switch_zmalloc(ptr, len)
switch_core_session_t * session
switch_size_t switch_buffer_read_loop(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data endlessly from a switch_buffer_t.
switch_buffer_t * buffer
const char * caller_id_name
Definition: switch_caller.h:79
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_status_t switch_ivr_uuid_bridge(const char *originator_uuid, const char *originatee_uuid)
Bridge two existing sessions.
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:270
#define SWITCH_BLANK_STRING
Definition: switch_types.h:47
#define SWITCH_ENT_ORIGINATE_DELIM
Definition: switch_types.h:46
#define switch_channel_down_nosig(_channel)
An abstraction of a data frame.
Definition: switch_frame.h:43
uintptr_t switch_size_t
switch_status_t switch_ivr_stop_tone_detect_session(switch_core_session_t *session)
Stop looking for TONES.
#define MAX_PEERS
switch_byte_t switch_byte_t uint32_t buflen
void switch_cond_next(void)
Definition: switch_time.c:638
char * switch_core_get_variable(_In_z_ const char *varname)
Retrieve a global variable from the core.
void switch_channel_wait_for_state_timeout(switch_channel_t *other_channel, switch_channel_state_t want_state, uint32_t timeout)
void switch_channel_restart(switch_channel_t *channel)
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
switch_call_cause_t
static switch_status_t switch_event_create_plain(switch_event_t **event, switch_event_types_t event_id)
Definition: switch_event.h:385
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_caller_profile_flag_t flags
switch_status_t switch_channel_set_variable_var_check(switch_channel_t *channel, const char *varname, const char *value, switch_bool_t var_check)
switch_bool_t cancel_timeout
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
switch_core_session_t * peer_session
#define SWITCH_CHANNEL_API_ON_POST_ORIGINATE_VARIABLE
Definition: switch_types.h:166
unsigned int switch_core_session_running(_In_ switch_core_session_t *session)
determine if the session's state machine is running
static switch_status_t setup_ringback(originate_global_t *oglobals, originate_status_t *originate_status, int len, const char *ringback_data, ringback_t *ringback, switch_frame_t *write_frame, switch_codec_t *write_codec)
switch_channel_state_t
Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are ...
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.
Definition: switch_ivr.c:3177
switch_status_t
Common return values.
ringback_t * ringback
#define SWITCH_HOLDING_UUID_VARIABLE
Definition: switch_types.h:170
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:256
originate_global_t * oglobals
struct switch_event_header * next
Definition: switch_event.h:76
#define SWITCH_SIGNAL_BOND_VARIABLE
Definition: switch_types.h:202
void switch_channel_variable_last(switch_channel_t *channel)
Stop iterating over channel variables.
static int check_per_channel_timeouts(originate_global_t *oglobals, originate_status_t *originate_status, int max, time_t start, switch_call_cause_t *force_reason)
void switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
Set the given channel's originatee caller profile.
#define SWITCH_CHANNEL_EXECUTE_ON_POST_ORIGINATE_VARIABLE
Definition: switch_types.h:154
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
int switch_channel_state_change_pending(switch_channel_t *channel)
switch_caller_profile_t * caller_profile_override
#define SWITCH_B_SDP_VARIABLE
Definition: switch_types.h:198
switch_size_t switch_buffer_peek(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available, without removing re...
switch_buffer_t * audio_buffer
uint32_t samples
Definition: switch_frame.h:61
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
#define switch_channel_set_flag(_c, _f)
switch_status_t switch_channel_set_name(switch_channel_t *channel, const char *name)
Assign a name to a given channel.
#define SWITCH_CHANNEL_API_ON_ORIGINATE_VARIABLE
Definition: switch_types.h:165
switch_caller_profile_t * switch_caller_profile_dup(_In_ switch_memory_pool_t *pool, _In_ switch_caller_profile_t *tocopy)
Duplicate an existing caller profile object.
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:321
const char * caller_id_number
Definition: switch_caller.h:81
#define SWITCH_CHANNEL_API_ON_PRE_ORIGINATE_VARIABLE
Definition: switch_types.h:167
int switch_channel_add_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
add a state handler table to a given channel
static switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
const char * switch_stristr(const char *instr, const char *str)
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:642
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:675
A table of settings and callbacks that define a paticular implementation of a codec.
static int switch_false(const char *expr)
Evaluate the falsefullness of a string expression.
Definition: switch_utils.h:482
#define switch_channel_up_nosig(_channel)
void switch_event_destroy(switch_event_t **event)
Destroy an event.
#define QUOTED_ESC_COMMA
void switch_process_import(switch_core_session_t *session, switch_channel_t *peer_channel, const char *varname, const char *prefix)
static void *SWITCH_THREAD_FUNC early_thread_run(switch_thread_t *thread, void *obj)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_assert(expr)
#define switch_channel_set_variable(_channel, _var, _val)
switch_file_handle_t * fh
switch_status_t switch_ivr_generate_xml_cdr(switch_core_session_t *session, switch_xml_t *xml_cdr)
Generate an XML CDR report.
Definition: switch_ivr.c:2713
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
switch_status_t switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix)
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
void cJSON_Delete(cJSON *c)
Definition: switch_json.c:93
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_status_t switch_channel_pass_callee_id(switch_channel_t *channel, switch_channel_t *other_channel)
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
memset(buf, 0, buflen)
static uint8_t check_channel_status(originate_global_t *oglobals, originate_status_t *originate_status, uint32_t len, switch_call_cause_t *force_reason)
static const switch_state_handler_table_t originate_state_handlers
#define SWITCH_CHANNEL_CHANNEL_LOG(x)
const char * callee_id_name
Definition: switch_caller.h:87
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
char * cJSON_PrintUnformatted(cJSON *item)
Definition: switch_json.c:285
switch_event_header_t * headers
Definition: switch_event.h:90
#define SWITCH_EXPORT_VARS_VARIABLE
Definition: switch_types.h:194
switch_call_cause_t switch_channel_get_cause(_In_ switch_channel_t *channel)
return the cause code for a given channel
switch_status_t switch_core_session_thread_launch(_In_ switch_core_session_t *session)
Launch the session thread (state machine) on a given session.
switch_memory_pool_t * pool
switch_status_t switch_ivr_park ( switch_core_session_t session,
switch_input_args_t args 
)

Definition at line 892 of file switch_ivr.c.

References switch_codec_implementation::actual_samples_per_second, arg_recursion_check_start, arg_recursion_check_stop, 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, memset(), 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_goto_status, 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().

893 {
896  switch_frame_t *read_frame = NULL;
897  int stream_id = 0;
898  switch_event_t *event;
899  switch_unicast_conninfo_t *conninfo = NULL;
900  uint32_t rate = 0;
901  uint32_t bpf = 0;
902  const char *to;
903  int timeout = 0;
904  time_t expires = 0;
905  switch_codec_implementation_t read_impl = { 0 };
907  switch_codec_t codec = { 0 };
908  int sval = 0;
909  const char *var;
910  switch_frame_t write_frame = { 0 };
911  unsigned char *abuf = NULL;
912  switch_codec_implementation_t imp = { 0 };
913 
914 
915 
918  }
919 
920  if (switch_channel_test_flag(channel, CF_CONTROLLED)) {
921  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot park channels that are under control already.\n");
922  return SWITCH_STATUS_FALSE;
923  }
924 
925  if (switch_channel_get_state(channel) == CS_RESET) {
926  return SWITCH_STATUS_FALSE;
927  }
928 
930 
931  if ((to = switch_channel_get_variable(channel, "park_timeout"))) {
932  char *cause_str;
933 
934  if ((cause_str = strchr(to, ':'))) {
935  timeout_cause = switch_channel_str2cause(cause_str + 1);
936  }
937 
938  if ((timeout = atoi(to)) < 0) {
939  timeout = 0;
940  } else {
941  expires = switch_epoch_time_now(NULL) + timeout;
942  }
943  switch_channel_set_variable(channel, "park_timeout", NULL);
945  }
946 
949 
951  switch_channel_event_set_data(channel, event);
952  switch_event_fire(&event);
953  }
954 
956 
957  if (!rate && switch_channel_media_ready(channel)) {
958  switch_core_session_get_read_impl(session, &read_impl);
959  rate = read_impl.actual_samples_per_second;
960  bpf = read_impl.decoded_bytes_per_packet;
961 
962  if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
963  switch_core_session_get_read_impl(session, &imp);
964 
965  if (switch_core_codec_init(&codec,
966  "L16",
967  NULL,
968  NULL,
970  imp.microseconds_per_packet / 1000,
971  imp.number_of_channels,
974  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
977  }
978 
979 
980  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
982 
983  write_frame.codec = &codec;
985  write_frame.data = abuf;
987  write_frame.datalen = imp.decoded_bytes_per_packet;
988  write_frame.samples = write_frame.datalen / sizeof(int16_t);
989  }
990  }
991 
992  if (rate) {
993  if (switch_channel_test_flag(channel, CF_SERVICE)) {
995  status = SWITCH_STATUS_SUCCESS;
996  } else {
997  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, stream_id);
998  }
999  } else {
1000  switch_yield(20000);
1001 
1003  switch_ivr_parse_event(session, event);
1004  switch_event_destroy(&event);
1005  }
1006 
1007  status = SWITCH_STATUS_SUCCESS;
1008  }
1009 
1010  if (!SWITCH_READ_ACCEPTABLE(status)) {
1011  break;
1012  }
1013 
1014  if (rate && write_frame.data && sval) {
1015  switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, read_impl.number_of_channels, sval);
1016  switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
1017  }
1018 
1019  if (expires && switch_epoch_time_now(NULL) >= expires) {
1020  switch_channel_hangup(channel, timeout_cause);
1021  break;
1022  }
1023 
1024  if (switch_channel_test_flag(channel, CF_UNICAST)) {
1025  if (!switch_channel_media_ready(channel)) {
1028  }
1029  }
1030 
1031  if (!conninfo) {
1032  if (!(conninfo = switch_channel_get_private(channel, "unicast"))) {
1034  }
1035 
1036  if (conninfo) {
1037  unicast_thread_launch(conninfo);
1038  }
1039  }
1040 
1041  if (conninfo) {
1042  switch_size_t len = 0;
1043  uint32_t flags = 0;
1045  uint32_t dlen = sizeof(decoded);
1046  switch_status_t tstatus;
1047  switch_byte_t *sendbuf = NULL;
1048  uint32_t sendlen = 0;
1049 
1050  switch_assert(read_frame);
1051 
1052  if (switch_test_flag(read_frame, SFF_CNG)) {
1053  sendlen = bpf;
1055  memset(decoded, 255, sendlen);
1056  sendbuf = decoded;
1057  tstatus = SWITCH_STATUS_SUCCESS;
1058  } else {
1059  if (switch_test_flag(conninfo, SUF_NATIVE)) {
1060  tstatus = SWITCH_STATUS_NOOP;
1061  } else {
1062  switch_codec_t *read_codec = switch_core_session_get_read_codec(session);
1063  tstatus = switch_core_codec_decode(read_codec,
1064  &conninfo->read_codec,
1065  read_frame->data,
1066  read_frame->datalen, read_impl.actual_samples_per_second, decoded, &dlen, &rate, &flags);
1067  }
1068  switch (tstatus) {
1069  case SWITCH_STATUS_NOOP:
1070  case SWITCH_STATUS_BREAK:
1071  sendbuf = read_frame->data;
1072  sendlen = read_frame->datalen;
1073  tstatus = SWITCH_STATUS_SUCCESS;
1074  break;
1075  case SWITCH_STATUS_SUCCESS:
1076  sendbuf = decoded;
1077  sendlen = dlen;
1078  tstatus = SWITCH_STATUS_SUCCESS;
1079  break;
1080  default:
1083  break;
1084  }
1085  }
1086 
1087  if (tstatus == SWITCH_STATUS_SUCCESS) {
1088  len = sendlen;
1089  if (switch_socket_sendto(conninfo->socket, conninfo->remote_addr, 0, (void *) sendbuf, &len) != SWITCH_STATUS_SUCCESS) {
1091  }
1092  }
1093  }
1094  }
1095 
1096  switch_ivr_parse_all_events(session);
1097 
1098 
1099  if (switch_channel_has_dtmf(channel)) {
1100  switch_dtmf_t dtmf = { 0 };
1101 
1102  if (args && !args->input_callback && !args->buf && !args->dmachine) {
1103  status = SWITCH_STATUS_BREAK;
1104  break;
1105  }
1106 
1107  switch_channel_dequeue_dtmf(channel, &dtmf);
1108 
1109  if (args) {
1110  if (args->dmachine) {
1111  char ds[2] = {dtmf.digit, '\0'};
1112  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
1113  break;
1114  }
1115  }
1116 
1117  if (args->input_callback) {
1118  if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
1119  break;
1120  }
1121  }
1122  }
1123  }
1124 
1126  if (args && args->input_callback) {
1127  switch_status_t ostatus;
1128 
1129  if ((ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
1130  status = ostatus;
1131  break;
1132  }
1133  } else {
1134  switch_channel_event_set_data(channel, event);
1135  switch_event_fire(&event);
1136  }
1137  }
1138 
1139  if (args && args->dmachine) {
1140  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1141  break;
1142  }
1143  }
1144 
1145 
1146  }
1147 
1148  end:
1149 
1151 
1152  if (write_frame.codec) {
1153  switch_core_codec_destroy(&codec);
1154  }
1155 
1156  switch_safe_free(abuf);
1157 
1160 
1162  switch_channel_event_set_data(channel, event);
1163  switch_event_fire(&event);
1164  }
1165 
1166  if (switch_channel_test_flag(channel, CF_UNICAST)) {
1168  }
1169 
1170  return status;
1171 }
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
switch_socket_t * socket
Definition: switch_ivr.h:52
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
#define arg_recursion_check_stop(_args)
void switch_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t channels, uint32_t divisor)
Generate static noise.
#define switch_channel_media_ready(_channel)
switch_sockaddr_t * remote_addr
Definition: switch_ivr.h:58
switch_status_t switch_core_codec_decode(switch_codec_t *codec, switch_codec_t *other_codec, void *encoded_data, uint32_t encoded_data_len, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
Decode data using a codec handle.
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
uint8_t switch_byte_t
Definition: switch_types.h:246
switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
#define SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE
Definition: switch_types.h:129
#define SWITCH_PARK_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:217
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
static void unicast_thread_launch(switch_unicast_conninfo_t *conninfo)
Definition: switch_ivr.c:355
uint32_t buflen
Definition: switch_frame.h:59
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
uint32_t datalen
Definition: switch_frame.h:57
switch_status_t switch_socket_sendto(switch_socket_t *sock, switch_sockaddr_t *where, int32_t flags, const char *buf, switch_size_t *len)
Definition: switch_apr.c:773
switch_status_t switch_ivr_parse_event(switch_core_session_t *session, switch_event_t *event)
Definition: switch_ivr.c:497
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
#define switch_zmalloc(ptr, len)
switch_codec_t read_codec
Definition: switch_ivr.h:49
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_input_callback_function_t input_callback
switch_status_t switch_core_session_dequeue_private_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event)
DE-Queue a private event on a given session.
switch_call_cause_t switch_channel_str2cause(_In_ const char *str)
return a cause code for a given string
An abstraction of a data frame.
Definition: switch_frame.h:43
uintptr_t switch_size_t
#define arg_recursion_check_start(_args)
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
void switch_cond_next(void)
Definition: switch_time.c:638
switch_call_cause_t
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:256
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
uint32_t samples
Definition: switch_frame.h:61
#define switch_channel_set_flag(_c, _f)
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:321
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
switch_status_t switch_ivr_deactivate_unicast(switch_core_session_t *session)
Definition: switch_ivr.c:365
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_assert(expr)
#define switch_channel_set_variable(_channel, _var, _val)
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
memset(buf, 0, buflen)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_ivr_dmachine_t * dmachine
switch_status_t switch_ivr_parse_all_events ( switch_core_session_t session)

Parse all commands from an event.

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

Definition at line 867 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(), and SWITCH_STATUS_SUCCESS.

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_originate(), switch_ivr_park(), switch_ivr_play_file(), switch_ivr_record_file(), switch_ivr_session_echo(), switch_ivr_sleep(), and switch_ivr_wait_for_answer().

868 {
869  int x = 0;
870  switch_channel_t *channel;
871 
873 
874  channel = switch_core_session_get_channel(session);
875 
877  if (switch_channel_media_up(channel)) {
879  } else {
880  return SWITCH_STATUS_SUCCESS;
881  }
882  }
883 
885  x++;
886  }
887 
888  return SWITCH_STATUS_SUCCESS;
889 }
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_parse_next_event(switch_core_session_t *session)
Definition: switch_ivr.c:755
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_channel_media_up(_channel)
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:801
switch_status_t switch_ivr_parse_all_messages ( switch_core_session_t session)

Definition at line 801 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_core_session_run(), 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().

802 {
804  int i = 0;
805 
807 
808  while (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) {
809  i++;
810 
811  if (switch_ivr_process_indications(session, message) == SWITCH_STATUS_SUCCESS) {
813  } else {
814  switch_core_session_receive_message(session, message);
815  message = NULL;
816  }
817  }
818 
820 }
switch_status_t switch_ivr_parse_all_signal_data(switch_core_session_t *session)
Definition: switch_ivr.c:859
switch_status_t switch_ivr_process_indications(switch_core_session_t *session, switch_core_session_message_t *message)
Definition: switch_ivr.c:772
void switch_core_session_free_message(switch_core_session_message_t **message)
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
switch_status_t switch_core_session_dequeue_message(_In_ switch_core_session_t *session, _Out_ switch_core_session_message_t **message)
DE-Queue an message on a given session.
switch_status_t switch_ivr_parse_all_signal_data ( switch_core_session_t session)

Definition at line 859 of file switch_ivr.c.

References SWITCH_FALSE, switch_ivr_parse_signal_data(), and SWITCH_TRUE.

Referenced by switch_ivr_parse_all_messages().

859  {
861 }
switch_status_t switch_ivr_parse_signal_data(switch_core_session_t *session, switch_bool_t all, switch_bool_t only_session_thread)
Definition: switch_ivr.c:823
switch_status_t switch_ivr_parse_event ( _In_ switch_core_session_t session,
_In_ switch_event_t event 
)

Parse command from an event.

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

Referenced by switch_ivr_speak_text_handle().

switch_status_t switch_ivr_parse_next_event ( switch_core_session_t session)

Definition at line 755 of file switch_ivr.c.

References switch_channel_event_set_data(), switch_core_session_dequeue_private_event(), switch_core_session_get_channel(), switch_event_fire, switch_event_prep_for_delivery, SWITCH_EVENT_PRIVATE_COMMAND, switch_ivr_parse_event(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by audio_bridge_thread(), and switch_ivr_parse_all_events().

756 {
757  switch_event_t *event;
759 
761  status = switch_ivr_parse_event(session, event);
762  event->event_id = SWITCH_EVENT_PRIVATE_COMMAND;
765  switch_event_fire(&event);
766  }
767 
768  return status;
769 
770 }
#define switch_event_prep_for_delivery(_event)
Definition: switch_event.h:242
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_parse_event(switch_core_session_t *session, switch_event_t *event)
Definition: switch_ivr.c:497
switch_status_t switch_core_session_dequeue_private_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event)
DE-Queue a private event on a given session.
switch_status_t
Common return values.
switch_status_t switch_ivr_parse_next_signal_data ( switch_core_session_t session)

Definition at line 863 of file switch_ivr.c.

References SWITCH_FALSE, and switch_ivr_parse_signal_data().

863  {
865 }
switch_status_t switch_ivr_parse_signal_data(switch_core_session_t *session, switch_bool_t all, switch_bool_t only_session_thread)
Definition: switch_ivr.c:823
switch_status_t switch_ivr_parse_signal_data ( switch_core_session_t session,
switch_bool_t  all,
switch_bool_t  only_session_thread 
)

Definition at line 823 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_in_thread(), switch_core_session_receive_message, SWITCH_MESSAGE_INDICATE_SIGNAL_DATA, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_channel_check_signal(), switch_ivr_parse_all_signal_data(), and switch_ivr_parse_next_signal_data().

824 {
825  void *data;
826  switch_core_session_message_t msg = { 0 };
827  int i = 0;
829 
830  if (only_session_thread && !switch_core_session_in_thread(session)) {
831  return SWITCH_STATUS_FALSE;
832  }
833 
835  return SWITCH_STATUS_FALSE;
836  }
837 
839 
841  msg.from = __FILE__;
842 
844  i++;
845 
846  msg.pointer_arg = data;
848 
849  data = NULL;
850  if (!all)
851  break;
852  }
853 
855 
857 }
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_session_dequeue_signal_data(switch_core_session_t *session, void **signal_data)
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
#define switch_channel_set_flag(_c, _f)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
switch_bool_t switch_core_session_in_thread(switch_core_session_t *session)
switch_status_t switch_ivr_pause_detect_speech ( switch_core_session_t session)

Pause background Speech detection on a session.

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

Definition at line 4590 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().

4591 {
4594 
4595  if (sth) {
4596  switch_core_asr_pause(sth->ah);
4597  return SWITCH_STATUS_SUCCESS;
4598  }
4599  return SWITCH_STATUS_FALSE;
4600 }
switch_asr_handle_t * ah
switch_status_t switch_core_asr_pause(switch_asr_handle_t *ah)
Pause detection on an asr handle.
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
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
sessionthe session to play and detect on
filethe path to the file
mod_namethe module name of the ASR library
grammarthe grammar text, URI, or local file name
resultof speech recognition, allocated from the session pool
input_timeouttime to wait for input
argsarguements to pass for callbacks etc
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 4245 of file switch_ivr_async.c.

References arg_recursion_check_start, arg_recursion_check_stop, play_and_detect_speech_state_t::done, PLAY_AND_DETECT_DONE, PLAY_AND_DETECT_DONE_RECOGNIZING, play_and_detect_input_callback(), play_and_detect_speech_state_t::result, switch_channel_get_name(), switch_channel_get_variable, 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_ivr_stop_detect_speech(), SWITCH_LOG_INFO, switch_log_printf(), SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, and switch_true().

4252 {
4254  int recognizing = 0;
4255  switch_input_args_t myargs = { 0 };
4258 
4260 
4261  if (result == NULL) {
4262  goto done;
4263  }
4264 
4265  if (!input_timeout) input_timeout = 5000;
4266 
4267  if (!args) {
4268  args = &myargs;
4269  }
4270 
4271  /* start speech detection */
4272  if ((status = switch_ivr_detect_speech(session, mod_name, grammar, "", NULL, NULL)) != SWITCH_STATUS_SUCCESS) {
4273  /* map SWITCH_STATUS_FALSE to SWITCH_STATUS_GENERR to indicate grammar load failed
4274  SWITCH_STATUS_NOT_INITALIZED will be passed back to indicate ASR resource problem */
4275  if (status == SWITCH_STATUS_FALSE) {
4276  status = SWITCH_STATUS_GENERR;
4277  }
4278  goto done;
4279  }
4280  recognizing = 1;
4281 
4282  /* play the prompt, looking for detection result */
4284  args->buf = &state;
4285  args->buflen = sizeof(state);
4286  status = switch_ivr_play_file(session, NULL, file, args);
4287 
4289  state.done |= PLAY_AND_DETECT_DONE;
4290  goto done;
4291  }
4292 
4293  if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) {
4294  status = SWITCH_STATUS_FALSE;
4295  goto done;
4296  }
4297 
4298  /* wait for result if not done */
4299  if (!state.done) {
4301  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) WAITING FOR RESULT\n", switch_channel_get_name(channel));
4302  while (!state.done && switch_channel_ready(channel)) {
4303  status = switch_ivr_sleep(session, input_timeout, SWITCH_FALSE, args);
4304 
4306  state.done |= PLAY_AND_DETECT_DONE;
4307  goto done;
4308  }
4309 
4310  if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) {
4311  status = SWITCH_STATUS_FALSE;
4312  goto done;
4313  }
4314  }
4315  }
4316 
4317 
4318 
4319 done:
4320  if (recognizing && !(state.done & PLAY_AND_DETECT_DONE_RECOGNIZING)) {
4322  }
4323  if (recognizing && switch_true(switch_channel_get_variable(channel, "play_and_detect_speech_close_asr"))) {
4325  }
4326 
4327  if (state.done) {
4328  status = SWITCH_STATUS_SUCCESS;
4329  }
4330  *result = state.result;
4331 
4333 
4334  return status;
4335 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
static switch_status_t play_and_detect_input_callback(switch_core_session_t *session, void *input, switch_input_type_t input_type, void *data, unsigned int len)
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.
Definition: switch_ivr.c:127
#define switch_channel_ready(_channel)
#define arg_recursion_check_stop(_args)
#define PLAY_AND_DETECT_DONE_RECOGNIZING
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
#define PLAY_AND_DETECT_DONE
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
switch_status_t switch_ivr_dmachine_last_ping(switch_ivr_dmachine_t *dmachine)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given 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.
#define switch_channel_get_variable(_c, _v)
switch_input_callback_function_t input_callback
#define arg_recursion_check_start(_args)
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
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
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_ivr_dmachine_t * dmachine
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
sessionthe session to play the file too
fhfile handle to use (NULL for builtin one)
filethe path to the file
argsarguements to pass for callbacks etc
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1153 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, arg_recursion_check_start, arg_recursion_check_stop, switch_directories::base_dir, switch_frame::buflen, buflen, CF_BREAK, CF_HOLD, CF_VIDEO, switch_frame::channels, switch_frame::codec, cur, 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, memset(), 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_audio_sync, switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_event_set_data(), switch_channel_get_name(), 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_locked, 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_has_video(), switch_core_file_open, switch_core_file_read(), switch_core_file_seek(), switch_core_media_set_video_file(), 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_merge(), SWITCH_EVENT_PLAYBACK_START, SWITCH_EVENT_PLAYBACK_STOP, SWITCH_FALSE, SWITCH_FILE_BREAK_ON_CHANGE, SWITCH_FILE_CALLBACK, SWITCH_FILE_DATA_SHORT, SWITCH_FILE_FLAG_READ, SWITCH_FILE_FLAG_VIDEO, 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_is_parsing(), 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_RW_WRITE, switch_safe_free, switch_separate_string(), switch_set_flag_locked, 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_true(), SWITCH_URL_SEPARATOR, switch_yield, switch_zmalloc, switch_frame::timestamp, switch_frame::user_data, 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().

1154 {
1156  int16_t *abuf = NULL;
1157  switch_dtmf_t dtmf = { 0 };
1158  uint32_t interval = 0, samples = 0, framelen, sample_start = 0, channels = 1;
1159  uint32_t ilen = 0;
1160  switch_size_t olen = 0, llen = 0;
1161  switch_frame_t write_frame = { 0 };
1162  switch_timer_t timer = { 0 };
1163  switch_codec_t codec = { 0 };
1165  char *codec_name;
1168  const char *p;
1169  //char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
1170  char *ext;
1171  const char *prefix;
1172  const char *timer_name;
1173  const char *prebuf;
1174  const char *alt = NULL;
1175  const char *sleep_val;
1176  const char *play_delimiter_val;
1177  char play_delimiter = 0;
1178  int sleep_val_i = 250;
1179  int eof = 0;
1180  switch_size_t bread = 0;
1181  int l16 = 0;
1182  switch_codec_implementation_t read_impl = { 0 };
1183  char *file_dup;
1184  char *argv[128] = { 0 };
1185  int argc;
1186  int cur;
1187  int done = 0;
1188  int timeout_samples = 0;
1189  switch_bool_t timeout_as_success = SWITCH_FALSE;
1190  const char *var;
1191  int more_data = 0;
1192  switch_event_t *event;
1193  uint32_t test_native = 0, last_native = 0;
1194  uint32_t buflen = 0;
1195  int flags;
1196 
1198  return SWITCH_STATUS_FALSE;
1199  }
1200 
1201  switch_core_session_get_read_impl(session, &read_impl);
1202 
1203  if ((var = switch_channel_get_variable(channel, "playback_timeout_sec"))) {
1204  int tmp = atoi(var);
1205  if (tmp > 1) {
1206  timeout_samples = read_impl.actual_samples_per_second * tmp;
1207  }
1208  }
1209 
1210  if ((var = switch_channel_get_variable(channel, "playback_timeout_as_success"))) {
1211  if (switch_true(var)) {
1212  timeout_as_success = SWITCH_TRUE;
1213  }
1214  }
1215  if ((play_delimiter_val = switch_channel_get_variable(channel, "playback_delimiter"))) {
1216  play_delimiter = *play_delimiter_val;
1217 
1218  if ((sleep_val = switch_channel_get_variable(channel, "playback_sleep_val"))) {
1219  int tmp = atoi(sleep_val);
1220  if (tmp >= 0) {
1221  sleep_val_i = tmp;
1222  }
1223  }
1224  }
1225 
1226  prefix = switch_channel_get_variable(channel, "sound_prefix");
1227  timer_name = switch_channel_get_variable(channel, "timer_name");
1228 
1229  if (zstr(file) || !switch_channel_media_ready(channel)) {
1230  return SWITCH_STATUS_FALSE;
1231  }
1232 
1234 
1235  if (!zstr(read_impl.iananame) && !strcasecmp(read_impl.iananame, "l16")) {
1236  l16++;
1237  }
1238 
1239  if (play_delimiter) {
1240  file_dup = switch_core_session_strdup(session, file);
1241  argc = switch_separate_string(file_dup, play_delimiter, argv, (sizeof(argv) / sizeof(argv[0])));
1242  } else {
1243  argc = 1;
1244  argv[0] = (char *) file;
1245  }
1246 
1247  if (!fh) {
1248  fh = &lfh;
1249  memset(fh, 0, sizeof(lfh));
1250  }
1251 
1252  if (fh->samples > 0) {
1253  sample_start = fh->samples;
1254  fh->samples = 0;
1255  }
1256 
1257 
1258 
1259 
1260  for (cur = 0; switch_channel_ready(channel) && !done && cur < argc; cur++) {
1261  file = argv[cur];
1262  eof = 0;
1263 
1264  if (cur) {
1265  fh->samples = sample_start = 0;
1266  if (sleep_val_i) {
1267  status = switch_ivr_sleep(session, sleep_val_i, SWITCH_FALSE, args);
1268  if(status != SWITCH_STATUS_SUCCESS) {
1269  break;
1270  }
1271  }
1272  }
1273 
1274  status = SWITCH_STATUS_SUCCESS;
1275 
1276  if ((alt = strchr(file, ':'))) {
1277  char *dup;
1278 
1279  if (!strncasecmp(file, "phrase:", 7)) {
1280  char *arg = NULL;
1281  const char *lang = switch_channel_get_variable(channel, "language");
1282  alt = file + 7;
1283  dup = switch_core_session_strdup(session, alt);
1284 
1285  if (dup) {
1286  if ((arg = strchr(dup, ':'))) {
1287  *arg++ = '\0';
1288  }
1289  if ((status = switch_ivr_phrase_macro(session, dup, arg, lang, args)) != SWITCH_STATUS_SUCCESS) {
1291  return status;
1292  }
1293  continue;
1294  } else {
1295  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
1296  continue;
1297  }
1298  } else if (!strncasecmp(file, "say:", 4)) {
1299  char *engine = NULL, *voice = NULL, *text = NULL;
1300  alt = file + 4;
1301  dup = switch_core_session_strdup(session, alt);
1302  engine = dup;
1303 
1304  if (!zstr(engine)) {
1305  if ((voice = strchr(engine, ':'))) {
1306  *voice++ = '\0';
1307  if (!zstr(voice) && (text = strchr(voice, ':'))) {
1308  *text++ = '\0';
1309  }
1310  }
1311  }
1312 
1313  if (!zstr(engine) && !zstr(voice) && !zstr(text)) {
1314  if ((status = switch_ivr_speak_text(session, engine, voice, text, args)) != SWITCH_STATUS_SUCCESS) {
1316  return status;
1317  }
1318  } else {
1319  text = engine;
1320  engine = (char *) switch_channel_get_variable(channel, "tts_engine");
1321  voice = (char *) switch_channel_get_variable(channel, "tts_voice");
1322  if (engine && text) {
1323  if ((status = switch_ivr_speak_text(session, engine, voice, text, args)) != SWITCH_STATUS_SUCCESS) {
1325  return status;
1326  }
1327  } else {
1328  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
1329  }
1330  }
1331  continue;
1332  }
1333 
1334  }
1335 
1336  if (!prefix) {
1337  prefix = SWITCH_GLOBAL_dirs.base_dir;
1338  }
1339 
1340  if (!strstr(file, SWITCH_URL_SEPARATOR)) {
1341  if (!switch_is_file_path(file)) {
1342  char *tfile = NULL;
1343  char *e;
1344 
1345  if (*file == '{') {
1346  tfile = switch_core_session_strdup(session, file);
1347 
1348  while (*file == '{') {
1349  if ((e = switch_find_end_paren(tfile, '{', '}'))) {
1350  *e = '\0';
1351  file = e + 1;
1352  while(*file == ' ') file++;
1353  } else {
1354  tfile = NULL;
1355  break;
1356  }
1357  }
1358  }
1359 
1360  file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "}" : "", prefix, SWITCH_PATH_SEPARATOR, file);
1361  }
1362  if ((ext = strrchr(file, '.'))) {
1363  ext++;
1364  } else {
1365  ext = read_impl.iananame;
1366  file = switch_core_session_sprintf(session, "%s.%s", file, ext);
1367  }
1368  }
1369 
1370  if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
1371  int maybe = atoi(prebuf);
1372  if (maybe > 0) {
1373  fh->prebuf = maybe;
1374  }
1375  }
1376 
1377 
1378  if (!fh->prefix) {
1379  fh->prefix = prefix;
1380  }
1381 
1383 
1384  if (switch_channel_test_flag(channel, CF_VIDEO)) {
1385  flags |= SWITCH_FILE_FLAG_VIDEO;
1386  //switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
1387  }
1388 
1389  if (switch_core_file_open(fh,
1390  file,
1391  read_impl.number_of_channels,
1392  read_impl.actual_samples_per_second, flags, NULL) != SWITCH_STATUS_SUCCESS) {
1394  status = SWITCH_STATUS_NOTFOUND;
1395  continue;
1396  }
1397 
1398  switch_channel_audio_sync(channel);
1400  switch_channel_set_private(channel, "__fh", fh);
1402 
1405  }
1406 
1407  if (!abuf) {
1408  buflen = write_frame.buflen = FILE_STARTSAMPLES * sizeof(*abuf) * fh->channels;
1409  switch_zmalloc(abuf, write_frame.buflen);
1410  write_frame.data = abuf;
1411  }
1412 
1413  if (sample_start > 0) {
1414  uint32_t pos = 0;
1415  switch_core_file_seek(fh, &pos, 0, SEEK_SET);
1416  switch_core_file_seek(fh, &pos, sample_start, SEEK_CUR);
1418  }
1419 
1421  //title = switch_core_session_strdup(session, p);
1422  switch_channel_set_variable(channel, "RECORD_TITLE", p);
1423  }
1424 
1426  //copyright = switch_core_session_strdup(session, p);
1427  switch_channel_set_variable(channel, "RECORD_COPYRIGHT", p);
1428  }
1429 
1431  //software = switch_core_session_strdup(session, p);
1432  switch_channel_set_variable(channel, "RECORD_SOFTWARE", p);
1433  }
1434 
1436  //artist = switch_core_session_strdup(session, p);
1437  switch_channel_set_variable(channel, "RECORD_ARTIST", p);
1438  }
1439 
1441  //comment = switch_core_session_strdup(session, p);
1442  switch_channel_set_variable(channel, "RECORD_COMMENT", p);
1443  }
1444 
1446  //date = switch_core_session_strdup(session, p);
1447  switch_channel_set_variable(channel, "RECORD_DATE", p);
1448  }
1449 
1450  interval = read_impl.microseconds_per_packet / 1000;
1451 
1452  if (!fh->audio_buffer) {
1455  }
1456 
1457  codec_name = "L16";
1458 
1459  if (!switch_core_codec_ready((&codec))) {
1460  if (switch_core_codec_init(&codec,
1461  codec_name,
1462  NULL,
1463  NULL,
1464  fh->samplerate,
1465  interval, read_impl.number_of_channels,
1468  SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n",
1469  codec_name, fh->samplerate, read_impl.number_of_channels, interval);
1470 
1471 
1472  } else {
1474  "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name,
1475  fh->samplerate, read_impl.number_of_channels, interval);
1477  switch_channel_set_private(channel, "__fh", NULL);
1479 
1481 
1483 
1485  status = SWITCH_STATUS_GENERR;
1486  continue;
1487  }
1488  }
1489 
1490  test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
1491 
1492  if (test_native) {
1493  write_frame.codec = switch_core_session_get_read_codec(session);
1494  samples = read_impl.samples_per_packet;
1495  framelen = read_impl.encoded_bytes_per_packet;
1496  channels = read_impl.number_of_channels;
1497  if (framelen == 0) {
1498  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s cannot play or record native files with variable length data\n", switch_channel_get_name(channel));
1499 
1501  switch_channel_set_private(channel, "__fh", NULL);
1503 
1506 
1508  status = SWITCH_STATUS_GENERR;
1509  continue;
1510 
1511  }
1512  } else {
1513  write_frame.codec = &codec;
1514  samples = codec.implementation->samples_per_packet;
1515  framelen = codec.implementation->decoded_bytes_per_packet;
1516  channels = codec.implementation->number_of_channels;
1517  }
1518 
1519  last_native = test_native;
1520 
1521  if (timer_name && !timer.samplecount) {
1522  uint32_t len;
1523 
1524  len = samples * 2 * channels;
1525  if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) {
1526  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n");
1527  switch_core_codec_destroy(&codec);
1529  switch_channel_set_private(channel, "__fh", NULL);
1531 
1533 
1536  status = SWITCH_STATUS_GENERR;
1537  continue;
1538  }
1539  switch_core_timer_sync(&timer); // Sync timer
1541  "Setup timer success %u bytes per %d ms! %d ch\n", len, interval, codec.implementation->number_of_channels);
1542  }
1543  write_frame.rate = fh->samplerate;
1544  write_frame.channels = fh->channels;
1545  if (timer_name) {
1546  /* start a thread to absorb incoming audio */
1547  switch_core_service_session(session);
1548  }
1549 
1550  ilen = samples * channels;
1551 
1553  switch_channel_event_set_data(channel, event);
1554  if (!strncasecmp(file, "local_stream:", 13)) {
1555  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "local_stream");
1556  }
1557  if (!strncasecmp(file, "tone_stream:", 12)) {
1558  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "tone_stream");
1559  }
1560  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file);
1561  if (fh->params) {
1562  switch_event_merge(event, fh->params);
1563  }
1564  switch_event_fire(&event);
1565  }
1566 
1567  for (;;) {
1568  int do_speed = 1;
1569  int last_speed = -1;
1570  int f;
1571 
1572  if (!switch_channel_ready(channel)) {
1573  status = SWITCH_STATUS_FALSE;
1574  break;
1575  }
1576 
1577  if ((f = switch_channel_test_flag(channel, CF_BREAK))) {
1579  if (f == 2) {
1580  done = 1;
1581  }
1582  status = SWITCH_STATUS_BREAK;
1583  break;
1584  }
1585 
1586  switch_ivr_parse_all_events(session);
1587 
1588  if (args) {
1589  /*
1590  dtmf handler function you can hook up to be executed when a digit is dialed during playback
1591  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
1592  */
1593  if (switch_channel_has_dtmf(channel)) {
1594  switch_channel_dequeue_dtmf(channel, &dtmf);
1595 
1596  if (!args->input_callback && !args->buf && !args->dmachine) {
1597  status = SWITCH_STATUS_BREAK;
1598  done = 1;
1599  break;
1600  }
1601 
1602 
1603  if (args->dmachine) {
1604  char ds[2] = {dtmf.digit, '\0'};
1605  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
1606  break;
1607  }
1608  }
1609 
1610  if (args->input_callback) {
1611  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
1612  } else if (args->buf) {
1613  *((char *) args->buf) = dtmf.digit;
1614  status = SWITCH_STATUS_BREAK;
1615  }
1616  }
1617 
1618  if (args->input_callback) {
1619  switch_event_t *event;
1620 
1622  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
1623  if (ostatus != SWITCH_STATUS_SUCCESS) {
1624  status = ostatus;
1625  }
1626 
1627  switch_event_destroy(&event);
1628  }
1629  }
1630 
1631  if (status != SWITCH_STATUS_SUCCESS) {
1632  done = 1;
1633  break;
1634  }
1635  }
1636 
1637  buflen = FILE_STARTSAMPLES * sizeof(*abuf) * fh->cur_channels ? fh->cur_channels : fh->channels;
1638 
1639  if (buflen > write_frame.buflen) {
1640  abuf = realloc(abuf, buflen);
1641  write_frame.data = abuf;
1642  write_frame.buflen = buflen;
1643  }
1644 
1646  if (framelen > FILE_STARTSAMPLES) {
1647  framelen = FILE_STARTSAMPLES;
1648  }
1649  memset(abuf, 255, framelen);
1650  olen = ilen;
1651  do_speed = 0;
1652  } else if (fh->sp_audio_buffer && (eof || (switch_buffer_inuse(fh->sp_audio_buffer) > (switch_size_t) (framelen)))) {
1653  if (!(bread = switch_buffer_read(fh->sp_audio_buffer, abuf, framelen))) {
1654  if (eof) {
1655  continue;
1656  } else {
1657  break;
1658  }
1659  }
1660 
1661  if (bread < framelen) {
1662  memset(abuf + bread, 255, framelen - bread);
1663  }
1664 
1665  olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
1666  do_speed = 0;
1667  } else if (fh->audio_buffer && (eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (framelen)))) {
1668  if (!(bread = switch_buffer_read(fh->audio_buffer, abuf, framelen))) {
1669  if (eof) {
1670  break;
1671  } else {
1672  continue;
1673  }
1674  }
1675 
1676  fh->offset_pos += (uint32_t)(switch_test_flag(fh, SWITCH_FILE_NATIVE) ? bread : bread / 2);
1677 
1678  if (bread < framelen) {
1679  memset(abuf + bread, 255, framelen - bread);
1680  }
1681 
1682  olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
1683  } else {
1684  switch_status_t rstatus;
1685 
1686  if (eof) {
1687  break;
1688  }
1689  olen = FILE_STARTSAMPLES;
1691  olen /= 2;
1692  }
1694 
1695  if ((rstatus = switch_core_file_read(fh, abuf, &olen)) == SWITCH_STATUS_BREAK) {
1696  continue;
1697  }
1698 
1699  if (rstatus != SWITCH_STATUS_SUCCESS) {
1700  eof++;
1701  continue;
1702  }
1703 
1704  test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
1705 
1706  if (test_native != last_native) {
1707  if (test_native) {
1708  write_frame.codec = switch_core_session_get_read_codec(session);
1709  samples = read_impl.samples_per_packet;
1710  framelen = read_impl.encoded_bytes_per_packet;
1711  if (framelen == 0) {
1712  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s cannot play or record native files with variable length data\n", switch_channel_get_name(channel));
1713  eof++;
1714  continue;
1715  }
1716  } else {
1717  write_frame.codec = &codec;
1718  samples = codec.implementation->samples_per_packet;
1719  framelen = codec.implementation->decoded_bytes_per_packet;
1720  }
1722  }
1723 
1724  last_native = test_native;
1725 
1726  switch_buffer_write(fh->audio_buffer, abuf, switch_test_flag(fh, SWITCH_FILE_NATIVE) ? olen : olen * 2 * fh->channels);
1727  olen = switch_buffer_read(fh->audio_buffer, abuf, framelen);
1728  fh->offset_pos += (uint32_t)(olen / 2);
1729 
1731  olen /= 2;
1732  }
1733 
1734  }
1735 
1736  if (done || olen <= 0) {
1737  break;
1738  }
1739 
1741  if (fh->speed > 2) {
1742  fh->speed = 2;
1743  } else if (fh->speed < -2) {
1744  fh->speed = -2;
1745  }
1746  }
1747 
1748  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
1750  }
1751 
1753  /* file position has changed flush the buffer */
1756  }
1757 
1758 
1759  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->speed && do_speed) {
1760  float factor = 0.25f * abs(fh->speed);
1761  switch_size_t newlen, supplement, step;
1762  short *bp = write_frame.data;
1763  switch_size_t wrote = 0;
1764 
1765  supplement = (int) (factor * olen);
1766  if (!supplement) {
1767  supplement = 1;
1768  }
1769  newlen = (fh->speed > 0) ? olen - supplement : olen + supplement;
1770 
1771  step = (fh->speed > 0) ? (newlen / supplement) : (olen / supplement);
1772 
1773  if (!fh->sp_audio_buffer) {
1774  switch_buffer_create_dynamic(&fh->sp_audio_buffer, 1024, 1024, 0);
1775  }
1776 
1777  while ((wrote + step) < newlen) {
1778  switch_buffer_write(fh->sp_audio_buffer, bp, step * 2);
1779  wrote += step;
1780  bp += step;
1781  if (fh->speed > 0) {
1782  bp++;
1783  } else {
1784  float f;
1785  short s;
1786  f = (float) (*bp + *(bp + 1) + *(bp - 1));
1787  f /= 3;
1788  s = (short) f;
1790  wrote++;
1791  }
1792  }
1793  if (wrote < newlen) {
1794  switch_size_t r = newlen - wrote;
1795  switch_buffer_write(fh->sp_audio_buffer, bp, r * 2);
1796  wrote += r;
1797  }
1798  last_speed = fh->speed;
1799  continue;
1800  }
1801 
1802  if (olen < llen) {
1803  uint8_t *dp = (uint8_t *) write_frame.data;
1804  memset(dp + (int) olen, 255, (int) (llen - olen));
1805  olen = llen;
1806  }
1807 
1808  if (!more_data) {
1809  if (timer_name) {
1811  break;
1812  }
1813  } else { /* time off the channel (if you must) */
1814  switch_frame_t *read_frame;
1815  switch_status_t tstatus;
1816 
1817  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
1819  switch_yield(10000);
1820  }
1821 
1822  tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_SINGLE_READ, 0);
1823 
1824 
1825  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
1826  break;
1827  }
1828 
1829  if (args && args->dmachine) {
1830  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1831  break;
1832  }
1833  }
1834 
1835  if (args && (args->read_frame_callback)) {
1836  int ok = 1;
1838  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
1839  ok = 0;
1840  }
1842  if (!ok) {
1843  break;
1844  }
1845  }
1846  }
1847  }
1848 
1849  more_data = 0;
1850  write_frame.samples = (uint32_t) olen;
1851 
1853  write_frame.datalen = (uint32_t) olen;
1854  } else {
1855  write_frame.datalen = write_frame.samples * 2;
1856  }
1857 
1858  llen = olen;
1859 
1860  if (timer_name) {
1861  write_frame.timestamp = timer.samplecount;
1862  }
1863 #ifndef WIN32
1864 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
1865  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && l16) {
1866  switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);
1867  }
1868 #endif
1869 #endif
1870  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->vol) {
1871  switch_change_sln_volume(write_frame.data, write_frame.datalen / 2, fh->vol);
1872  }
1873 
1874  /* write silence while dmachine is in reading state */
1875  if (args && args->dmachine && switch_ivr_dmachine_is_parsing(args->dmachine)) {
1876  memset(write_frame.data, 0, write_frame.datalen);
1877  }
1878 
1879  status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
1880 
1881  if (timeout_samples) {
1882  timeout_samples -= write_frame.samples;
1883  if (timeout_samples <= 0) {
1884  timeout_samples = 0;
1885  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "timeout reached playing file\n");
1886  if (timeout_as_success) {
1887  status = SWITCH_STATUS_SUCCESS;
1888  } else {
1889  status = SWITCH_STATUS_TIMEOUT;
1890  }
1891  break;
1892  }
1893  }
1894 
1895 
1896  if (status == SWITCH_STATUS_MORE_DATA) {
1897  status = SWITCH_STATUS_SUCCESS;
1898  more_data = 1;
1899  continue;
1900  } else if (status != SWITCH_STATUS_SUCCESS) {
1901  done = 1;
1902  break;
1903  }
1904 
1905  if (done) {
1906  break;
1907  }
1908  }
1909 
1910  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done playing file %s\n", file);
1911  switch_channel_set_variable_printf(channel, "playback_last_offset_pos", "%d", fh->offset_pos);
1912 
1913  if (read_impl.samples_per_second) {
1914  switch_channel_set_variable_printf(channel, "playback_seconds", "%d", fh->samples_in / fh->native_rate);
1915  switch_channel_set_variable_printf(channel, "playback_ms", "%d", fh->samples_in / (fh->native_rate / 1000));
1916  }
1917  switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_in);
1918 
1920  switch_channel_event_set_data(channel, event);
1921  if (!strncasecmp(file, "local_stream:", 13)) {
1922  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "local_stream");
1923  }
1924  if (!strncasecmp(file, "tone_stream:", 12)) {
1925  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "tone_stream");
1926  }
1927  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file);
1928  if (status == SWITCH_STATUS_BREAK) {
1929  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "break");
1930  } else {
1931  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "done");
1932  }
1933  if (fh->params) {
1934  switch_event_merge(event, fh->params);
1935  }
1936  switch_event_fire(&event);
1937  }
1938 
1940  switch_channel_set_private(channel, "__fh", NULL);
1942 
1945 
1946  if (fh->audio_buffer) {
1948  }
1949 
1950  if (fh->sp_audio_buffer) {
1952  }
1953  }
1954 
1955  if (switch_core_codec_ready((&codec))) {
1956  switch_core_codec_destroy(&codec);
1957  }
1958 
1959  if (timer.samplecount) {
1960  /* End the audio absorbing thread */
1962  switch_core_timer_destroy(&timer);
1963  }
1964 
1965  switch_safe_free(abuf);
1966 
1968 
1970 
1971  return status;
1972 }
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
void switch_core_thread_session_end(_In_ switch_core_session_t *session)
Signal a thread using a thread session to terminate.
switch_status_t switch_core_session_io_write_lock(switch_core_session_t *session)
char * switch_core_session_sprintf(_In_ switch_core_session_t *session, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the session ...
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_core_timer_init(switch_timer_t *timer, const char *timer_name, int interval, int samples, switch_memory_pool_t *pool)
Request a timer handle using given time module.
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
switch_size_t switch_buffer_read(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available. Remove read data fr...
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
char * switch_find_end_paren(const char *s, char open, char close)
Definition: switch_utils.c:661
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
#define switch_core_file_open(_fh, _file_path, _channels, _rate, _flags, _pool)
Open a media file using file format modules.
Definition: switch_core.h:1865
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
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.
Definition: switch_ivr.c:127
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
switch_bool_t
Definition: switch_types.h:405
uint32_t timestamp
Definition: switch_frame.h:69
#define SWITCH_URL_SEPARATOR
Definition: switch_types.h:124
switch_memory_pool_t * pool
switch_status_t switch_core_file_get_string(_In_ switch_file_handle_t *fh, switch_audio_col_t col, const char **string)
get metadata of the desired string
Representation of an event.
Definition: switch_event.h:80
switch_status_t switch_core_file_close(_In_ switch_file_handle_t *fh)
Close an open file handle.
#define switch_channel_ready(_channel)
#define arg_recursion_check_stop(_args)
switch_status_t switch_core_media_set_video_file(switch_core_session_t *session, switch_file_handle_t *fh, switch_rw_t rw)
#define switch_channel_media_ready(_channel)
switch_status_t switch_core_file_seek(_In_ switch_file_handle_t *fh, unsigned int *cur_pos, int64_t samples, int whence)
Seek a position in a file.
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
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_core_file_read(_In_ switch_file_handle_t *fh, void *data, switch_size_t *len)
Read media from a file handle.
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
pack cur
Abstract handler to a timer module.
switch_size_t switch_buffer_write(_In_ switch_buffer_t *buffer, _In_bytecount_(datalen) const void *data, _In_ switch_size_t datalen)
Write data into a switch_buffer_t up to the length of datalen.
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
#define zstr(x)
Definition: switch_utils.h:281
switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
void switch_change_sln_volume(int16_t *data, uint32_t samples, int32_t vol)
Change the volume of a signed linear audio frame.
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_session_io_rwunlock(switch_core_session_t *session)
switch_bool_t switch_ivr_dmachine_is_parsing(switch_ivr_dmachine_t *dmachine)
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:122
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:59
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
#define switch_channel_audio_sync(_c)
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
uint32_t datalen
Definition: switch_frame.h:57
void switch_event_merge(switch_event_t *event, switch_event_t *tomerge)
uint32_t rate
Definition: switch_frame.h:63
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_zmalloc(ptr, len)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_input_callback_function_t input_callback
void switch_buffer_zero(_In_ switch_buffer_t *buffer)
Remove all data from the buffer.
An abstraction of a data frame.
Definition: switch_frame.h:43
uintptr_t switch_size_t
#define arg_recursion_check_start(_args)
#define switch_set_flag_locked(obj, flag)
Set a flag on an arbitrary object while locked.
Definition: switch_utils.h:638
void switch_swap_linear(int16_t *buf, int len)
Perform a byteswap on a buffer of 16 bit samples.
switch_byte_t switch_byte_t uint32_t buflen
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
#define switch_core_service_session(_s)
Definition: switch_core.h:1186
switch_status_t switch_core_timer_destroy(switch_timer_t *timer)
Destroy an allocated timer.
switch_buffer_t * audio_buffer
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:60
switch_read_frame_callback_function_t read_frame_callback
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
switch_status_t switch_core_timer_next(switch_timer_t *timer)
Wait for one cycle on an existing timer.
#define switch_clear_flag_locked(obj, flag)
Clear a flag on an arbitrary object.
Definition: switch_utils.h:648
#define FILE_BUFSIZE
switch_status_t
Common return values.
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_buffer_t * sp_audio_buffer
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
#define FILE_BLOCKSIZE
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
static switch_bool_t switch_is_file_path(const char *file)
uint32_t samples
Definition: switch_frame.h:61
uint32_t channels
Definition: switch_frame.h:65
switch_bool_t switch_core_file_has_video(switch_file_handle_t *fh, switch_bool_t CHECK_OPEN)
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
#define FILE_STARTSAMPLES
struct apr_pool_t switch_memory_pool_t
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
static switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_ivr_phrase_macro(session, macro_name, data, lang, args)
Definition: switch_ivr.h:903
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_assert(expr)
#define switch_channel_set_variable(_channel, _var, _val)
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
memset(buf, 0, buflen)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_ivr_dmachine_t * dmachine
switch_status_t switch_core_timer_sync(switch_timer_t *timer)
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:801
switch_status_t switch_ivr_process_indications ( switch_core_session_t session,
switch_core_session_message_t message 
)

Definition at line 772 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().

773 {
776 
777  switch(message->message_id) {
781  }
782  break;
786  }
787  break;
791  }
792  break;
793  default:
794  status = SWITCH_STATUS_FALSE;
795  break;
796  }
797 
798  return status;
799 }
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
#define switch_channel_answer(channel)
Answer a channel (initiate/acknowledge a successful connection)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_channel_ring_ready(channel)
Send Ringing message to a channel.
switch_status_t
Common return values.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
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
sessionthe session to record from
fhfile handle to use
filethe path to the file
argsarguements to pass for callbacks etc
limitmax 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
sessionthe session to record
filethe path to the file
limitstop recording after this amount of time (in ms, 0 = never stop)
fhfile handle to use (NULL for builtin one)
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2345 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, switch_directories::base_dir, CF_VIDEO, switch_codec_implementation::decoded_bytes_per_packet, record_helper::fh, record_helper::file, record_helper::final_timeout_ms, eavesdrop_pvt::flags, switch_core_session_message::from, record_helper::hangup_on_error, switch_codec_implementation::iananame, record_helper::in_fh, record_helper::initial_timeout_ms, switch_core_session_message::message_id, record_helper::min_sec, record_helper::native, switch_codec_implementation::number_of_channels, record_helper::out_fh, record_helper::packet_len, switch_file_handle::pre_buffer_datalen, eavesdrop_pvt::read_impl, record_callback(), record_helper::silence_threshold, SMBF_ANSWER_REQ, SMBF_BRIDGE_REQ, SMBF_READ_PING, SMBF_READ_STREAM, SMBF_READ_VIDEO_PING, SMBF_READ_VIDEO_STREAM, SMBF_STEREO, SMBF_STEREO_SWAP, SMBF_TAP_NATIVE_READ, SMBF_TAP_NATIVE_WRITE, SMBF_WRITE_STREAM, SMBF_WRITE_VIDEO_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_channel_test_flag(), switch_core_file_close(), switch_core_file_has_video(), 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_receive_message, 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_VIDEO, SWITCH_FILE_FLAG_WRITE, SWITCH_FILE_NATIVE, 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_MESSAGE_INDICATE_VIDEO_REFRESH_REQ, SWITCH_PATH_SEPARATOR, switch_set_flag, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, switch_str_nil, SWITCH_TRUE, switch_true(), and SWITCH_URL_SEPARATOR.

Referenced by switch_core_media_bug_transfer_recordings().

2346 {
2348  const char *p;
2349  const char *vval;
2351  switch_status_t status;
2352  time_t to = 0;
2354  uint8_t channels;
2355  switch_codec_implementation_t read_impl = { 0 };
2356  struct record_helper *rh = NULL;
2359  char *file_path = NULL;
2360  char *ext;
2361  char *in_file = NULL, *out_file = NULL;
2362 
2363  if ((p = switch_channel_get_variable(channel, "RECORD_HANGUP_ON_ERROR"))) {
2364  hangup_on_error = switch_true(p);
2365  }
2366 
2367  if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
2368  return SWITCH_STATUS_FALSE;
2369  }
2370 
2371  if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
2372  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not record session. Media not enabled on channel\n");
2373  return SWITCH_STATUS_FALSE;
2374  }
2375 
2376  switch_core_session_get_read_impl(session, &read_impl);
2377  channels = read_impl.number_of_channels;
2378 
2379  if ((bug = switch_channel_get_private(channel, file))) {
2380  if (switch_true(switch_channel_get_variable(channel, "RECORD_TOGGLE_ON_REPEAT"))) {
2381  return switch_ivr_stop_record_session(session, file);
2382  }
2383 
2384  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Already recording [%s]\n", file);
2385  return SWITCH_STATUS_SUCCESS;
2386  }
2387 
2388 
2389  if ((p = switch_channel_get_variable(channel, "RECORD_CHECK_BRIDGE")) && switch_true(p)) {
2390  switch_core_session_t *other_session;
2391  int exist = 0;
2393 
2394  if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
2395  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
2396  if ((bug = switch_channel_get_private(other_channel, file))) {
2397  if (switch_true(switch_channel_get_variable(other_channel, "RECORD_TOGGLE_ON_REPEAT"))) {
2398  rstatus = switch_ivr_stop_record_session(other_session, file);
2399  } else {
2400  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(other_session), SWITCH_LOG_WARNING, "Already recording [%s]\n", file);
2401  }
2402  exist = 1;
2403  }
2404  switch_core_session_rwunlock(other_session);
2405  }
2406 
2407  if (exist) {
2408  return rstatus;
2409  }
2410  }
2411 
2412  if (!fh) {
2413  if (!(fh = switch_core_session_alloc(session, sizeof(*fh)))) {
2414  return SWITCH_STATUS_MEMERR;
2415  }
2416  }
2417 
2418  if ((p = switch_channel_get_variable(channel, "RECORD_WRITE_ONLY")) && switch_true(p)) {
2419  flags &= ~SMBF_READ_STREAM;
2420  flags |= SMBF_WRITE_STREAM;
2421  }
2422 
2423  if ((p = switch_channel_get_variable(channel, "RECORD_READ_ONLY")) && switch_true(p)) {
2424  flags &= ~SMBF_WRITE_STREAM;
2425  flags |= SMBF_READ_STREAM;
2426  }
2427 
2428  if (channels == 1) { /* if leg is already stereo this feature is not available */
2429  if ((p = switch_channel_get_variable(channel, "RECORD_STEREO")) && switch_true(p)) {
2430  flags |= SMBF_STEREO;
2431  flags &= ~SMBF_STEREO_SWAP;
2432  channels = 2;
2433  }
2434 
2435  if ((p = switch_channel_get_variable(channel, "RECORD_STEREO_SWAP")) && switch_true(p)) {
2436  flags |= SMBF_STEREO;
2437  flags |= SMBF_STEREO_SWAP;
2438  channels = 2;
2439  }
2440  }
2441 
2442  if ((p = switch_channel_get_variable(channel, "RECORD_ANSWER_REQ")) && switch_true(p)) {
2443  flags |= SMBF_ANSWER_REQ;
2444  }
2445 
2446  if ((p = switch_channel_get_variable(channel, "RECORD_BRIDGE_REQ")) && switch_true(p)) {
2447  flags |= SMBF_BRIDGE_REQ;
2448  }
2449 
2450  if ((p = switch_channel_get_variable(channel, "RECORD_APPEND")) && switch_true(p)) {
2451  file_flags |= SWITCH_FILE_WRITE_APPEND;
2452  }
2453 
2454 
2455  fh->samplerate = 0;
2456  if ((vval = switch_channel_get_variable(channel, "record_sample_rate"))) {
2457  int tmp = 0;
2458 
2459  tmp = atoi(vval);
2460 
2461  if (switch_is_valid_rate(tmp)) {
2462  fh->samplerate = tmp;
2463  }
2464  }
2465 
2466  if (!fh->samplerate) {
2467  fh->samplerate = read_impl.actual_samples_per_second;
2468  }
2469 
2470  fh->channels = channels;
2471 
2472  if ((vval = switch_channel_get_variable(channel, "enable_file_write_buffering"))) {
2473  int tmp = atoi(vval);
2474 
2475  if (tmp > 0) {
2476  fh->pre_buffer_datalen = tmp;
2477  } else if (switch_true(vval)) {
2479  }
2480 
2481  } else {
2483  }
2484 
2485 
2486  if (!switch_is_file_path(file)) {
2487  char *tfile = NULL;
2488  char *e;
2489  const char *prefix;
2490 
2491  prefix = switch_channel_get_variable(channel, "sound_prefix");
2492 
2493  if (!prefix) {
2494  prefix = SWITCH_GLOBAL_dirs.base_dir;
2495  }
2496 
2497  if (*file == '[') {
2498  tfile = switch_core_session_strdup(session, file);
2499  if ((e = switch_find_end_paren(tfile, '[', ']'))) {
2500  *e = '\0';
2501  file = e + 1;
2502  } else {
2503  tfile = NULL;
2504  }
2505  } else {
2506  file_path = switch_core_session_sprintf(session, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, file);
2507  }
2508 
2509  file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
2510  } else {
2511  file_path = switch_core_session_strdup(session, file);
2512  }
2513 
2514  if (file_path && !strstr(file_path, SWITCH_URL_SEPARATOR)) {
2515  char *p;
2516  char *path = switch_core_session_strdup(session, file_path);
2517 
2518  if ((p = strrchr(path, *SWITCH_PATH_SEPARATOR))) {
2519  *p = '\0';
2520 
2521  if (*path == '{') {
2522  path = switch_find_end_paren(path, '{', '}') + 1;
2523  }
2524 
2526  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error creating %s\n", path);
2527  return SWITCH_STATUS_GENERR;
2528  }
2529 
2530  } else {
2531  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error finding the folder path section in '%s'\n", path);
2532  path = NULL;
2533  }
2534  }
2535 
2536  rh = switch_core_session_alloc(session, sizeof(*rh));
2537 
2538  if ((ext = strrchr(file, '.'))) {
2539  ext++;
2540 
2541  if (switch_channel_test_flag(channel, CF_VIDEO)) {
2542  file_flags |= SWITCH_FILE_FLAG_VIDEO;
2543  }
2544 
2545  if (switch_core_file_open(fh, file, channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
2546  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", file);
2547  if (hangup_on_error) {
2550  }
2551  return SWITCH_STATUS_GENERR;
2552  }
2553 
2555  //switch_core_media_set_video_file(session, fh, SWITCH_RW_READ);
2556  //switch_channel_set_flag_recursive(session->channel, CF_VIDEO_DECODED_READ);
2557 
2558  if ((vval = switch_channel_get_variable(channel, "record_concat_video")) && switch_true(vval)) {
2559  flags |= SMBF_READ_VIDEO_STREAM;
2560  flags |= SMBF_WRITE_VIDEO_STREAM;
2561  } else {
2562  flags |= SMBF_READ_VIDEO_PING;
2563  }
2564  } else {
2565  flags &= ~SMBF_READ_VIDEO_PING;
2566  flags &= ~SMBF_READ_VIDEO_STREAM;
2567  flags &= ~SMBF_WRITE_VIDEO_STREAM;
2568  }
2569 
2570  } else {
2571  int tflags = 0;
2572 
2573  ext = read_impl.iananame;
2574 
2575  in_file = switch_core_session_sprintf(session, "%s-in.%s", file, ext);
2576  out_file = switch_core_session_sprintf(session, "%s-out.%s", file, ext);
2578  channels = 1;
2581 
2582  if (switch_core_file_open(&rh->in_fh, in_file, channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
2583  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", in_file);
2584  if (hangup_on_error) {
2587  }
2588  return SWITCH_STATUS_GENERR;
2589  }
2590 
2591  if (switch_core_file_open(&rh->out_fh, out_file, channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
2592  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", out_file);
2594  if (hangup_on_error) {
2597  }
2598  return SWITCH_STATUS_GENERR;
2599  }
2600 
2601  rh->native = 1;
2602  fh = NULL;
2603 
2604  if ((flags & SMBF_WRITE_STREAM)) {
2605  tflags |= SMBF_TAP_NATIVE_WRITE;
2606  }
2607 
2608  if ((flags & SMBF_READ_STREAM)) {
2609  tflags |= SMBF_TAP_NATIVE_READ;
2610  }
2611 
2612  flags = tflags;
2613  }
2614 
2615 
2616 
2617  if ((p = switch_channel_get_variable(channel, "RECORD_TITLE"))) {
2618  vval = (const char *) switch_core_session_strdup(session, p);
2620  switch_channel_set_variable(channel, "RECORD_TITLE", NULL);
2621  }
2622 
2623  if ((p = switch_channel_get_variable(channel, "RECORD_COPYRIGHT"))) {
2624  vval = (const char *) switch_core_session_strdup(session, p);
2626  switch_channel_set_variable(channel, "RECORD_COPYRIGHT", NULL);
2627  }
2628 
2629  if ((p = switch_channel_get_variable(channel, "RECORD_SOFTWARE"))) {
2630  vval = (const char *) switch_core_session_strdup(session, p);
2632  switch_channel_set_variable(channel, "RECORD_SOFTWARE", NULL);
2633  }
2634 
2635  if ((p = switch_channel_get_variable(channel, "RECORD_ARTIST"))) {
2636  vval = (const char *) switch_core_session_strdup(session, p);
2638  switch_channel_set_variable(channel, "RECORD_ARTIST", NULL);
2639  }
2640 
2641  if ((p = switch_channel_get_variable(channel, "RECORD_COMMENT"))) {
2642  vval = (const char *) switch_core_session_strdup(session, p);
2644  switch_channel_set_variable(channel, "RECORD_COMMENT", NULL);
2645  }
2646 
2647  if ((p = switch_channel_get_variable(channel, "RECORD_DATE"))) {
2648  vval = (const char *) switch_core_session_strdup(session, p);
2650  switch_channel_set_variable(channel, "RECORD_DATE", NULL);
2651  }
2652 
2653  if (limit) {
2654  to = switch_epoch_time_now(NULL) + limit;
2655  }
2656 
2657  rh->fh = fh;
2658  rh->file = switch_core_session_strdup(session, file);
2659  rh->packet_len = read_impl.decoded_bytes_per_packet;
2660 
2661  if (file_flags & SWITCH_FILE_WRITE_APPEND) {
2662  rh->min_sec = 3;
2663  }
2664 
2665  if ((p = switch_channel_get_variable(channel, "RECORD_MIN_SEC"))) {
2666  int tmp = atoi(p);
2667  if (tmp >= 0) {
2668  rh->min_sec = tmp;
2669  }
2670  }
2671 
2672  if ((p = switch_channel_get_variable(channel, "RECORD_INITIAL_TIMEOUT_MS"))) {
2673  int tmp = atoi(p);
2674  if (tmp >= 0) {
2675  rh->initial_timeout_ms = tmp;
2676  rh->silence_threshold = 200;
2677  }
2678  }
2679 
2680  if ((p = switch_channel_get_variable(channel, "RECORD_FINAL_TIMEOUT_MS"))) {
2681  int tmp = atoi(p);
2682  if (tmp >= 0) {
2683  rh->final_timeout_ms = tmp;
2684  rh->silence_threshold = 200;
2685  }
2686  }
2687 
2688  if ((p = switch_channel_get_variable(channel, "RECORD_SILENCE_THRESHOLD"))) {
2689  int tmp = atoi(p);
2690  if (tmp >= 0) {
2691  rh->silence_threshold = tmp;
2692  }
2693  }
2694 
2696 
2697  if ((status = switch_core_media_bug_add(session, "session_record", file,
2698  record_callback, rh, to, flags, &bug)) != SWITCH_STATUS_SUCCESS) {
2699  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error adding media bug for file %s\n", file);
2700  if (rh->native) {
2703  } else {
2705  }
2706  return status;
2707  }
2708 
2709  if ((p = switch_channel_get_variable(channel, "RECORD_PRE_BUFFER_FRAMES"))) {
2710  int tmp = atoi(p);
2711 
2712  if (tmp > 0) {
2714  }
2715  } else {
2717  }
2718 
2719  switch_channel_set_private(channel, file, bug);
2720 
2721  if (switch_channel_test_flag(channel, CF_VIDEO)) {
2722  switch_core_session_message_t msg = { 0 };
2723 
2724  msg.from = __FILE__;
2726 
2727  switch_core_session_receive_message(session, &msg);
2728  }
2729 
2730  return SWITCH_STATUS_SUCCESS;
2731 }
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
char * switch_core_session_sprintf(_In_ switch_core_session_t *session, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the session ...
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
char * switch_find_end_paren(const char *s, char open, char close)
Definition: switch_utils.c:661
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
#define switch_core_file_open(_fh, _file_path, _channels, _rate, _flags, _pool)
Open a media file using file format modules.
Definition: switch_core.h:1865
switch_status_t switch_ivr_stop_record_session(switch_core_session_t *session, const char *file)
Stop Recording a session.
switch_bool_t
Definition: switch_types.h:405
#define SWITCH_URL_SEPARATOR
Definition: switch_types.h:124
switch_status_t switch_core_file_set_string(_In_ switch_file_handle_t *fh, switch_audio_col_t col, const char *string)
Set metadata to the desired string.
switch_status_t switch_core_media_bug_set_pre_buffer_framecount(switch_media_bug_t *bug, uint32_t framecount)
switch_status_t switch_core_file_close(_In_ switch_file_handle_t *fh)
Close an open file handle.
switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session, _In_ const char *function, _In_ const char *target, _In_ switch_media_bug_callback_t callback, _In_opt_ void *user_data, _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug)
Add a media bug to the session.
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session)
Retrieve the read codec from a given session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:122
#define switch_channel_get_variable(_c, _v)
switch_file_handle_t in_fh
#define switch_core_session_get_partner(_session, _partner)
Definition: switch_core.h:1002
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:60
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
#define SWITCH_DEFAULT_DIR_PERMS
Definition: switch_types.h:118
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_status_t switch_dir_make_recursive(const char *path, switch_fileperms_t perm, switch_memory_pool_t *pool)
Definition: switch_apr.c:528
static switch_bool_t switch_is_file_path(const char *file)
switch_bool_t switch_core_file_has_video(switch_file_handle_t *fh, switch_bool_t CHECK_OPEN)
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:321
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
switch_bool_t hangup_on_error
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_is_valid_rate(_tmp)
Definition: switch_utils.h:344
uint32_t switch_media_bug_flag_t
switch_file_handle_t out_fh
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_file_handle_t * fh
#define switch_channel_set_variable(_channel, _var, _val)
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
#define switch_channel_media_up(_channel)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
#define SWITCH_DEFAULT_FILE_BUFFER_LEN
Definition: switch_types.h:229
static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
switch_media_bug_t * bug
switch_status_t switch_ivr_resume_detect_speech ( switch_core_session_t session)

Resume background Speech detection on a session.

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

Definition at line 4602 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().

4603 {
4606 
4607  if (sth) {
4608  switch_core_asr_resume(sth->ah);
4609  return SWITCH_STATUS_SUCCESS;
4610  }
4611  return SWITCH_STATUS_FALSE;
4612 }
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_status_t switch_core_asr_resume(switch_asr_handle_t *ah)
Resume detection on an asr handle.
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
runtimewhen (in epoch time) to run the broadcast
uuidthe uuid of the session to broadcast on
paththe path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>"
flagsflags 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 4944 of file switch_ivr_async.c.

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

4945 {
4946  struct broadcast_helper *helper;
4947  size_t len = sizeof(*helper) + strlen(path) + 1;
4948  char *cur = NULL;
4949 
4950  switch_zmalloc(cur, len);
4951  helper = (struct broadcast_helper *) cur;
4952 
4953  cur += sizeof(*helper);
4954  switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
4955  helper->flags = flags;
4956 
4957  switch_copy_string(cur, path, len - sizeof(helper));
4958  helper->path = cur;
4959 
4960  return switch_scheduler_add_task(runtime, sch_broadcast_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
4961 }
#define __SWITCH_FUNC__
switch_media_flag_t flags
pack cur
struct switch_runtime runtime
Definition: switch_core.c:64
uint32_t switch_scheduler_add_task(time_t task_runtime, switch_scheduler_func_t func, const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags)
Schedule a task in the future.
#define switch_zmalloc(ptr, len)
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1]
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
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
runtimethe time (int epoch seconds) to transfer the call
uuidthe uuid of the session to hangup
causethe hanup cause code
bleghangup up the B-Leg if possible
Returns
the id of the task

Definition at line 4847 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.

4848 {
4849  struct hangup_helper *helper;
4850  size_t len = sizeof(*helper);
4851 
4852  switch_zmalloc(helper, len);
4853 
4854  switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
4855  helper->cause = cause;
4856  helper->bleg = bleg;
4857 
4858  return switch_scheduler_add_task(runtime, sch_hangup_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
4859 }
#define __SWITCH_FUNC__
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1]
switch_bool_t bleg
struct switch_runtime runtime
Definition: switch_core.c:64
uint32_t switch_scheduler_add_task(time_t task_runtime, switch_scheduler_func_t func, const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags)
Schedule a task in the future.
switch_call_cause_t cause
#define switch_zmalloc(ptr, len)
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
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
runtimethe time (int epoch seconds) to transfer the call
uuidthe uuid of the session to transfer
extensionthe new extension
dialplanthe new dialplan (OPTIONAL, may be NULL)
contextthe new context (OPTIONAL, may be NULL)
Returns
the id of the task

Definition at line 4884 of file switch_ivr_async.c.

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

4885 {
4886  struct transfer_helper *helper;
4887  size_t len = sizeof(*helper);
4888  char *cur = NULL;
4889 
4890  if (extension) {
4891  len += strlen(extension) + 1;
4892  }
4893 
4894  if (dialplan) {
4895  len += strlen(dialplan) + 1;
4896  }
4897 
4898  if (context) {
4899  len += strlen(context) + 1;
4900  }
4901 
4902  switch_zmalloc(cur, len);
4903  helper = (struct transfer_helper *) cur;
4904 
4905  switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
4906 
4907  cur += sizeof(*helper);
4908 
4909  if (extension) {
4910  switch_copy_string(cur, extension, strlen(extension) + 1);
4911  helper->extension = cur;
4912  cur += strlen(helper->extension) + 1;
4913  }
4914 
4915  if (dialplan) {
4916  switch_copy_string(cur, dialplan, strlen(dialplan) + 1);
4917  helper->dialplan = cur;
4918  cur += strlen(helper->dialplan) + 1;
4919  }
4920 
4921  if (context) {
4922  switch_copy_string(cur, context, strlen(context) + 1);
4923  helper->context = cur;
4924  }
4925 
4926  return switch_scheduler_add_task(runtime, sch_transfer_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
4927 }
#define __SWITCH_FUNC__
pack cur
struct switch_runtime runtime
Definition: switch_core.c:64
uint32_t switch_scheduler_add_task(time_t task_runtime, switch_scheduler_func_t func, const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags)
Schedule a task in the future.
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1]
#define switch_zmalloc(ptr, len)
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
switch_status_t switch_ivr_session_audio ( switch_core_session_t session,
const char *  cmd,
const char *  direction,
int  level 
)

Definition at line 3101 of file switch_ivr_async.c.

References switch_session_audio_t::read_level, switch_session_audio_t::read_mute, switch_session_audio_t::session, 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.

3102 {
3104  switch_media_bug_t *bug;
3105  switch_status_t status;
3107  switch_codec_implementation_t read_impl = { 0 };
3108  int existing = 0, c_read = 0, c_write = 0, flags = SMBF_NO_PAUSE;
3109 
3111  return SWITCH_STATUS_FALSE;
3112  }
3113 
3114  switch_core_session_get_read_impl(session, &read_impl);
3115 
3116 
3117  if ((bug = switch_channel_get_private(channel, "__audio"))) {
3119  existing = 1;
3120  } else {
3121  if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
3122  return SWITCH_STATUS_MEMERR;
3123  }
3124 
3125  pvt->session = session;
3126  }
3127 
3128 
3129  if (!strcasecmp(direction, "write")) {
3130  flags = SMBF_WRITE_REPLACE;
3131  c_write = 1;
3132  } else if (!strcasecmp(direction, "read")) {
3133  flags = SMBF_READ_REPLACE;
3134  c_read = 1;
3135  } else if (!strcasecmp(direction, "both")) {
3137  c_read = c_write = 1;
3138  }
3139 
3140 
3141  if (!strcasecmp(cmd, "mute")) {
3142  if (c_read) {
3143  pvt->read_mute = level;
3144  pvt->read_level = 0;
3145  }
3146  if (c_write) {
3147  pvt->write_mute = level;
3148  pvt->write_level = 0;
3149  }
3150  } else if (!strcasecmp(cmd, "level")) {
3151  if (level < 5 && level > -5) {
3152  if (c_read) {
3153  pvt->read_level = level;
3154  }
3155  if (c_write) {
3156  pvt->write_level = level;
3157  }
3158  }
3159  }
3160 
3161  if (existing) {
3162  switch_core_media_bug_set_flag(bug, flags);
3163  } else {
3164  if ((status = switch_core_media_bug_add(session, "audio", cmd,
3165  session_audio_callback, pvt, 0, flags, &bug)) != SWITCH_STATUS_SUCCESS) {
3166  return status;
3167  }
3168 
3169  switch_channel_set_private(channel, "__audio", bug);
3170  }
3171 
3172 
3173  return SWITCH_STATUS_SUCCESS;
3174 }
void * switch_core_media_bug_get_user_data(_In_ switch_media_bug_t *bug)
Obtain private data from a media bug.
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
static switch_bool_t session_audio_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
uint32_t switch_core_media_bug_set_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag)
switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session, _In_ const char *function, _In_ const char *target, _In_ switch_media_bug_callback_t callback, _In_opt_ void *user_data, _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug)
Add a media bug to the session.
switch_core_session_t * session
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
switch_status_t switch_ivr_session_echo ( switch_core_session_t session,
switch_input_args_t args 
)

  • NEEDDESC -

Parameters
sessionthe session to act on

Definition at line 645 of file switch_ivr_async.c.

References arg_recursion_check_start, CF_BREAK, CF_VIDEO_DECODED_READ, CF_VIDEO_ECHO, switch_dtmf_t::digit, 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_set_flag, switch_channel_test_flag(), switch_core_session_dequeue_event(), switch_core_session_get_channel(), switch_core_session_raw_read(), switch_core_session_read_frame(), switch_core_session_reset(), switch_core_session_video_reset(), switch_core_session_write_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_FALSE, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_true().

646 {
647  switch_status_t status;
648  switch_frame_t *read_frame;
650 
652  return SWITCH_STATUS_FALSE;
653  }
654 
656 
657  if (switch_true(switch_channel_get_variable(channel, "echo_decode_video"))) {
659  }
660 
661  if (switch_true(switch_channel_get_variable(channel, "echo_decode_audio"))) {
663  }
664 
666 
667  while (switch_channel_ready(channel)) {
668  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
669  if (!SWITCH_READ_ACCEPTABLE(status)) {
670  break;
671  }
672 
674 
675  if (args && (args->input_callback || args->buf || args->buflen)) {
676  switch_dtmf_t dtmf = {0};
677 
678  /*
679  dtmf handler function you can hook up to be executed when a digit is dialed during playback
680  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
681  */
682  if (switch_channel_has_dtmf(channel)) {
683  if (!args->input_callback && !args->buf) {
684  status = SWITCH_STATUS_BREAK;
685  break;
686  }
687  switch_channel_dequeue_dtmf(channel, &dtmf);
688  if (args->input_callback) {
689  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
690  } else {
691  *((char *) args->buf) = dtmf.digit;
692  status = SWITCH_STATUS_BREAK;
693  }
694  }
695 
696  if (args->input_callback) {
697  switch_event_t *event = NULL;
698 
700  status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
701  switch_event_destroy(&event);
702  }
703  }
704 
705  if (status != SWITCH_STATUS_SUCCESS) {
706  break;
707  }
708  }
709 
710  switch_core_session_write_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
711 
712  if (switch_channel_test_flag(channel, CF_BREAK)) {
714  break;
715  }
716  }
717 
720 
721  return SWITCH_STATUS_SUCCESS;
722 }
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
void switch_core_session_raw_read(switch_core_session_t *session)
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
switch_input_callback_function_t input_callback
An abstraction of a data frame.
Definition: switch_frame.h:43
#define arg_recursion_check_start(_args)
void switch_core_session_video_reset(switch_core_session_t *session)
switch_status_t
Common return values.
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
#define switch_channel_set_flag(_c, _f)
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
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
sessionthe session to transfer
extensionthe new extension
dialplanthe new dialplan (OPTIONAL, may be NULL)
contextthe new context (OPTIONAL, may be NULL)

Referenced by fs_switch_ivr_session_transfer(), switch_channel_handle_cause(), switch_ivr_multi_threaded_bridge(), switch_ivr_originate(), 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 4630 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.

4631 {
4634 
4635  if (sth && sth->ah && name && val) {
4636  switch_core_asr_text_param(sth->ah, (char *) name, val);
4637  status = SWITCH_STATUS_SUCCESS;
4638  }
4639 
4640  return status;
4641 }
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
void switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val)
Set a text parameter on an asr handle.
int switch_ivr_set_xml_chan_vars ( switch_xml_t  xml,
switch_channel_t channel,
int  off 
)

Definition at line 2689 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_channel_variable_last(), switch_ivr_set_xml_chan_var(), and switch_event_header::value.

Referenced by switch_ivr_generate_xml_cdr().

2690 {
2691 
2693 
2694  if (!hi)
2695  return off;
2696 
2697  for (; hi; hi = hi->next) {
2698  if (hi->idx) {
2699  int i;
2700 
2701  for (i = 0; i < hi->idx; i++) {
2702  off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->array[i], off);
2703  }
2704  } else {
2705  off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->value, off);
2706  }
2707  }
2709 
2710  return off;
2711 }
static int switch_ivr_set_xml_chan_var(switch_xml_t xml, const char *var, const char *val, int off)
Definition: switch_ivr.c:2667
An event Header.
Definition: switch_event.h:65
switch_event_header_t * switch_channel_variable_first(switch_channel_t *channel)
Start iterating over the entries in the channel variable list.
struct switch_event_header * next
Definition: switch_event.h:76
void switch_channel_variable_last(switch_channel_t *channel)
Stop iterating over channel variables.
int switch_ivr_set_xml_profile_data ( switch_xml_t  xml,
switch_caller_profile_t caller_profile,
int  off 
)

Definition at line 2463 of file switch_ivr.c.

References profile_node_s::next, switch_xml_add_child_d, switch_xml_set_txt_d, profile_node_s::val, and profile_node_s::var.

Referenced by switch_ivr_generate_xml_cdr().

2464 {
2465  switch_xml_t param;
2466 
2467  if (!(param = switch_xml_add_child_d(xml, "username", off++))) {
2468  return -1;
2469  }
2470  switch_xml_set_txt_d(param, caller_profile->username);
2471 
2472  if (!(param = switch_xml_add_child_d(xml, "dialplan", off++))) {
2473  return -1;
2474  }
2475  switch_xml_set_txt_d(param, caller_profile->dialplan);
2476 
2477  if (!(param = switch_xml_add_child_d(xml, "caller_id_name", off++))) {
2478  return -1;
2479  }
2480  switch_xml_set_txt_d(param, caller_profile->caller_id_name);
2481 
2482  if (!(param = switch_xml_add_child_d(xml, "caller_id_number", off++))) {
2483  return -1;
2484  }
2485  switch_xml_set_txt_d(param, caller_profile->caller_id_number);
2486 
2487  if (!(param = switch_xml_add_child_d(xml, "callee_id_name", off++))) {
2488  return -1;
2489  }
2490  switch_xml_set_txt_d(param, caller_profile->callee_id_name);
2491 
2492  if (!(param = switch_xml_add_child_d(xml, "callee_id_number", off++))) {
2493  return -1;
2494  }
2495  switch_xml_set_txt_d(param, caller_profile->callee_id_number);
2496 
2497  if (!(param = switch_xml_add_child_d(xml, "ani", off++))) {
2498  return -1;
2499  }
2500  switch_xml_set_txt_d(param, caller_profile->ani);
2501 
2502  if (!(param = switch_xml_add_child_d(xml, "aniii", off++))) {
2503  return -1;
2504  }
2505  switch_xml_set_txt_d(param, caller_profile->aniii);
2506 
2507 
2508  if (!(param = switch_xml_add_child_d(xml, "network_addr", off++))) {
2509  return -1;
2510  }
2511  switch_xml_set_txt_d(param, caller_profile->network_addr);
2512 
2513  if (!(param = switch_xml_add_child_d(xml, "rdnis", off++))) {
2514  return -1;
2515  }
2516  switch_xml_set_txt_d(param, caller_profile->rdnis);
2517 
2518  if (!(param = switch_xml_add_child_d(xml, "destination_number", off++))) {
2519  return -1;
2520  }
2521  switch_xml_set_txt_d(param, caller_profile->destination_number);
2522 
2523  if (!(param = switch_xml_add_child_d(xml, "uuid", off++))) {
2524  return -1;
2525  }
2526  switch_xml_set_txt_d(param, caller_profile->uuid);
2527 
2528  if (!(param = switch_xml_add_child_d(xml, "source", off++))) {
2529  return -1;
2530  }
2531  switch_xml_set_txt_d(param, caller_profile->source);
2532 
2533  if (caller_profile->transfer_source) {
2534  if (!(param = switch_xml_add_child_d(xml, "transfer_source", off++))) {
2535  return -1;
2536  }
2537  switch_xml_set_txt_d(param, caller_profile->transfer_source);
2538  }
2539 
2540  if (!(param = switch_xml_add_child_d(xml, "context", off++))) {
2541  return -1;
2542  }
2543  switch_xml_set_txt_d(param, caller_profile->context);
2544 
2545  if (!(param = switch_xml_add_child_d(xml, "chan_name", off++))) {
2546  return -1;
2547  }
2548  switch_xml_set_txt_d(param, caller_profile->chan_name);
2549 
2550 
2551  if (caller_profile->soft) {
2552  profile_node_t *pn;
2553 
2554  for (pn = caller_profile->soft; pn; pn = pn->next) {
2555 
2556  if (!(param = switch_xml_add_child_d(xml, pn->var, off++))) {
2557  return -1;
2558  }
2559  switch_xml_set_txt_d(param, pn->val);
2560  }
2561 
2562  }
2563 
2564 
2565  return off;
2566 }
const char * network_addr
Definition: switch_caller.h:93
#define switch_xml_add_child_d(xml, name, off)
wrapper for switch_xml_add_child() that strdup()s name
Definition: switch_xml.h:269
A representation of an XML tree.
Definition: switch_xml.h:76
const char * dialplan
Definition: switch_caller.h:77
const char * username
Definition: switch_caller.h:75
const char * callee_id_number
Definition: switch_caller.h:89
const char * caller_id_name
Definition: switch_caller.h:79
struct profile_node_s * next
Definition: switch_caller.h:66
#define switch_xml_set_txt_d(xml, txt)
wrapper for switch_xml_set_txt() that strdup()s txt \ sets the character content for the given tag an...
Definition: switch_xml.h:283
const char * caller_id_number
Definition: switch_caller.h:81
profile_node_t * soft
const char * callee_id_name
Definition: switch_caller.h:87
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
sessionone session
peer_sessionthe other session
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1341 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, 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_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_core_standard_on_reset(), switch_ivr_3p_nomedia(), switch_ivr_multi_threaded_bridge(), and switch_ivr_nomedia().

1342 {
1343  switch_channel_t *caller_channel = switch_core_session_get_channel(session);
1344  switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
1345  switch_event_t *event;
1346 
1347  if (switch_channel_down_nosig(peer_channel)) {
1348  switch_channel_hangup(caller_channel, switch_channel_get_cause(peer_channel));
1349  return SWITCH_STATUS_FALSE;
1350  }
1351 
1352  if (!switch_channel_up_nosig(caller_channel)) {
1354  return SWITCH_STATUS_FALSE;
1355  }
1356 
1357  check_bridge_export(caller_channel, peer_channel);
1358 
1361 
1364  switch_channel_set_variable(peer_channel, "call_uuid", switch_core_session_get_uuid(session));
1365 
1368 
1369  switch_channel_clear_state_handler(caller_channel, NULL);
1370  switch_channel_clear_state_handler(peer_channel, NULL);
1371 
1374 
1375  switch_channel_set_variable(caller_channel, "signal_bridge", "true");
1376  switch_channel_set_variable(peer_channel, "signal_bridge", "true");
1377 
1378  /* fire events that will change the data table from "show channels" */
1380  switch_channel_event_set_data(caller_channel, event);
1381  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", "signal_bridge");
1382  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(peer_session));
1383  switch_event_fire(&event);
1384  }
1385 
1387  switch_channel_event_set_data(peer_channel, event);
1388  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", "signal_bridge");
1390  switch_event_fire(&event);
1391  }
1392 
1393  switch_channel_set_state_flag(caller_channel, CF_RESET);
1394  switch_channel_set_state_flag(peer_channel, CF_RESET);
1395 
1396  switch_channel_set_state(caller_channel, CS_HIBERNATE);
1397  switch_channel_set_state(peer_channel, CS_HIBERNATE);
1398 
1399 #if 0
1400  if (switch_channel_test_flag(caller_channel, CF_BRIDGED)) {
1401  switch_channel_set_flag(caller_channel, CF_TRANSFER);
1402  switch_channel_set_flag(peer_channel, CF_TRANSFER);
1403  }
1404 #endif
1405 
1406  switch_ivr_bridge_display(session, peer_session);
1407 
1408  return SWITCH_STATUS_SUCCESS;
1409 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:201
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
void switch_channel_set_state_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Set given flag(s) on a given channel to be applied on the next state change.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
clear a state handler table from a given channel
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_channel_down_nosig(_channel)
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
static void check_bridge_export(switch_channel_t *channel, switch_channel_t *peer_channel)
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
#define switch_channel_set_flag(_c, _f)
void switch_ivr_bridge_display(switch_core_session_t *session, switch_core_session_t *peer_session)
int switch_channel_add_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
add a state handler table to a given channel
#define switch_channel_up_nosig(_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_channel_set_variable(_channel, _var, _val)
static const switch_state_handler_table_t signal_bridge_state_handlers
switch_call_cause_t switch_channel_get_cause(_In_ switch_channel_t *channel)
return the cause code for a given channel
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
sessionthe session to wait for.
msthe number of milliseconds
syncsynchronize the channel's audio before waiting
argsarguements 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_codec_implementation::actual_samples_per_second, arg_recursion_check_start, arg_recursion_check_stop, switch_frame::buflen, CF_BREAK, CF_VIDEO_BLANK, 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, 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_set_flag, 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_goto_status, 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_channel_perform_answer(), switch_ivr_originate(), switch_ivr_phrase_macro_event(), switch_ivr_play_and_detect_speech(), and switch_ivr_play_file().

128 {
131  switch_time_t start = switch_micro_time_now(), now, done = switch_micro_time_now() + (ms * 1000);
132  switch_frame_t *read_frame, cng_frame = { 0 };
133  int32_t left;
134  uint32_t elapsed;
135  char data[2] = "";
136 
137  switch_frame_t write_frame = { 0 };
138  unsigned char *abuf = NULL;
139  switch_codec_implementation_t imp = { 0 };
140  switch_codec_t codec = { 0 };
141  int sval = 0;
142  const char *var;
143 
145 
147 
148  switch_core_session_get_read_impl(session, &imp);
149 
150  /*
151  if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
152  !switch_channel_media_ready(channel) && !switch_channel_test_flag(channel, CF_SERVICE)) {
153  if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
154  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media.\n");
155  return SWITCH_STATUS_FALSE;
156  }
157  }
158  */
159 
160  if (!switch_channel_media_ready(channel)) {
161 
162  for (elapsed=0; switch_channel_ready(channel) && elapsed<(ms/20); elapsed++) {
163  if (switch_channel_test_flag(channel, CF_BREAK)) {
166  }
167 
168  switch_yield(20 * 1000);
169  }
171  }
172 
174  && (sval = atoi(var))) {
176  }
177 
178  if (ms > 10 && sval) {
179 
180  if (switch_core_codec_init(&codec,
181  "L16",
182  NULL,
183  NULL,
185  imp.microseconds_per_packet / 1000,
186  imp.number_of_channels,
189  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
192  }
193 
194 
195  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
197 
198  write_frame.codec = &codec;
200  write_frame.data = abuf;
202  write_frame.datalen = imp.decoded_bytes_per_packet;
203  write_frame.samples = write_frame.datalen / sizeof(int16_t);
204 
205  }
206 
207  if (!write_frame.datalen) {
208  sval = 0;
209  }
210 
211  cng_frame.data = data;
212  cng_frame.datalen = 2;
213  cng_frame.buflen = 2;
214  switch_set_flag((&cng_frame), SFF_CNG);
215 
216  if (sync) {
217  switch_channel_audio_sync(channel);
218  }
219 
220  if (!ms) {
222  }
223 
224  for (;;) {
225  now = switch_micro_time_now();
226  elapsed = (int32_t) ((now - start) / 1000);
227  left = ms - elapsed;
228 
229  if (!switch_channel_ready(channel)) {
230  status = SWITCH_STATUS_FALSE;
231  break;
232  }
233 
234  if (switch_channel_test_flag(channel, CF_BREAK)) {
236  status = SWITCH_STATUS_BREAK;
237  break;
238  }
239 
240  if (now > done || left <= 0) {
241  break;
242  }
243 
244 
246 
247 
248  if (args) {
249  switch_dtmf_t dtmf = {0};
250 
251  /*
252  dtmf handler function you can hook up to be executed when a digit is dialed during playback
253  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
254  */
255  if (switch_channel_has_dtmf(channel)) {
256  if (!args->input_callback && !args->buf && !args->dmachine) {
257  status = SWITCH_STATUS_BREAK;
258  break;
259  }
260  switch_channel_dequeue_dtmf(channel, &dtmf);
261 
262  if (args->dmachine) {
263  char ds[2] = {dtmf.digit, '\0'};
264  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
265  break;
266  }
267  }
268 
269  if (args->input_callback) {
270  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
271  } else if (args->buf) {
272  *((char *) args->buf) = dtmf.digit;
273  status = SWITCH_STATUS_BREAK;
274  }
275  }
276 
277  if (args->input_callback) {
278  switch_event_t *event = NULL;
279 
281  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
282  if (ostatus != SWITCH_STATUS_SUCCESS) {
283  status = ostatus;
284  }
285  switch_event_destroy(&event);
286  }
287  }
288 
289  if (status != SWITCH_STATUS_SUCCESS) {
290  break;
291  }
292  }
293 
294  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
295 
296  if (!SWITCH_READ_ACCEPTABLE(status)) {
297  break;
298  }
299 
300  if (args && args->dmachine) {
301  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
302  break;
303  }
304  }
305 
306  if (sval && write_frame.datalen) {
307  switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, imp.number_of_channels, sval);
308  switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
309  } else {
310  switch_core_session_write_frame(session, &cng_frame, SWITCH_IO_FLAG_NONE, 0);
311  }
312  }
313 
314 
315  end:
316 
318 
320 
321  if (write_frame.codec) {
323  }
324 
325  switch_safe_free(abuf);
326 
327  return status;
328 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:310
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
#define arg_recursion_check_stop(_args)
void switch_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t channels, uint32_t divisor)
Generate static noise.
#define switch_channel_media_ready(_channel)
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
#define SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE
Definition: switch_types.h:129
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
int64_t switch_time_t
Definition: switch_apr.h:188
uint32_t buflen
Definition: switch_frame.h:59
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
#define switch_channel_audio_sync(_c)
uint32_t datalen
Definition: switch_frame.h:57
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
#define switch_zmalloc(ptr, len)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_input_callback_function_t input_callback
#define SWITCH_IVR_VERIFY_SILENCE_DIVISOR(divisor)
Definition: switch_ivr.h:68
An abstraction of a data frame.
Definition: switch_frame.h:43
#define arg_recursion_check_start(_args)
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
switch_status_t
Common return values.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:256
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
uint32_t samples
Definition: switch_frame.h:61
#define switch_channel_set_flag(_c, _f)
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_ivr_dmachine_t * dmachine
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
sessionthe session to speak on
tts_namethe desired tts module
voice_namethe desired voice
textthe text to speak
argsarguements to pass for callbacks etc
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2647 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, arg_recursion_check_start, arg_recursion_check_stop, switch_frame::codec, cached_speech_handle::codec, memset(), switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, 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().

2649 {
2651  uint32_t rate = 0;
2652  int interval = 0;
2653  uint32_t channels;
2654  switch_frame_t write_frame = { 0 };
2655  switch_timer_t ltimer, *timer;
2656  switch_codec_t lcodec, *codec;
2658  char *codec_name;
2660  switch_speech_handle_t lsh, *sh;
2662  const char *timer_name, *var;
2663  cached_speech_handle_t *cache_obj = NULL;
2664  int need_create = 1, need_alloc = 1;
2665  switch_codec_implementation_t read_impl = { 0 };
2666  switch_core_session_get_read_impl(session, &read_impl);
2667 
2669  return SWITCH_STATUS_FALSE;
2670  }
2671 
2673 
2674  sh = &lsh;
2675  codec = &lcodec;
2676  timer = &ltimer;
2677 
2680  need_create = 0;
2681  if (!strcasecmp(cache_obj->tts_name, tts_name)) {
2682  need_alloc = 0;
2683  } else {
2685  }
2686  }
2687 
2688  if (!cache_obj) {
2689  cache_obj = (cached_speech_handle_t *) switch_core_session_alloc(session, sizeof(*cache_obj));
2690  }
2691  if (need_alloc) {
2692  switch_copy_string(cache_obj->tts_name, tts_name, sizeof(cache_obj->tts_name));
2693  switch_copy_string(cache_obj->voice_name, voice_name, sizeof(cache_obj->voice_name));
2695  }
2696  sh = &cache_obj->sh;
2697  codec = &cache_obj->codec;
2698  timer = &cache_obj->timer;
2699  }
2700 
2701  timer_name = switch_channel_get_variable(channel, "timer_name");
2702 
2704 
2705  rate = read_impl.actual_samples_per_second;
2706  interval = read_impl.microseconds_per_packet / 1000;
2707  channels = read_impl.number_of_channels;
2708 
2709  if (need_create) {
2710  memset(sh, 0, sizeof(*sh));
2711  if ((status = switch_core_speech_open(sh, tts_name, voice_name, (uint32_t) rate, interval, read_impl.number_of_channels, &flags, NULL)) != SWITCH_STATUS_SUCCESS) {
2712  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid TTS module!\n");
2716  return status;
2717  }
2718  } else if (cache_obj && strcasecmp(cache_obj->voice_name, voice_name)) {
2719  switch_copy_string(cache_obj->voice_name, voice_name, sizeof(cache_obj->voice_name));
2720  switch_core_speech_text_param_tts(sh, "voice", voice_name);
2721  }
2722 
2724  flags = 0;
2725  switch_core_speech_close(sh, &flags);
2727  return SWITCH_STATUS_FALSE;
2728  }
2729  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
2730 
2731  codec_name = "L16";
2732 
2733  if (need_create) {
2734  if (switch_core_codec_init(codec,
2735  codec_name,
2736  NULL,
2737  NULL, (int) rate, interval, channels, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
2738  pool) == SWITCH_STATUS_SUCCESS) {
2739  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
2740  } else {
2741  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed %s@%uhz 1 channel %dms\n", codec_name,
2742  rate, interval);
2743  flags = 0;
2744  switch_core_speech_close(sh, &flags);
2748  return SWITCH_STATUS_GENERR;
2749  }
2750  }
2751 
2752  write_frame.codec = codec;
2753 
2754  if (timer_name) {
2755  if (need_create) {
2756  if (switch_core_timer_init(timer, timer_name, interval, (int) sh->samples, pool) != SWITCH_STATUS_SUCCESS) {
2757  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n");
2758  switch_core_codec_destroy(write_frame.codec);
2759  flags = 0;
2760  switch_core_speech_close(sh, &flags);
2764  return SWITCH_STATUS_GENERR;
2765  }
2766  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", sh->samples * 2,
2767  interval);
2768  }
2769  switch_core_timer_sync(timer); // Sync timer
2770 
2771  /* start a thread to absorb incoming audio */
2772  switch_core_service_session(session);
2773 
2774  }
2775 
2776  status = switch_ivr_speak_text_handle(session, sh, write_frame.codec, timer_name ? timer : NULL, text, args);
2777  flags = 0;
2778 
2779  if (!cache_obj) {
2780  switch_core_speech_close(sh, &flags);
2782  }
2783 
2784  if (timer_name) {
2785  /* End the audio absorbing thread */
2787  if (!cache_obj) {
2789  }
2790  }
2791 
2794 
2795  return status;
2796 }
void switch_core_thread_session_end(_In_ switch_core_session_t *session)
Signal a thread using a thread session to terminate.
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_core_timer_init(switch_timer_t *timer, const char *timer_name, int interval, int samples, switch_memory_pool_t *pool)
Request a timer handle using given time module.
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
uint32_t switch_speech_flag_t
switch_memory_pool_t * pool
#define arg_recursion_check_stop(_args)
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
void switch_core_speech_text_param_tts(switch_speech_handle_t *sh, char *param, const char *val)
Set a text parameter on a TTS handle.
Abstract handler to a timer module.
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)
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
switch_codec_t * codec
Definition: switch_frame.h:45
#define SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME
Definition: switch_types.h:187
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags)
Close an open speech handle.
#define SWITCH_CACHE_SPEECH_HANDLES_VARIABLE
Definition: switch_types.h:186
#define switch_channel_get_variable(_c, _v)
An abstraction of a data frame.
Definition: switch_frame.h:43
#define arg_recursion_check_start(_args)
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
switch_speech_handle_t sh
#define switch_core_service_session(_s)
Definition: switch_core.h:1186
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
switch_status_t switch_core_timer_destroy(switch_timer_t *timer)
Destroy an allocated timer.
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_status_t switch_core_speech_open(_In_ switch_speech_handle_t *sh, const char *module_name, const char *voice_name, _In_ unsigned int rate, _In_ unsigned int interval, _In_ unsigned int channels, switch_speech_flag_t *flags, _In_opt_ switch_memory_pool_t *pool)
Open a speech handle.
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
struct apr_pool_t switch_memory_pool_t
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
memset(buf, 0, buflen)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
void switch_ivr_clear_speech_cache(switch_core_session_t *session)
switch_status_t switch_core_timer_sync(switch_timer_t *timer)
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 2350 of file switch_ivr_play_say.c.

References arg_recursion_check_start, arg_recursion_check_stop, switch_frame::buflen, CF_BREAK, CF_HOLD, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_dtmf_t::digit, memset(), 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_codec_ready(), 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_RECOMMENDED_BUFFER_SIZE, 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, switch_frame::timestamp, and switch_frame::user_data.

Referenced by switch_ivr_speak_text().

2353 {
2355  short abuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
2356  switch_dtmf_t dtmf = { 0 };
2357  uint32_t len = 0;
2358  switch_size_t ilen = 0;
2359  switch_frame_t write_frame = { 0 };
2360  int done = 0;
2363  switch_size_t extra = 0;
2364  char *p, *tmp = NULL;
2365  const char *star, *pound;
2366  switch_size_t starlen, poundlen;
2367 
2368  if (!sh) {
2369  return SWITCH_STATUS_FALSE;
2370  }
2371 
2373  return SWITCH_STATUS_FALSE;
2374  }
2375 
2376  if (!switch_core_codec_ready(codec)) {
2377  return SWITCH_STATUS_FALSE;
2378  }
2379 
2381 
2382  write_frame.data = abuf;
2383  write_frame.buflen = sizeof(abuf);
2384 
2385  len = sh->samples * 2 * sh->channels;
2386 
2387  flags = 0;
2388 
2389  if (!(star = switch_channel_get_variable(channel, "star_replace"))) {
2390  star = "star";
2391  }
2392  if (!(pound = switch_channel_get_variable(channel, "pound_replace"))) {
2393  pound = "pound";
2394  }
2395  starlen = strlen(star);
2396  poundlen = strlen(pound);
2397 
2398 
2399  for (p = text; p && *p; p++) {
2400  if (*p == '*') {
2401  extra += starlen;
2402  } else if (*p == '#') {
2403  extra += poundlen;
2404  }
2405  }
2406 
2407  if (extra) {
2408  char *tp;
2409  switch_size_t mylen = strlen(text) + extra + 1;
2410  tmp = malloc(mylen);
2411  if (!tmp) {
2413  return SWITCH_STATUS_MEMERR;
2414  }
2415  memset(tmp, 0, mylen);
2416  tp = tmp;
2417  for (p = text; p && *p; p++) {
2418  if (*p == '*') {
2419  strncat(tp, star, starlen);
2420  tp += starlen;
2421  } else if (*p == '#') {
2422  strncat(tp, pound, poundlen);
2423  tp += poundlen;
2424  } else {
2425  *tp++ = *p;
2426  }
2427  }
2428 
2429  text = tmp;
2430  }
2431 
2432  switch_core_speech_feed_tts(sh, text, &flags);
2433  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Speaking text: %s\n", text);
2434  switch_safe_free(tmp);
2435  text = NULL;
2436 
2437  write_frame.rate = sh->rate;
2438  memset(write_frame.data, 0, len);
2439  write_frame.datalen = len;
2440  write_frame.samples = len / 2;
2441  write_frame.codec = codec;
2442 
2443  switch_assert(codec->implementation != NULL);
2444 
2445  switch_channel_audio_sync(channel);
2446 
2447 
2448  for (;;) {
2449  switch_event_t *event;
2450 
2451  ilen = len;
2452 
2453  if (!switch_channel_ready(channel)) {
2454  status = SWITCH_STATUS_FALSE;
2455  break;
2456  }
2457 
2458  if (switch_channel_test_flag(channel, CF_BREAK)) {
2460  status = SWITCH_STATUS_BREAK;
2461  break;
2462  }
2463 
2465  switch_ivr_parse_event(session, event);
2466  switch_event_destroy(&event);
2467  }
2468 
2469  if (args) {
2470  /* dtmf handler function you can hook up to be executed when a digit is dialed during playback
2471  * if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
2472  */
2473  if (switch_channel_has_dtmf(channel)) {
2474  if (!args->input_callback && !args->buf && !args->dmachine) {
2475  status = SWITCH_STATUS_BREAK;
2476  done = 1;
2477  break;
2478  }
2479  if (args->buf && !strcasecmp(args->buf, "_break_")) {
2480  status = SWITCH_STATUS_BREAK;
2481  } else {
2482  switch_channel_dequeue_dtmf(channel, &dtmf);
2483 
2484  if (args->dmachine) {
2485  char ds[2] = {dtmf.digit, '\0'};
2486  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
2487  break;
2488  }
2489  }
2490 
2491  if (args->input_callback) {
2492  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
2493  } else if (args->buf) {
2494  *((char *) args->buf) = dtmf.digit;
2495  status = SWITCH_STATUS_BREAK;
2496  }
2497  }
2498  }
2499 
2500  if (args->input_callback) {
2502  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
2503  if (ostatus != SWITCH_STATUS_SUCCESS) {
2504  status = ostatus;
2505  }
2506  switch_event_destroy(&event);
2507  }
2508  }
2509 
2510  if (status != SWITCH_STATUS_SUCCESS) {
2511  done = 1;
2512  break;
2513  }
2514  }
2515 
2517  if (timer) {
2519  break;
2520  }
2521  } else {
2522  switch_frame_t *read_frame;
2523  switch_status_t tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2524 
2525  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
2527  switch_yield(10000);
2528  }
2529 
2530  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
2531  break;
2532  }
2533 
2534  if (args && args->dmachine) {
2535  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
2536  goto done;
2537  }
2538  }
2539 
2540  if (args && (args->read_frame_callback)) {
2541  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
2542  goto done;
2543  }
2544  }
2545  }
2546  continue;
2547  }
2548 
2549 
2551  status = switch_core_speech_read_tts(sh, abuf, &ilen, &flags);
2552 
2553  if (status != SWITCH_STATUS_SUCCESS) {
2554  if (status == SWITCH_STATUS_BREAK) {
2555  status = SWITCH_STATUS_SUCCESS;
2556  }
2557  done = 1;
2558  }
2559 
2560  if (done) {
2561  break;
2562  }
2563 
2564  write_frame.datalen = (uint32_t) ilen;
2565  write_frame.samples = (uint32_t) (ilen / 2 / sh->channels);
2566  if (timer) {
2567  write_frame.timestamp = timer->samplecount;
2568  }
2570  done = 1;
2571  break;
2572  }
2573 
2574  if (done) {
2575  break;
2576  }
2577 
2578  if (timer) {
2580  break;
2581  }
2582  } else { /* time off the channel (if you must) */
2583  switch_frame_t *read_frame;
2584  switch_status_t tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2585 
2586  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
2588  switch_yield(10000);
2589  }
2590 
2591  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
2592  break;
2593  }
2594 
2595  if (args && args->dmachine) {
2596  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
2597  goto done;
2598  }
2599  }
2600 
2601  if (args && (args->read_frame_callback)) {
2602  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
2603  goto done;
2604  }
2605  }
2606  }
2607  }
2608 
2609  done:
2610 
2611  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done speaking text\n");
2612  flags = 0;
2614 
2616  return status;
2617 }
switch_status_t switch_core_speech_read_tts(switch_speech_handle_t *sh, void *data, switch_size_t *datalen, switch_speech_flag_t *flags)
Read rendered audio from the TTS module.
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match)
uint32_t switch_speech_flag_t
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
uint32_t timestamp
Definition: switch_frame.h:69
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
#define arg_recursion_check_stop(_args)
switch_status_t switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags)
Feed text to the TTS module.
switch_status_t switch_ivr_parse_event(_In_ switch_core_session_t *session, _In_ switch_event_t *event)
Parse command from an event.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:59
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
#define switch_channel_audio_sync(_c)
uint32_t datalen
Definition: switch_frame.h:57
uint32_t rate
Definition: switch_frame.h:63
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_input_callback_function_t input_callback
switch_status_t switch_core_session_dequeue_private_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event)
DE-Queue a private event on a given session.
An abstraction of a data frame.
Definition: switch_frame.h:43
uintptr_t switch_size_t
#define arg_recursion_check_start(_args)
switch_read_frame_callback_function_t read_frame_callback
void switch_core_speech_flush_tts(switch_speech_handle_t *sh)
Flush TTS audio on a given handle.
switch_status_t switch_core_timer_next(switch_timer_t *timer)
Wait for one cycle on an existing timer.
switch_status_t
Common return values.
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
uint32_t samples
Definition: switch_frame.h:61
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
static switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_assert(expr)
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
memset(buf, 0, buflen)
switch_ivr_dmachine_t * dmachine
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:801
switch_status_t switch_ivr_stop_detect_speech ( switch_core_session_t session)

Stop background Speech detection on a session.

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

Definition at line 4574 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_init(), switch_ivr_detect_speech_load_grammar(), switch_ivr_detect_speech_unload_grammar(), and switch_ivr_play_and_detect_speech().

4575 {
4577  struct speech_thread_handle *sth;
4578 
4579  switch_assert(channel != NULL);
4580  if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
4582  switch_core_event_hook_remove_recv_dtmf(session, speech_on_dtmf);
4583  switch_core_media_bug_remove(session, &sth->bug);
4584  return SWITCH_STATUS_SUCCESS;
4585  }
4586 
4587  return SWITCH_STATUS_FALSE;
4588 }
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
static switch_status_t speech_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:226
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug)
Remove a media bug from the session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
#define switch_assert(expr)
switch_media_bug_t * bug
switch_status_t switch_ivr_stop_displace_session ( switch_core_session_t session,
const char *  file 
)

Stop displacing a session.

Parameters
sessionthe session
filefile name from the switch_ivr_displace_session call
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 898 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.

899 {
902 
903  if ((bug = switch_channel_get_private(channel, file))) {
904  switch_channel_set_private(channel, file, NULL);
905  switch_core_media_bug_remove(session, &bug);
906  return SWITCH_STATUS_SUCCESS;
907  }
908 
909  return SWITCH_STATUS_FALSE;
910 }
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug)
Remove a media bug from the session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_media_bug_t * bug
switch_status_t switch_ivr_stop_inband_dtmf_generate_session ( switch_core_session_t session)

Stop generating DTMF inband.

Parameters
sessionthe session to stop generating
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3450 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.

3451 {
3453  switch_media_bug_t *bug = switch_channel_get_private(channel, "dtmf_generate");
3454 
3455  if (bug) {
3456  switch_channel_set_private(channel, "dtmf_generate", NULL);
3457  switch_core_media_bug_remove(session, &bug);
3458  return SWITCH_STATUS_SUCCESS;
3459  }
3460 
3461  return SWITCH_STATUS_FALSE;
3462 
3463 }
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug)
Remove a media bug from the session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_media_bug_t * bug
switch_status_t switch_ivr_stop_inband_dtmf_session ( switch_core_session_t session)

Stop looking for DTMF inband.

Parameters
sessionthe session to stop looking
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3216 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.

3217 {
3220 
3221  if ((bug = switch_channel_get_private(channel, "dtmf"))) {
3222  switch_channel_set_private(channel, "dtmf", NULL);
3223  switch_core_media_bug_remove(session, &bug);
3224  return SWITCH_STATUS_SUCCESS;
3225  }
3226  return SWITCH_STATUS_FALSE;
3227 }
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug)
Remove a media bug from the session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_media_bug_t * bug
switch_status_t switch_ivr_stop_record_session ( switch_core_session_t session,
const char *  file 
)

Stop Recording a session.

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

Definition at line 1544 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().

1545 {
1548 
1549  if (!strcasecmp(file, "all")) {
1551  } else if ((bug = switch_channel_get_private(channel, file))) {
1552  switch_core_media_bug_remove(session, &bug);
1553  return SWITCH_STATUS_SUCCESS;
1554  }
1555  return SWITCH_STATUS_FALSE;
1556 }
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_media_bug_remove_callback(switch_core_session_t *session, switch_media_bug_callback_t callback)
Remove media bug callback.
switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug)
Remove a media bug from the session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
switch_media_bug_t * bug
switch_status_t switch_ivr_stop_session_audio ( switch_core_session_t session)

Definition at line 3088 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.

3089 {
3092 
3093  if ((bug = switch_channel_get_private(channel, "__audio"))) {
3094  switch_channel_set_private(channel, "__audio", NULL);
3095  switch_core_media_bug_remove(session, &bug);
3096  return SWITCH_STATUS_SUCCESS;
3097  }
3098  return SWITCH_STATUS_FALSE;
3099 }
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug)
Remove a media bug from the session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_media_bug_t * bug
switch_status_t switch_ivr_stop_tone_detect_session ( switch_core_session_t session)

Stop looking for TONES.

Parameters
sessionthe session to stop looking
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3682 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.

Referenced by switch_ivr_originate().

3683 {
3685  switch_tone_container_t *cont = switch_channel_get_private(channel, "_tone_detect_");
3686  int i = 0;
3687 
3688  if (cont) {
3689  switch_channel_set_private(channel, "_tone_detect_", NULL);
3690  for (i = 0; i < cont->index; i++) {
3691  cont->list[i].up = 0;
3692  }
3693  switch_core_media_bug_remove(session, &cont->bug);
3694  if (cont->detect_fax) {
3695  cont->detect_fax = 0;
3696  }
3697  return SWITCH_STATUS_SUCCESS;
3698  }
3699  return SWITCH_STATUS_FALSE;
3700 }
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
switch_media_bug_t * bug
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug)
Remove a media bug from the session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
switch_tone_detect_t list[MAX_TONES+1]
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
sessionthe session to start looking
keythe name of the tone.
tone_speccomma sep list of tone freqs
flagsone or both of 'r' and 'w'
timeouttimeout
appoptional application to execute when tone is found
dataoptional data for appliaction
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 3702 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, switch_tone_detect_t::app, switch_tone_container_t::bug, switch_tone_container_t::bug_running, switch_tone_detect_t::callback, switch_tone_detect_t::data, switch_tone_detect_t::default_expires, switch_tone_detect_t::default_sleep, switch_tone_container_t::detect_fax, switch_tone_detect_t::expires, teletone_tone_map_t::freqs, switch_tone_detect_t::hits, switch_tone_container_t::index, switch_tone_detect_t::key, switch_tone_container_t::list, switch_tone_detect_t::map, MAX_TONES, memset(), switch_tone_detect_t::mt, switch_tone_detect_t::once, teletone_multi_tone_t::sample_rate, switch_tone_container_t::session, switch_tone_detect_t::sleep, SMBF_NO_PAUSE, SMBF_READ_REPLACE, SMBF_WRITE_REPLACE, switch_tone_detect_t::start_time, switch_channel_get_name(), switch_channel_get_private(), switch_channel_get_variable, 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_impl(), switch_core_session_strdup, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), switch_micro_time_now(), SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, teletone_multi_tone_init(), tone_detect_callback(), tone_on_dtmf(), switch_tone_detect_t::total_hits, switch_tone_detect_t::up, and zstr.

Referenced by check_channel_status().

3706 {
3708  switch_status_t status;
3709  switch_tone_container_t *cont = switch_channel_get_private(channel, "_tone_detect_");
3710  char *p, *next;
3711  int i = 0, ok = 0, detect_fax = 0;
3712  switch_media_bug_flag_t bflags = 0;
3713  const char *var;
3714  switch_codec_implementation_t read_impl = { 0 };
3715  switch_core_session_get_read_impl(session, &read_impl);
3716 
3717 
3718  if (zstr(key)) {
3719  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Key Specified!\n");
3720  return SWITCH_STATUS_FALSE;
3721  }
3722 
3723  if (cont) {
3724  if (cont->index >= MAX_TONES) {
3725  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Max Tones Reached!\n");
3726  return SWITCH_STATUS_FALSE;
3727  }
3728 
3729  for (i = 0; i < cont->index; i++) {
3730  if (!zstr(cont->list[i].key) && !strcasecmp(key, cont->list[i].key)) {
3731  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Re-enabling %s\n", key);
3732  cont->list[i].up = 1;
3733  cont->list[i].hits = 0;
3734  cont->list[i].sleep = 0;
3735  cont->list[i].expires = 0;
3736  return SWITCH_STATUS_SUCCESS;
3737  }
3738  }
3739  }
3740 
3741  if (zstr(tone_spec)) {
3742  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Spec Specified!\n");
3743  return SWITCH_STATUS_FALSE;
3744  }
3745 
3746  if (!cont && !(cont = switch_core_session_alloc(session, sizeof(*cont)))) {
3747  return SWITCH_STATUS_MEMERR;
3748  }
3749 
3750  if ((var = switch_channel_get_variable(channel, "tone_detect_hits"))) {
3751  int tmp = atoi(var);
3752  if (tmp > 0) {
3753  hits = tmp;
3754  }
3755  }
3756 
3757  if (!hits) hits = 1;
3758 
3759  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);
3760 
3761  i = 0;
3762  p = (char *) tone_spec;
3763 
3764  do {
3765  teletone_process_t this;
3766  next = strchr(p, ',');
3767  while (*p == ' ')
3768  p++;
3769  if ((this = (teletone_process_t) atof(p))) {
3770  ok++;
3771  cont->list[cont->index].map.freqs[i++] = this;
3772  }
3773  if (!strncasecmp(p, "1100", 4)) {
3774  detect_fax = cont->index;
3775  }
3776 
3777  if (next) {
3778  p = next + 1;
3779  }
3780  } while (next);
3781  cont->list[cont->index].map.freqs[i++] = 0;
3782 
3783  if (!ok) {
3784  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid tone spec!\n");
3785  return SWITCH_STATUS_FALSE;
3786  }
3787 
3788  cont->detect_fax = detect_fax;
3789 
3790  cont->list[cont->index].key = switch_core_session_strdup(session, key);
3791 
3792  if (app) {
3793  cont->list[cont->index].app = switch_core_session_strdup(session, app);
3794  }
3795 
3796  if (data) {
3797  cont->list[cont->index].data = switch_core_session_strdup(session, data);
3798  }
3799 
3800  cont->list[cont->index].callback = callback;
3801 
3802  if (!hits)
3803  hits = 1;
3804 
3805  cont->list[cont->index].hits = 0;
3806  cont->list[cont->index].total_hits = hits;
3807  cont->list[cont->index].start_time = switch_micro_time_now();
3808 
3809  cont->list[cont->index].up = 1;
3810  memset(&cont->list[cont->index].mt, 0, sizeof(cont->list[cont->index].mt));
3811  cont->list[cont->index].mt.sample_rate = read_impl.actual_samples_per_second;
3812  teletone_multi_tone_init(&cont->list[cont->index].mt, &cont->list[cont->index].map);
3813  cont->session = session;
3814 
3816  return SWITCH_STATUS_FALSE;
3817  }
3818 
3819  cont->list[cont->index].default_sleep = 25;
3820  cont->list[cont->index].default_expires = 250;
3821 
3822  if ((var = switch_channel_get_variable(channel, "tone_detect_sleep"))) {
3823  int tmp = atoi(var);
3824  if (tmp > 0) {
3825  cont->list[cont->index].default_sleep = tmp;
3826  }
3827  }
3828 
3829  if ((var = switch_channel_get_variable(channel, "tone_detect_expires"))) {
3830  int tmp = atoi(var);
3831  if (tmp > 0) {
3832  cont->list[cont->index].default_expires = tmp;
3833  }
3834  }
3835 
3836 
3837  if (zstr(flags)) {
3838  bflags = SMBF_READ_REPLACE;
3839  } else {
3840  if (strchr(flags, 'o')) {
3841  cont->list[cont->index].once = 1;
3842  }
3843 
3844  if (strchr(flags, 'r')) {
3845  bflags |= SMBF_READ_REPLACE;
3846  } else if (strchr(flags, 'w')) {
3847  bflags |= SMBF_WRITE_REPLACE;
3848  }
3849  }
3850 
3851  bflags |= SMBF_NO_PAUSE;
3852 
3853  if (cont->bug_running) {
3854  status = SWITCH_STATUS_SUCCESS;
3855  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s bug already running\n", switch_channel_get_name(channel));
3856  } else {
3857  cont->bug_running = 1;
3858  if (cont->detect_fax) {
3859  switch_core_event_hook_add_send_dtmf(session, tone_on_dtmf);
3860  switch_core_event_hook_add_recv_dtmf(session, tone_on_dtmf);
3861  }
3862 
3863  if ((status = switch_core_media_bug_add(session, "tone_detect", key,
3864  tone_detect_callback, cont, timeout, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
3865  cont->bug_running = 0;
3866  return status;
3867  }
3868  switch_channel_set_private(channel, "_tone_detect_", cont);
3869  }
3870 
3871  cont->index++;
3872 
3873  return SWITCH_STATUS_SUCCESS;
3874 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:310
teletone_multi_tone_t mt
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define MAX_TONES
switch_core_session_t * session
teletone_tone_map_t map
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
double teletone_process_t
Definition: libteletone.h:84
static switch_bool_t tone_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
switch_media_bug_t * bug
switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session, _In_ const char *function, _In_ const char *target, _In_ switch_media_bug_callback_t callback, _In_opt_ void *user_data, _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug)
Add a media bug to the session.
#define zstr(x)
Definition: switch_utils.h:281
void teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
Initilize a multi-frequency tone detector.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
static switch_status_t tone_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
switch_core_session_t * session
teletone_process_t freqs[TELETONE_MAX_TONES]
Definition: libteletone.h:95
#define switch_channel_get_variable(_c, _v)
switch_status_t
Common return values.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
uint32_t switch_media_bug_flag_t
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_tone_detect_callback_t callback
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_tone_detect_t list[MAX_TONES+1]
memset(buf, 0, buflen)
switch_status_t switch_ivr_transfer_recordings ( switch_core_session_t orig_session,
switch_core_session_t new_session 
)

Definition at line 1571 of file switch_ivr_async.c.

References record_callback(), switch_channel_get_variable, switch_channel_set_variable, switch_channel_transfer_variable_prefix(), switch_core_media_bug_transfer_callback(), switch_core_session_get_channel(), switch_ivr_record_user_data_dup(), SWITCH_RECORD_POST_PROCESS_EXEC_API_VARIABLE, and SWITCH_RECORD_POST_PROCESS_EXEC_APP_VARIABLE.

1572 {
1573  const char *var = NULL;
1574  switch_channel_t *orig_channel = switch_core_session_get_channel(orig_session);
1575  switch_channel_t *new_channel = switch_core_session_get_channel(new_session);
1576 
1579  }
1581 
1583 }
#define SWITCH_RECORD_POST_PROCESS_EXEC_APP_VARIABLE
Definition: switch_types.h:145
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_core_media_bug_transfer_callback(switch_core_session_t *orig_session, switch_core_session_t *new_session, switch_media_bug_callback_t callback, void *(*user_data_dup_func)(switch_core_session_t *, void *))
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_transfer_variable_prefix(switch_channel_t *orig_channel, switch_channel_t *new_channel, const char *prefix)
static void * switch_ivr_record_user_data_dup(switch_core_session_t *session, void *user_data)
#define SWITCH_RECORD_POST_PROCESS_EXEC_API_VARIABLE
Definition: switch_types.h:146
#define switch_channel_set_variable(_channel, _var, _val)
static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
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
sessathe original session
sessbthe new session
varthe name of the variable to transfer (NULL for all)
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 2182 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.

2183 {
2186  switch_event_t *var_event;
2187 
2188  const char *val = NULL;
2189  uint8_t prefix = 0;
2190 
2191  if (var && *var == '~') {
2192  var++;
2193  prefix = 1;
2194  }
2195 
2196  if (var && !prefix) {
2197  if ((val = switch_channel_get_variable(chana, var))) {
2198  switch_channel_set_variable(chanb, var, val);
2199  }
2200  } else {
2202 
2203  switch_channel_get_variables(chana, &var_event);
2204 
2205  for (hi = var_event->headers; hi; hi = hi->next) {
2206  char *vvar = hi->name;
2207  char *vval = hi->value;
2208  if (vvar && vval && (!prefix || (var && !strncmp((char *) vvar, var, strlen(var))))) {
2209  switch_channel_set_variable(chanb, (char *) vvar, (char *) vval);
2210  }
2211  }
2212 
2213  switch_event_destroy(&var_event);
2214  }
2215 
2216  return SWITCH_STATUS_SUCCESS;
2217 }
Representation of an event.
Definition: switch_event.h:80
An event Header.
Definition: switch_event.h:65
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_get_variables(switch_channel_t *channel, switch_event_t **event)
struct switch_event_header * next
Definition: switch_event.h:76
void switch_event_destroy(switch_event_t **event)
Destroy an event.
#define switch_channel_set_variable(_channel, _var, _val)
switch_event_header_t * headers
Definition: switch_event.h:90
switch_status_t switch_ivr_unhold ( switch_core_session_t session)

Signal the session with a protocol specific unhold message.

Parameters
sessionthe session to unhold
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1515 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_event_set_data(), switch_channel_get_partner_uuid(), 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_EVENT_CHANNEL_UNHOLD, switch_event_create, switch_event_fire, SWITCH_FALSE, SWITCH_MESSAGE_INDICATE_UNHOLD, and SWITCH_STATUS_SUCCESS.

Referenced by switch_core_media_toggle_hold(), switch_ivr_hold_toggle_uuid(), and switch_ivr_unhold_uuid().

1516 {
1517  switch_core_session_message_t msg = { 0 };
1519  const char *other_uuid;
1520  switch_core_session_t *b_session;
1521  switch_event_t *event;
1522 
1524  msg.from = __FILE__;
1525 
1528 
1529  switch_core_session_receive_message(session, &msg);
1530 
1531 
1532  if ((other_uuid = switch_channel_get_partner_uuid(channel)) && (b_session = switch_core_session_locate(other_uuid))) {
1533  switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
1534  switch_channel_stop_broadcast(b_channel);
1535  switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
1536  switch_core_session_rwunlock(b_session);
1537  }
1538 
1539 
1541  switch_channel_event_set_data(channel, event);
1542  switch_event_fire(&event);
1543  }
1544 
1545  return SWITCH_STATUS_SUCCESS;
1546 }
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
#define switch_channel_stop_broadcast(_channel)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
switch_status_t switch_ivr_unhold_uuid ( const char *  uuid)

Signal the session with a protocol specific unhold message.

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

Definition at line 1548 of file switch_ivr.c.

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

1549 {
1551 
1552  if ((session = switch_core_session_locate(uuid))) {
1553  switch_ivr_unhold(session);
1555  }
1556 
1557  return SWITCH_STATUS_SUCCESS;
1558 }
switch_core_session_t * session
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
switch_status_t switch_ivr_unhold(switch_core_session_t *session)
Signal the session with a protocol specific unhold message.
Definition: switch_ivr.c:1515
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
switch_status_t switch_ivr_uuid_bridge ( const char *  originator_uuid,
const char *  originatee_uuid 
)

Bridge two existing sessions.

Parameters
originator_uuidthe uuid of the originator
originatee_uuidthe 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 1807 of file switch_ivr_bridge.c.

References switch_caller_profile::callee_id_name, switch_caller_profile::callee_id_number, switch_caller_profile::caller_id_name, switch_caller_profile::caller_id_number, CF_BLEG, CF_BRIDGE_ORIGINATOR, CF_DIALPLAN, CF_HOLD_ON_BRIDGE, CF_LEG_HOLDING, CF_ORIGINATING, CF_RECOVERING_BRIDGE, CF_REDIRECT, CF_TRANSFER, CF_UUID_BRIDGE_ORIGINATOR, cleanup_proxy_mode_a(), CS_CONSUME_MEDIA, CS_HIBERNATE, switch_caller_profile::destination_number, DUMP_EVENT, switch_caller_profile::pool, SWITCH_BRIDGE_CHANNEL_VARIABLE, SWITCH_BRIDGE_UUID_VARIABLE, SWITCH_CALL_DIRECTION_INBOUND, SWITCH_CALL_DIRECTION_OUTBOUND, switch_caller_profile_clone(), switch_caller_profile_event_set_data(), switch_channel_add_state_handler(), switch_channel_add_variable_var_check(), switch_channel_clear_flag(), 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_inbound_display, switch_channel_invert_cid(), switch_channel_media_up, switch_channel_outbound_display, 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_step_caller_profile(), 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_core_strdup, switch_epoch_time_now(), SWITCH_EVENT_CHANNEL_DATA, switch_event_create_plain(), switch_event_destroy(), SWITCH_FALSE, 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, and switch_caller_profile::uuid_str.

Referenced by switch_core_standard_on_reset(), switch_ivr_3p_media(), switch_ivr_intercept_session(), switch_ivr_media(), and switch_ivr_originate().

1808 {
1809  switch_core_session_t *originator_session, *originatee_session, *swap_session;
1810  switch_channel_t *originator_channel, *originatee_channel, *swap_channel;
1812  switch_caller_profile_t *originator_cp, *originatee_cp;
1814 
1815  if ((originator_session = switch_core_session_locate(originator_uuid))) {
1816  if ((originatee_session = switch_core_session_locate(originatee_uuid))) {
1817  originator_channel = switch_core_session_get_channel(originator_session);
1818  originatee_channel = switch_core_session_get_channel(originatee_session);
1819 
1820 
1821  if (switch_channel_test_flag(originator_channel, CF_LEG_HOLDING)) {
1822  switch_channel_set_flag(originator_channel, CF_HOLD_ON_BRIDGE);
1823  }
1824 
1825  if (switch_channel_test_flag(originatee_channel, CF_LEG_HOLDING)) {
1826  switch_channel_set_flag(originatee_channel, CF_HOLD_ON_BRIDGE);
1827  }
1828 
1829 
1830  if (switch_channel_direction(originator_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(originator_channel, CF_DIALPLAN)) {
1831  if (!switch_channel_test_flag(originator_channel, CF_RECOVERING_BRIDGE)) {
1832  switch_channel_flip_cid(originator_channel);
1833  }
1834  switch_channel_set_flag(originator_channel, CF_DIALPLAN);
1835  }
1836 
1837  if (switch_channel_down_nosig(originator_channel)) {
1838  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));
1839  switch_core_session_rwunlock(originator_session);
1840  switch_core_session_rwunlock(originatee_session);
1841  return SWITCH_STATUS_FALSE;
1842  }
1843 
1844  if (!switch_channel_media_up(originator_channel)) {
1845  if (switch_channel_media_up(originatee_channel)) {
1846  swap_session = originator_session;
1847  originator_session = originatee_session;
1848  originatee_session = swap_session;
1849 
1850  swap_channel = originator_channel;
1851  originator_channel = originatee_channel;
1852  originatee_channel = swap_channel;
1853  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originatee_session), SWITCH_LOG_WARNING, "reversing order of channels so this will work!\n");
1854  } else {
1855  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_CRIT, "Neither channel is answered, cannot bridge them.\n");
1856  switch_core_session_rwunlock(originator_session);
1857  switch_core_session_rwunlock(originatee_session);
1858  return SWITCH_STATUS_FALSE;
1859  }
1860  }
1861 
1862  if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(originatee_channel, CF_DIALPLAN)) {
1863  switch_channel_clear_flag(originatee_channel, CF_DIALPLAN);
1864  }
1865 
1866  cleanup_proxy_mode_a(originator_session);
1867  cleanup_proxy_mode_a(originatee_session);
1868 
1869  /* override transmit state for originator_channel to bridge to originatee_channel
1870  * install pointer to originatee_session into originator_channel
1871  * set CF_TRANSFER on both channels and change state to CS_SOFT_EXECUTE to
1872  * interrupt anything they are already doing.
1873  * originatee_session will fall asleep and originator_session will bridge to it
1874  */
1875 
1876  switch_channel_set_flag(originator_channel, CF_REDIRECT);
1877  switch_channel_set_flag(originatee_channel, CF_REDIRECT);
1878 
1879 
1880  switch_channel_set_variable(originator_channel, SWITCH_UUID_BRIDGE, switch_core_session_get_uuid(originatee_session));
1887 
1888 
1889  originator_cp = switch_channel_get_caller_profile(originator_channel);
1890  originatee_cp = switch_channel_get_caller_profile(originatee_channel);
1891 
1892 
1893 
1894  if (switch_channel_outbound_display(originator_channel)) {
1895  switch_channel_invert_cid(originator_channel);
1896 
1897  if (switch_channel_direction(originator_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
1898  switch_channel_clear_flag(originatee_channel, CF_BLEG);
1899  }
1900  }
1901 
1902  if (switch_channel_inbound_display(originatee_channel)) {
1903  switch_channel_invert_cid(originatee_channel);
1904 
1905  if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
1906  switch_channel_set_flag(originatee_channel, CF_BLEG);
1907  }
1908 
1909  }
1910 
1911 
1912  switch_channel_set_variable(originatee_channel, "original_destination_number", originatee_cp->destination_number);
1913  switch_channel_set_variable(originatee_channel, "original_caller_id_name", originatee_cp->caller_id_name);
1914  switch_channel_set_variable(originatee_channel, "original_caller_id_number", originatee_cp->caller_id_number);
1915 
1916  switch_channel_set_variable(originator_channel, "original_destination_number", originator_cp->destination_number);
1917  switch_channel_set_variable(originator_channel, "original_caller_id_name", originator_cp->caller_id_name);
1918  switch_channel_set_variable(originator_channel, "original_caller_id_number", originator_cp->caller_id_number);
1919 
1920  switch_channel_step_caller_profile(originatee_channel);
1921  switch_channel_step_caller_profile(originator_channel);
1922 
1923  originator_cp = switch_channel_get_caller_profile(originator_channel);
1924  originatee_cp = switch_channel_get_caller_profile(originatee_channel);
1925 
1926 
1927 #ifdef DEEP_DEBUG_CID
1928  {
1929  switch_event_t *event;
1930 
1932  //switch_channel_event_set_basic_data(originator_channel, event);
1933  switch_caller_profile_event_set_data(originator_cp, "ORIGINATOR", event);
1934  switch_caller_profile_event_set_data(originatee_cp, "ORIGINATEE", event);
1935  DUMP_EVENT(event);
1936  switch_event_destroy(&event);
1937  }
1938  }
1939 #endif
1940 
1941  switch_channel_set_originator_caller_profile(originatee_channel, switch_caller_profile_clone(originatee_session, originator_cp));
1942  switch_channel_set_originatee_caller_profile(originator_channel, switch_caller_profile_clone(originator_session, originatee_cp));
1943 
1944  originator_cp->callee_id_name = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_name);
1945  originator_cp->callee_id_number = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_number);
1946 
1947  originatee_cp->caller_id_name = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_name);
1948  originatee_cp->caller_id_number = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_number);
1949 
1950 #ifdef DEEP_DEBUG_CID
1951  {
1952  switch_event_t *event;
1953 
1955  //switch_channel_event_set_basic_data(originator_channel, event);
1956  switch_caller_profile_event_set_data(originator_cp, "POST-ORIGINATOR", event);
1957  switch_caller_profile_event_set_data(originatee_cp, "POST-ORIGINATEE", event);
1958  DUMP_EVENT(event);
1959  switch_event_destroy(&event);
1960  }
1961  }
1962 #endif
1963 
1964  switch_channel_stop_broadcast(originator_channel);
1965  switch_channel_stop_broadcast(originatee_channel);
1966 
1967  switch_channel_set_flag(originator_channel, CF_TRANSFER);
1968  switch_channel_set_flag(originatee_channel, CF_TRANSFER);
1969 
1970 
1971  switch_channel_clear_flag(originator_channel, CF_ORIGINATING);
1972  switch_channel_clear_flag(originatee_channel, CF_ORIGINATING);
1973 
1974 
1975  originator_cp->transfer_source = switch_core_sprintf(originator_cp->pool,
1976  "%ld:%s:uuid_br:%s", (long)switch_epoch_time_now(NULL), originator_cp->uuid_str,
1977  switch_core_session_get_uuid(originatee_session));
1981 
1982 
1983  originatee_cp->transfer_source = switch_core_sprintf(originatee_cp->pool,
1984  "%ld:%s:uuid_br:%s", (long)switch_epoch_time_now(NULL), originatee_cp->uuid_str,
1985  switch_core_session_get_uuid(originator_session));
1989 
1990  /* change the states and let the chips fall where they may */
1991 
1992  //switch_channel_set_variable(originator_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
1993  //switch_channel_set_variable(originatee_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
1994  switch_channel_clear_state_handler(originator_channel, NULL);
1995  switch_channel_clear_state_handler(originatee_channel, NULL);
1996 
1997 
1998 
2001 
2005 
2008 
2009  state = switch_channel_get_state(originator_channel);
2010  switch_channel_set_state(originator_channel, state == CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE);
2011  state = switch_channel_get_state(originatee_channel);
2012  switch_channel_set_state(originatee_channel, state == CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE);
2013 
2014  status = SWITCH_STATUS_SUCCESS;
2015 
2016  //switch_ivr_bridge_display(originator_session, originatee_session);
2017 
2018  /* release the read locks we have on the channels */
2019  switch_core_session_rwunlock(originator_session);
2020  switch_core_session_rwunlock(originatee_session);
2021 
2022  } else {
2023  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_DEBUG, "originatee uuid %s is not present\n", originatee_uuid);
2024  switch_core_session_rwunlock(originator_session);
2025  }
2026  } else {
2027  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_DEBUG, "originator uuid %s is not present\n", originator_uuid);
2028  }
2029 
2030  return status;
2031 }
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define SWITCH_CHANNEL_SESSION_LOG(x)
Call Specific Data.
Definition: switch_caller.h:73
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
void switch_channel_clear_state_flag(switch_channel_t *channel, switch_channel_flag_t flag)
#define SWITCH_TRANSFER_SOURCE_VARIABLE
Definition: switch_types.h:143
#define switch_channel_stop_broadcast(_channel)
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
Representation of an event.
Definition: switch_event.h:80
static const switch_state_handler_table_t uuid_bridge_state_handlers
switch_caller_profile_t * switch_caller_profile_clone(_In_ switch_core_session_t *session, _In_ switch_caller_profile_t *tocopy)
Clone an existing caller profile object.
void switch_channel_flip_cid(switch_channel_t *channel)
#define switch_channel_outbound_display(_channel)
void switch_channel_set_state_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Set given flag(s) on a given channel to be applied on the next state change.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
void switch_channel_invert_cid(switch_channel_t *channel)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void switch_caller_profile_event_set_data(_In_ switch_caller_profile_t *caller_profile, _In_opt_z_ const char *prefix, _In_ switch_event_t *event)
Add headers to an existing event in regards to a specific profile.
#define switch_channel_inbound_display(_channel)
const char * callee_id_number
Definition: switch_caller.h:89
switch_status_t switch_channel_add_variable_var_check(switch_channel_t *channel, const char *varname, const char *value, switch_bool_t var_check, switch_stack_t stack)
void switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
clear a state handler table from a given channel
#define DUMP_EVENT(_e)
const char * caller_id_name
Definition: switch_caller.h:79
#define SWITCH_BRIDGE_UUID_VARIABLE
Definition: switch_types.h:182
#define switch_channel_down_nosig(_channel)
void switch_channel_set_originator_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
Set the given channel's originator caller profile.
static switch_status_t switch_event_create_plain(switch_event_t **event, switch_event_types_t event_id)
Definition: switch_event.h:385
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_channel_state_t
Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are ...
void switch_channel_step_caller_profile(switch_channel_t *channel)
switch_status_t
Common return values.
#define SWITCH_SIGNAL_BOND_VARIABLE
Definition: switch_types.h:202
void switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
Set the given channel's originatee caller profile.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_channel_set_flag(_c, _f)
switch_call_direction_t switch_channel_direction(switch_channel_t *channel)
static void cleanup_proxy_mode_a(switch_core_session_t *session)
#define SWITCH_TRANSFER_HISTORY_VARIABLE
Definition: switch_types.h:142
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:321
const char * caller_id_number
Definition: switch_caller.h:81
int switch_channel_add_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
add a state handler table to a given channel
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
void switch_event_destroy(switch_event_t **event)
Destroy an event.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
char * switch_core_sprintf(_In_ switch_memory_pool_t *pool, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the pool ...
#define switch_channel_set_variable(_channel, _var, _val)
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
#define switch_channel_media_up(_channel)
const char * callee_id_name
Definition: switch_caller.h:87
#define SWITCH_BRIDGE_CHANNEL_VARIABLE
Definition: switch_types.h:180
#define SWITCH_UUID_BRIDGE
Definition: switch_types.h:227
switch_memory_pool_t * pool
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 1974 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, switch_frame::buflen, switch_file_handle::channels, 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_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_channel_set_variable_printf(), 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_LOG_ERROR, switch_log_printf(), SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, SWITCH_STATUS_FALSE, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_zmalloc.

1976 {
1977  uint32_t score, count = 0, j = 0;
1978  double energy = 0;
1980  int divisor = 0;
1981  uint32_t org_silence_hits = silence_hits;
1982  uint32_t channels;
1983  switch_frame_t *read_frame;
1985  int16_t *data;
1986  uint32_t listening = 0;
1987  int countdown = 0;
1988  switch_codec_t raw_codec = { 0 };
1989  int16_t *abuf = NULL;
1990  switch_frame_t write_frame = { 0 };
1991  switch_file_handle_t fh = { 0 };
1992  int32_t sample_count = 0;
1993  switch_codec_implementation_t read_impl = { 0 };
1994  switch_core_session_get_read_impl(session, &read_impl);
1995 
1996 
1997  if (timeout_ms) {
1998  sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
1999  }
2000 
2001  if (file) {
2002  if (switch_core_file_open(&fh,
2003  file,
2004  read_impl.number_of_channels,
2007  return SWITCH_STATUS_NOTFOUND;
2008  }
2010  write_frame.data = abuf;
2011  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2012  }
2013 
2014 
2015  if (switch_core_codec_init(&raw_codec,
2016  "L16",
2017  NULL,
2018  NULL,
2019  read_impl.actual_samples_per_second,
2020  read_impl.microseconds_per_packet / 1000,
2023 
2024  status = SWITCH_STATUS_FALSE;
2025  goto end;
2026  }
2027 
2028  write_frame.codec = &raw_codec;
2029 
2030  divisor = read_impl.actual_samples_per_second / 8000;
2031  channels = read_impl.number_of_channels;
2032 
2033  switch_core_session_set_read_codec(session, &raw_codec);
2034 
2035  while (switch_channel_ready(channel)) {
2036 
2037  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2038 
2039  if (!SWITCH_READ_ACCEPTABLE(status)) {
2040  break;
2041  }
2042 
2043  if (sample_count) {
2044  sample_count -= raw_codec.implementation->samples_per_packet;
2045  if (sample_count <= 0) {
2046  switch_channel_set_variable(channel, "wait_for_silence_timeout", "true");
2047  switch_channel_set_variable_printf(channel, "wait_for_silence_listenhits", "%d", listening);
2048  switch_channel_set_variable_printf(channel, "wait_for_silence_silence_hits", "%d", silence_hits);
2049  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_ivr_wait_for_silence: TIMEOUT %d\n", countdown);
2050  break;
2051  }
2052  }
2053 
2054  if (abuf) {
2056 
2057  if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
2058  break;
2059  }
2060 
2061  write_frame.samples = (uint32_t) olen;
2062  write_frame.datalen = (uint32_t) (olen * sizeof(int16_t) * fh.channels);
2063  if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
2064  break;
2065  }
2066  }
2067 
2068  if (countdown) {
2069  if (!--countdown) {
2070  switch_channel_set_variable(channel, "wait_for_silence_timeout", "false");
2071  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_ivr_wait_for_silence: SILENCE DETECTED\n");
2072  break;
2073  } else {
2074  continue;
2075  }
2076  }
2077 
2078  data = (int16_t *) read_frame->data;
2079 
2080  for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
2081  energy += abs(data[j++]);
2082  j += channels;
2083  }
2084 
2085  score = (uint32_t) (energy / (read_frame->samples / divisor));
2086 
2087  if (score >= thresh) {
2088  listening++;
2089  }
2090 
2091  if (listening > listen_hits && score < thresh) {
2092  if (!--silence_hits) {
2093  countdown = 25;
2094  }
2095  } else {
2096  silence_hits = org_silence_hits;
2097  }
2098  }
2099 
2101  switch_core_codec_destroy(&raw_codec);
2102 
2103  end:
2104 
2105  if (abuf) {
2106 
2108  free(abuf);
2109  }
2110 
2111  return status;
2112 }
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
#define SWITCH_CHANNEL_SESSION_LOG(x)
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
#define switch_core_file_open(_fh, _file_path, _channels, _rate, _flags, _pool)
Open a media file using file format modules.
Definition: switch_core.h:1865
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
switch_status_t switch_core_session_set_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec)
Assign the read codec to a given session.
switch_status_t switch_core_file_close(_In_ switch_file_handle_t *fh)
Close an open file handle.
#define switch_channel_ready(_channel)
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
switch_status_t switch_core_file_read(_In_ switch_file_handle_t *fh, void *data, switch_size_t *len)
Read media from a file handle.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:59
uint32_t datalen
Definition: switch_frame.h:57
#define switch_zmalloc(ptr, len)
An abstraction of a data frame.
Definition: switch_frame.h:43
uintptr_t switch_size_t
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
switch_status_t
Common return values.
uint32_t samples
Definition: switch_frame.h:61
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_channel_set_variable(_channel, _var, _val)
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
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
sessionthe current session to play sound to and collect digits
min_digitsthe fewest digits allowed for the response to be valid
max_digitsthe max number of digits to accept
max_triesnumber of times to replay the sound and capture digits
timeouttime to wait for input (this is per iteration, so total possible time = max_tries * (timeout + audio playback length)
valid_terminatorsfor input that can include # or * (useful for variable length prompts)
audio_filefile to play
bad_input_audio_filefile to play if the input from the user was invalid
var_namevariable name to put results in
digit_buffervariable digits captured will be put back into (empty if capture failed)
digit_buffer_lengthlength of the buffer for digits (should be the same or larger than max_digits)
digits_regexthe 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 2239 of file switch_ivr_play_say.c.

References memset(), 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_DEBUG1, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, switch_mprintf(), SWITCH_READ_TERMINATOR_USED_VARIABLE, switch_regex_match(), switch_safe_free, 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(), and switch_ivr_menu_execute().

2253 {
2255 
2256  while (switch_channel_ready(channel) && max_tries) {
2257  switch_status_t status;
2258 
2259  memset(digit_buffer, 0, digit_buffer_length);
2260 
2261  status = switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name,
2262  digit_buffer, digit_buffer_length, timeout, valid_terminators, digit_timeout);
2263 
2264  if (status == SWITCH_STATUS_RESTART) {
2265  return status;
2266  }
2267 
2268  if (status == SWITCH_STATUS_TIMEOUT && strlen(digit_buffer) >= min_digits) {
2269  status = SWITCH_STATUS_SUCCESS;
2270  }
2271 
2272  if ((min_digits == 0) && (strlen(digit_buffer) == 0) && switch_channel_get_variable(channel, SWITCH_READ_TERMINATOR_USED_VARIABLE) != 0)
2273  {
2274  return SWITCH_STATUS_SUCCESS;
2275  }
2276 
2277  if (!(status == SWITCH_STATUS_TOO_SMALL && strlen(digit_buffer) == 0)) {
2278  if (status == SWITCH_STATUS_SUCCESS) {
2279  if (!zstr(digit_buffer)) {
2280  char *invalid_var = NULL;
2281  if (zstr(digits_regex)) {
2282  return SWITCH_STATUS_SUCCESS;
2283  }
2284  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "Test Regex [%s][%s]\n", digit_buffer, digits_regex);
2285 
2286  invalid_var = switch_mprintf("%s_invalid", var_name);
2287  if (switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) {
2288  switch_channel_set_variable(channel, invalid_var, NULL);
2289  switch_safe_free(invalid_var);
2290  return SWITCH_STATUS_SUCCESS;
2291  } else {
2292  switch_channel_set_variable(channel, var_name, NULL);
2293  switch_channel_set_variable(channel, invalid_var, digit_buffer);
2294  switch_safe_free(invalid_var);
2295  }
2296  }
2297  }
2298  }
2299 
2300  if (!switch_channel_ready(channel)) {
2301  break;
2302  }
2303 
2304  switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL);
2305  max_tries--;
2306  }
2307 
2308  memset(digit_buffer, 0, digit_buffer_length);
2309 
2310  /* If we get here then check for transfer-on-failure ext/dp/context */
2311  /* split this arg on spaces to get ext, dp, and context */
2312 
2313  if (!zstr(transfer_on_failure)) {
2314  const char *failure_ext = NULL;
2315  const char *failure_dialplan = NULL;
2316  const char *failure_context = NULL;
2317  char *target[4];
2318  char *mydata = switch_core_session_strdup(session, transfer_on_failure);
2319  int argc;
2320 
2321  argc = switch_separate_string(mydata, ' ', target, (sizeof(target) / sizeof(target[0])));
2322 
2323  if ( argc < 1 ) {
2324  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,"Bad target for PAGD failure: [%s]\n", transfer_on_failure);
2325  return SWITCH_STATUS_FALSE;
2326  }
2327 
2328  if ( argc > 0 ) {
2329  failure_ext = target[0];
2330  }
2331 
2332  if ( argc > 1 ) {
2333  failure_dialplan = target[1];
2334  }
2335 
2336  if ( argc > 2 ) {
2337  failure_context = target[2];
2338  }
2339 
2341  "PAGD failure! Transfer to: %s / %s / %s\n", failure_ext, failure_dialplan, failure_context);
2342 
2343  switch_ivr_session_transfer(session,failure_ext, failure_dialplan, failure_context);
2344  return SWITCH_STATUS_FALSE;
2345  }
2346 
2347  return SWITCH_STATUS_FALSE;
2348 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_ivr_read(switch_core_session_t *session, uint32_t min_digits, uint32_t max_digits, const char *prompt_audio_file, const char *var_name, char *digit_buffer, switch_size_t digit_buffer_length, uint32_t timeout, const char *valid_terminators, uint32_t digit_timeout)
#define switch_channel_ready(_channel)
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
#define zstr(x)
Definition: switch_utils.h:281
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.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
#define switch_channel_get_variable(_c, _v)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
#define SWITCH_READ_TERMINATOR_USED_VARIABLE
Definition: switch_types.h:128
switch_status_t
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
#define switch_channel_set_variable(_channel, _var, _val)
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
memset(buf, 0, buflen)
switch_status_t switch_regex_match(const char *target, const char *expression)
Function to evaluate an expression against a string.
Definition: switch_regex.c:295