RTS API Documentation  1.10.11
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, const char *file, uint32_t limit, switch_file_handle_t *fh)
 Record a session to disk. More...
 
switch_status_t switch_ivr_record_session_event (switch_core_session_t *session, const char *file, uint32_t limit, switch_file_handle_t *fh, switch_event_t *variables)
 
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_detect_audio (switch_core_session_t *session, uint32_t thresh, uint32_t audio_hits, uint32_t timeout_ms, const char *file)
 
switch_status_t switch_ivr_detect_silence (switch_core_session_t *session, uint32_t thresh, uint32_t silence_hits, uint32_t timeout_ms, const char *file)
 
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_ivr_record_file_event (_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, switch_event_t *vars)
 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, const 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, const 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, switch_dial_handle_t *dh)
 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, switch_dial_handle_list_t *hl)
 
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_bridge_bleg (switch_core_session_t *session, switch_core_session_t *peer_session, uint32_t max_wait_ms)
 Bridge leaving b-leg in the control of another thread. Call from b-leg first then call switch_ivr_multi_threaded_bridge on a-leg and b-leg. 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...
 
void switch_ivr_check_hold (switch_core_session_t *session)
 
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

◆ switch_ivr_digit_stream_parser_t

Definition at line 712 of file switch_ivr.h.

◆ switch_ivr_digit_stream_t

Definition at line 714 of file switch_ivr.h.

Function Documentation

◆ switch_ivr_3p_media()

switch_status_t switch_ivr_3p_media ( const char *  uuid,
switch_media_flag_t  flags 
)

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

1664 {
1665  const char *other_uuid = NULL;
1666  switch_channel_t *channel, *other_channel = NULL;
1667  switch_core_session_t *session, *other_session;
1668  switch_core_session_message_t msg = { 0 };
1670  uint8_t swap = 0;
1671  //switch_frame_t *read_frame = NULL;
1672 
1674  msg.from = __FILE__;
1675 
1676  if ((session = switch_core_session_locate(uuid))) {
1677  channel = switch_core_session_get_channel(session);
1678 
1680  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Operation is invalid\n");
1682  return SWITCH_STATUS_INUSE;
1683  }
1684 
1686 
1687  if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
1688  swap = 1;
1689  }
1690 
1691 
1692  status = SWITCH_STATUS_SUCCESS;
1693 
1694  /* If we had early media in bypass mode before, it is no longer relevant */
1695  if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
1696  switch_core_session_message_t msg2 = { 0 };
1697 
1699  msg2.from = __FILE__;
1700  switch_core_session_receive_message(session, &msg2);
1701  }
1702 
1703  if ((flags & SMF_REPLYONLY_A)) {
1704  msg.numeric_arg = 1;
1705  }
1706 
1708 
1710  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't re-establsh media on %s\n", switch_channel_get_name(channel));
1713  return SWITCH_STATUS_GENERR;
1714  }
1715 
1716  if ((flags & SMF_REPLYONLY_B)) {
1717  msg.numeric_arg = 1;
1718  } else {
1719  msg.numeric_arg = 0;
1720  }
1721 
1722  if ((flags & SMF_IMMEDIATE)) {
1724  switch_yield(250000);
1725  } else {
1726  switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1727  switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1728  switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1730  //switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1731  }
1732 
1733  if ((flags & SMF_REBRIDGE)
1735  && (other_session = switch_core_session_locate(other_uuid))) {
1736 
1737  other_channel = switch_core_session_get_channel(other_session);
1738  switch_assert(other_channel != NULL);
1739 
1741  switch_channel_set_variable(other_channel, "rtp_secure_media", "optional");
1742 
1743  switch_core_session_receive_message(other_session, &msg);
1744  switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1745  switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1746  switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1747  switch_channel_wait_for_flag(other_channel, CF_3P_MEDIA_REQUESTED, SWITCH_FALSE, 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 
1758 
1759  if (other_channel) {
1760  if (swap) {
1761  switch_ivr_uuid_bridge(other_uuid, uuid);
1762  } else {
1763  switch_ivr_uuid_bridge(uuid, other_uuid);
1764  }
1765  switch_channel_wait_for_flag(channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
1766  switch_channel_wait_for_flag(other_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
1767  }
1768  }
1769 
1770  return status;
1771 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:202
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
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:179
_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:998
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:1247
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:932
#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_ivr_3p_nomedia()

switch_status_t switch_ivr_3p_nomedia ( const char *  uuid,
switch_media_flag_t  flags 
)

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

1882 {
1883  const char *other_uuid;
1884  switch_channel_t *channel, *other_channel = NULL;
1885  switch_core_session_t *session, *other_session = NULL;
1886  switch_core_session_message_t msg = { 0 };
1888  uint8_t swap = 0;
1889 
1891  msg.from = __FILE__;
1892 
1893  if ((session = switch_core_session_locate(uuid))) {
1894  status = SWITCH_STATUS_SUCCESS;
1895  channel = switch_core_session_get_channel(session);
1896 
1897  if (switch_channel_test_flag(channel, CF_MEDIA_TRANS) || (!(flags & SMF_FORCE) && switch_channel_test_flag(channel, CF_PROXY_MODE))) {
1898  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Operation is invalid\n");
1900  return SWITCH_STATUS_INUSE;
1901  }
1902 
1904 
1905  if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
1906  swap = 1;
1907  }
1908 
1909  if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_PROXY_MODE)) {
1910  if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
1911  (other_session = switch_core_session_locate(other_uuid))) {
1912  other_channel = switch_core_session_get_channel(other_session);
1913 
1916 
1917  switch_channel_set_flag(other_channel, CF_RESET);
1918  switch_channel_set_flag(other_channel, CF_REDIRECT);
1919 
1922  switch_core_session_receive_message(session, &msg);
1923 
1924  if (!switch_core_session_in_thread(session)) {
1926  }
1927 
1928  switch_channel_set_state(other_channel, CS_PARK);
1929 
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 
1936 
1937  if (!switch_core_session_in_thread(session)) {
1938  switch_channel_wait_for_state(channel, NULL, CS_PARK);
1939  }
1940 
1941  switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1942  switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1944 
1948 
1949 
1950  switch_core_session_receive_message(other_session, &msg);
1951  switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1952  switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1954  }
1955 
1956  if (other_channel) {
1957  if (swap) {
1958  switch_ivr_signal_bridge(other_session, session);
1959  } else {
1960  switch_ivr_signal_bridge(session, other_session);
1961  }
1962 
1963  if (switch_core_session_in_thread(session)) {
1964  switch_yield(100000);
1965  } else {
1966  switch_channel_wait_for_state(other_channel, channel, CS_HIBERNATE);
1967  }
1968 
1969  if (!switch_core_session_in_thread(session)) {
1970  switch_channel_wait_for_state(channel, other_channel, CS_HIBERNATE);
1971  }
1972  switch_core_session_rwunlock(other_session);
1973  }
1974  }
1975 
1978  }
1979 
1980 
1981 
1982  return status;
1983 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
#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:179
_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:998
#define switch_channel_get_variable(_c, _v)
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:200
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
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:197
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:932
#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_ivr_activate_unicast()

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 404 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().

408 {
410  switch_unicast_conninfo_t *conninfo = switch_core_session_alloc(session, sizeof(*conninfo));
411  switch_codec_t *read_codec;
412 
413  switch_assert(conninfo != NULL);
414 
415  conninfo->local_ip = switch_core_session_strdup(session, local_ip);
416  conninfo->local_port = local_port;
417 
418  conninfo->remote_ip = switch_core_session_strdup(session, remote_ip);
419  conninfo->remote_port = remote_port;
420  conninfo->session = session;
421 
422  if (!strcasecmp(transport, "udp")) {
423  conninfo->type = AF_INET;
424  conninfo->transport = SOCK_DGRAM;
425  } else if (!strcasecmp(transport, "tcp")) {
426  conninfo->type = AF_INET;
427  conninfo->transport = SOCK_STREAM;
428  } else {
429  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid transport %s\n", transport);
430  goto fail;
431  }
432 
433  if (flags) {
434  if (strstr(flags, "native")) {
435  switch_set_flag(conninfo, SUF_NATIVE);
436  }
437  }
438 
440 
441  read_codec = switch_core_session_get_read_codec(session);
442 
443  if (!switch_test_flag(conninfo, SUF_NATIVE)) {
444  if (switch_core_codec_init(&conninfo->read_codec,
445  "L16",
446  NULL,
447  NULL,
449  read_codec->implementation->microseconds_per_packet / 1000,
453  "Raw Codec Activation Success L16@%uhz 1 channel %dms\n",
455  } else {
456  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n",
458  goto fail;
459  }
460  }
461 
462  conninfo->write_frame.data = conninfo->write_frame_data;
463  conninfo->write_frame.buflen = sizeof(conninfo->write_frame_data);
464  conninfo->write_frame.codec = switch_test_flag(conninfo, SUF_NATIVE) ? read_codec : &conninfo->read_codec;
465 
466  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "connect %s:%d->%s:%d\n",
467  conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
468 
469  if (switch_sockaddr_info_get(&conninfo->local_addr,
470  conninfo->local_ip, SWITCH_UNSPEC, conninfo->local_port, 0,
472  goto fail;
473  }
474 
475  if (switch_sockaddr_info_get(&conninfo->remote_addr,
476  conninfo->remote_ip, SWITCH_UNSPEC, conninfo->remote_port, 0,
478  goto fail;
479  }
480 
481  if (switch_socket_create(&conninfo->socket, AF_INET, SOCK_DGRAM, 0, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
482  if (switch_socket_bind(conninfo->socket, conninfo->local_addr) != SWITCH_STATUS_SUCCESS) {
483  goto fail;
484  }
485  } else {
486  goto fail;
487  }
488 
489  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Created unicast connection %s:%d->%s:%d\n",
490  conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
491  switch_channel_set_private(channel, "unicast", conninfo);
494  return SWITCH_STATUS_SUCCESS;
495 
496  fail:
497 
498  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure creating unicast connection %s:%d->%s:%d\n",
499  conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port);
500  return SWITCH_STATUS_FALSE;
501 }
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:700
switch_status_t switch_socket_bind(switch_socket_t *sock, switch_sockaddr_t *sa)
Definition: switch_apr.c:742
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:56
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:70
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:293
#define switch_set_flag_locked(obj, flag)
Set a flag on an arbitrary object while locked.
Definition: switch_utils.h:707
#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:1693
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:727
#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:696
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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:719
#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:839
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.

◆ switch_ivr_bg_media()

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 2121 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().

2122 {
2125  media_job_t *job;
2126 
2128  td = switch_core_alloc(pool, sizeof(*td));
2129  job = switch_core_alloc(pool, sizeof(*job));
2130  td->func = media_thread_run;
2131  job->pool = pool;
2132  job->uuid = switch_core_strdup(pool, uuid);
2133  job->flags = flags;
2134  job->on = on;
2135  job->is3p = is3p;
2136  job->delay = delay;
2137  td->obj = job;
2138  td->pool = pool;
2140 
2141 }
const char * uuid
Definition: switch_ivr.c:2088
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:633
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
switch_memory_pool_t * pool
switch_memory_pool_t * pool
Definition: switch_core.h:71
switch_memory_pool_t * pool
Definition: switch_ivr.c:2087
switch_bool_t on
Definition: switch_ivr.c:2090
uint32_t delay
Definition: switch_ivr.c:2092
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
switch_thread_start_t func
Definition: switch_core.h:67
static void *SWITCH_THREAD_FUNC media_thread_run(switch_thread_t *thread, void *obj)
Definition: switch_ivr.c:2095
struct fspr_pool_t switch_memory_pool_t
switch_media_flag_t flags
Definition: switch_ivr.c:2089
switch_bool_t is3p
Definition: switch_ivr.c:2091
switch_status_t switch_thread_pool_launch_thread(switch_thread_data_t **tdp)

◆ switch_ivr_bridge_bleg()

switch_status_t switch_ivr_bridge_bleg ( switch_core_session_t session,
switch_core_session_t peer_session,
uint32_t  max_wait_ms 
)

Bridge leaving b-leg in the control of another thread. Call from b-leg first then call switch_ivr_multi_threaded_bridge on a-leg and b-leg.

Parameters
sessionb-leg session
Returns
SWITCH_STATUS_SUCCESS if all is well

Definition at line 1073 of file switch_ivr_bridge.c.

References audio_bridge_on_exchange_media(), CF_ARRANGED_BRIDGE, CF_TRANSFER, switch_assert, switch_channel_clear_flag(), switch_channel_set_flag, switch_channel_test_flag(), switch_channel_wait_for_flag(), switch_core_session_get_channel(), SWITCH_FALSE, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, uuid_bridge_on_hibernate(), uuid_bridge_on_reset(), and uuid_bridge_on_soft_execute().

1074 {
1075  switch_channel_t *channel;
1076  switch_channel_t *peer_channel = NULL;
1078 
1079  switch_assert(session);
1080  channel = switch_core_session_get_channel(session);
1081 
1083 
1084  if (peer_session) {
1085  peer_channel = switch_core_session_get_channel(peer_session);
1086  }
1087 
1088  status = switch_channel_wait_for_flag(channel, CF_ARRANGED_BRIDGE, SWITCH_FALSE, max_wait_ms, peer_channel);
1089 
1090  if (status == SWITCH_STATUS_FALSE) return status;
1091 
1094  return SWITCH_STATUS_FALSE;
1095  } else {
1097  if (!switch_channel_test_flag(channel, CF_TRANSFER)) {
1099  }
1100  }
1101 
1102  return SWITCH_STATUS_SUCCESS;
1103 }
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.
static switch_status_t audio_bridge_on_exchange_media(switch_core_session_t *session)
switch_status_t
Common return values.
#define switch_channel_set_flag(_c, _f)
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)

◆ switch_ivr_bridge_display()

void switch_ivr_bridge_display ( switch_core_session_t session,
switch_core_session_t peer_session 
)

Definition at line 336 of file switch_ivr_bridge.c.

References send_display().

Referenced by audio_bridge_thread(), and switch_ivr_signal_bridge().

337 {
338 
339  send_display(session, peer_session);
340  send_display(peer_session, session);
341 
342 }
static void send_display(switch_core_session_t *session, switch_core_session_t *peer_session)

◆ switch_ivr_broadcast()

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 5654 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 audio_bridge_thread(), 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().

5655 {
5656  switch_channel_t *channel;
5657  switch_core_session_t *session;
5658  switch_event_t *event;
5659  switch_core_session_t *other_session = NULL;
5660  const char *other_uuid = NULL;
5661  char *app = "playback";
5662  char *cause = NULL;
5663  char *mypath;
5664  char *p;
5665  int app_flags = 0, nomedia = 0;
5666 
5668 
5669  if (!(session = switch_core_session_locate(uuid))) {
5670  return SWITCH_STATUS_FALSE;
5671  }
5672 
5673  channel = switch_core_session_get_channel(session);
5674 
5675  mypath = strdup(path);
5676  switch_assert(mypath);
5677 
5678  if ((p = strchr(mypath, ':')) && *(p + 1) == ':') {
5679  app = mypath;
5680  *p++ = '\0';
5681  *p++ = '\0';
5682  path = p;
5683  }
5684 
5685  if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
5686  nomedia = 1;
5688  }
5689 
5690  if ((cause = strchr(app, '!'))) {
5691  *cause++ = '\0';
5692  if (!*cause) {
5693  cause = "normal_clearing";
5694  }
5695  }
5696 
5697  if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_partner_uuid(channel))
5698  && (other_session = switch_core_session_locate(other_uuid))) {
5699  if ((flags & SMF_EXEC_INLINE)) {
5700  switch_core_session_execute_application_get_flags(other_session, app, path, &app_flags);
5701  nomedia = 0;
5702  } else {
5703  switch_core_session_get_app_flags(app, &app_flags);
5705  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
5706  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
5707  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path);
5708  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
5709 
5710  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);
5711 
5712  if ((flags & SMF_LOOP)) {
5713  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1);
5714  }
5715 
5716  if ((flags & SMF_HOLD_BLEG)) {
5717  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true");
5718  }
5719 
5720  switch_core_session_queue_private_event(other_session, &event, (flags & SMF_PRIORITY));
5721  }
5722  }
5723 
5724  switch_core_session_rwunlock(other_session);
5725  other_session = NULL;
5726  }
5727 
5728  if ((app_flags & SAF_MEDIA_TAP)) {
5729  nomedia = 0;
5730  }
5731 
5732  if ((flags & SMF_ECHO_ALEG)) {
5733  if ((flags & SMF_EXEC_INLINE)) {
5735  } else {
5737  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
5738  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
5739  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path);
5740  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
5741  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);
5742 
5743  if ((flags & SMF_LOOP)) {
5744  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1);
5745  }
5746  if ((flags & SMF_HOLD_BLEG)) {
5747  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true");
5748  }
5749 
5750  switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY));
5751 
5752  if (nomedia)
5754  }
5755  }
5756  }
5757 
5758  if (cause) {
5760  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
5761  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", "hangup");
5762  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", cause);
5763  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true");
5764  switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY));
5765  }
5766  }
5767 
5769  switch_safe_free(mypath);
5770 
5771  return SWITCH_STATUS_SUCCESS;
5772 }
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&#39;s remote end.
Definition: switch_ivr.c:1773
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:1129
_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:885
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
const char *const const char *const path
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&#39;s uuid.
Definition: switch_core.h:932
#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:384
#define switch_channel_set_flag(_c, _f)
#define switch_assert(expr)

◆ switch_ivr_broadcast_in_thread()

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

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

4541 {
4543  switch_threadattr_t *thd_attr = NULL;
4545  bch_t *bch;
4546 
4547  switch_assert(session);
4548 
4549  pool = switch_core_session_get_pool(session);
4550 
4551  bch = switch_core_session_alloc(session, sizeof(*bch));
4552  bch->session = session;
4553  bch->app = app;
4554  bch->flags = flags;
4555 
4556 
4557  switch_threadattr_create(&thd_attr, pool);
4558  switch_threadattr_detach_set(thd_attr, 1);
4560  switch_thread_create(&thread, thd_attr, bcast_thread, bch, pool);
4561 }
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:683
switch_memory_pool_t * pool
const char * app
static switch_thread_t * thread
Definition: switch_log.c:486
switch_status_t switch_threadattr_detach_set(switch_threadattr_t *attr, int32_t on)
Definition: switch_apr.c:678
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:584
switch_core_session_t * session
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session&#39;s pool.
Definition: switch_core.h:696
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:665
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:698
struct fspr_pool_t switch_memory_pool_t
#define switch_assert(expr)
struct fspr_thread_t switch_thread_t
Definition: switch_apr.h:941
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.

◆ switch_ivr_check_hold()

void switch_ivr_check_hold ( switch_core_session_t session)

Definition at line 2143 of file switch_ivr.c.

References CC_MUTE_VIA_MEDIA_STREAM, CF_ANSWERED, CF_HOLD, switch_core_session_message::from, switch_core_session_message::message_id, SDP_TYPE_REQUEST, switch_channel_test_cap(), switch_channel_test_flag(), switch_core_media_set_smode(), switch_core_session_get_channel(), switch_core_session_media_flow(), switch_core_session_receive_message, switch_ivr_unhold(), SWITCH_MEDIA_FLOW_SENDRECV, SWITCH_MEDIA_TYPE_AUDIO, and SWITCH_MESSAGE_INDICATE_MEDIA_RENEG.

Referenced by switch_ivr_session_transfer(), and switch_ivr_uuid_bridge().

2144 {
2146 
2149  switch_core_session_message_t msg = { 0 };
2150 
2152  msg.from = __FILE__;
2153 
2155  switch_core_session_receive_message(session, &msg);
2156  }
2157 
2158  if (switch_channel_test_flag(channel, CF_HOLD)) {
2159  switch_ivr_unhold(session);
2160  }
2161 }
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
void switch_core_media_set_smode(switch_core_session_t *session, switch_media_type_t type, switch_media_flow_t smode, switch_sdp_type_t sdp_type)
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:179
_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:1247
uint32_t switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap)
switch_media_flow_t switch_core_session_media_flow(switch_core_session_t *session, switch_media_type_t type)
switch_status_t switch_ivr_unhold(switch_core_session_t *session)
Signal the session with a protocol specific unhold message.
Definition: switch_ivr.c:1603

◆ switch_ivr_clear_speech_cache()

void switch_ivr_clear_speech_cache ( switch_core_session_t session)

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

3009 {
3010  cached_speech_handle_t *cache_obj = NULL;
3012 
3015  if (cache_obj->timer.interval) {
3016  switch_core_timer_destroy(&cache_obj->timer);
3017  }
3018  if (cache_obj->sh.speech_interface) {
3019  switch_core_speech_close(&cache_obj->sh, &flags);
3020  }
3021  switch_core_codec_destroy(&cache_obj->codec);
3023  }
3024 }
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:189
_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_ivr_collect_digits_callback()

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 1225 of file switch_ivr.c.

References arg_recursion_check_start, arg_recursion_check_stop, switch_input_args_t::buf, switch_input_args_t::buflen, CF_BREAK, CF_SERVICE, switch_dtmf_t::digit, switch_input_args_t::dmachine, switch_input_args_t::input_callback, switch_input_args_t::read_frame_callback, 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_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, and switch_input_args_t::user_data.

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

1227 {
1230  switch_time_t abs_started = 0, digit_started = 0;
1231  uint32_t abs_elapsed = 0, digit_elapsed = 0;
1232 
1233  if (!args) {
1234  return SWITCH_STATUS_GENERR;
1235  }
1236 
1238 
1239  if (abs_timeout) {
1240  abs_started = switch_micro_time_now();
1241  }
1242  if (digit_timeout) {
1243  digit_started = switch_micro_time_now();
1244  }
1245 
1246  while (switch_channel_ready(channel)) {
1247  switch_frame_t *read_frame = NULL;
1248  switch_event_t *event;
1249  switch_dtmf_t dtmf = { 0 };
1250 
1251  if (switch_channel_test_flag(channel, CF_BREAK)) {
1253  status = SWITCH_STATUS_BREAK;
1254  break;
1255  }
1256 
1257  if (abs_timeout) {
1258  abs_elapsed = (uint32_t) ((switch_micro_time_now() - abs_started) / 1000);
1259  if (abs_elapsed >= abs_timeout) {
1260  status = SWITCH_STATUS_TIMEOUT;
1261  break;
1262  }
1263  }
1264  if (digit_timeout) {
1265  digit_elapsed = (uint32_t) ((switch_micro_time_now() - digit_started) / 1000);
1266  if (digit_elapsed >= digit_timeout) {
1267  status = SWITCH_STATUS_TIMEOUT;
1268  break;
1269  }
1270  }
1271 
1272 
1273  switch_ivr_parse_all_events(session);
1274 
1275 
1276  if (switch_channel_has_dtmf(channel)) {
1277  if (!args->input_callback && !args->buf && !args->dmachine) {
1278  status = SWITCH_STATUS_BREAK;
1279  break;
1280  }
1281  switch_channel_dequeue_dtmf(channel, &dtmf);
1282 
1283  if (args->dmachine) {
1284  char ds[2] = {dtmf.digit, '\0'};
1285  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
1286  break;
1287  }
1288  }
1289 
1290  if (args->input_callback) {
1291  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
1292  }
1293 
1294  if (digit_timeout) {
1295  digit_started = switch_micro_time_now();
1296  }
1297  }
1298 
1301  if (args->input_callback) {
1302  ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
1303  }
1304  if (ostatus != SWITCH_STATUS_SUCCESS) {
1305  status = ostatus;
1306  }
1307  switch_event_destroy(&event);
1308  }
1309 
1310  if (status != SWITCH_STATUS_SUCCESS) {
1311  break;
1312  }
1313 
1314  if (switch_channel_test_flag(channel, CF_SERVICE)) {
1315  switch_cond_next();
1316  } else {
1317  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1318  }
1319 
1320  if (!SWITCH_READ_ACCEPTABLE(status)) {
1321  break;
1322  }
1323 
1324  if (args && args->dmachine) {
1325  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1326  break;
1327  }
1328  }
1329 
1330  if (read_frame && args && (args->read_frame_callback)) {
1331  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
1332  break;
1333  }
1334  }
1335  }
1336 
1338 
1339  return status;
1340 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
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:913
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:54
#define arg_recursion_check_start(_args)
void switch_cond_next(void)
Definition: switch_time.c:658
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)
switch_ivr_dmachine_t * dmachine

◆ switch_ivr_collect_digits_count()

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 1342 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().

1348 {
1349  switch_size_t i = 0, x = strlen(buf);
1352  switch_time_t started = 0, digit_started = 0;
1353  uint32_t abs_elapsed = 0, digit_elapsed = 0;
1354  uint32_t eff_timeout = 0;
1355  switch_frame_t write_frame = { 0 };
1356  unsigned char *abuf = NULL;
1357  switch_codec_implementation_t imp = { 0 };
1358  switch_codec_t codec = { 0 };
1359  int sval = 0;
1360  const char *var;
1361 
1362 
1363  if (x >= buflen || x >= maxdigits) {
1364  return SWITCH_STATUS_FALSE;
1365  }
1366 
1367  if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
1368  switch_core_session_get_read_impl(session, &imp);
1369 
1370  if (switch_core_codec_init(&codec,
1371  "L16",
1372  NULL,
1373  NULL,
1374  imp.samples_per_second,
1375  imp.microseconds_per_packet / 1000,
1376  imp.number_of_channels,
1379  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
1381  return SWITCH_STATUS_FALSE;
1382  }
1383 
1384 
1385  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
1387 
1388  write_frame.codec = &codec;
1390  write_frame.data = abuf;
1391  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
1392  write_frame.datalen = imp.decoded_bytes_per_packet;
1393  write_frame.samples = write_frame.datalen / sizeof(int16_t);
1394  }
1395 
1396  if (terminator != NULL) {
1397  *terminator = '\0';
1398  }
1399 
1400  if (!zstr(terminators)) {
1401  for (i = 0; i < x; i++) {
1402  if (strchr(terminators, buf[i]) && terminator != NULL) {
1403  *terminator = buf[i];
1404  buf[i] = '\0';
1405  switch_safe_free(abuf);
1406  return SWITCH_STATUS_SUCCESS;
1407  }
1408  }
1409  }
1410 
1411  if (abs_timeout) {
1412  started = switch_micro_time_now();
1413  }
1414 
1415  if (digit_timeout && first_timeout) {
1416  eff_timeout = first_timeout;
1417  } else if (digit_timeout && !first_timeout) {
1418  eff_timeout = digit_timeout;
1419  } else if (first_timeout) {
1420  digit_timeout = eff_timeout = first_timeout;
1421  }
1422 
1423 
1424  if (eff_timeout) {
1425  digit_started = switch_micro_time_now();
1426  }
1427 
1428  while (switch_channel_ready(channel)) {
1429  switch_frame_t *read_frame;
1430 
1431  if (abs_timeout) {
1432  abs_elapsed = (uint32_t) ((switch_micro_time_now() - started) / 1000);
1433  if (abs_elapsed >= abs_timeout) {
1434  status = SWITCH_STATUS_TIMEOUT;
1435  break;
1436  }
1437  }
1438 
1439 
1440  switch_ivr_parse_all_events(session);
1441 
1442 
1443 
1444  if (eff_timeout) {
1445  digit_elapsed = (uint32_t) ((switch_micro_time_now() - digit_started) / 1000);
1446 
1447  if (digit_elapsed >= eff_timeout) {
1448  status = SWITCH_STATUS_TIMEOUT;
1449  break;
1450  }
1451  }
1452 
1453  if (switch_channel_has_dtmf(channel)) {
1454  switch_dtmf_t dtmf = { 0 };
1455  switch_size_t y;
1456 
1457  if (eff_timeout) {
1458  eff_timeout = digit_timeout;
1459  digit_started = switch_micro_time_now();
1460  }
1461 
1462  for (y = 0; y <= maxdigits; y++) {
1463  if (switch_channel_dequeue_dtmf(channel, &dtmf) != SWITCH_STATUS_SUCCESS) {
1464  break;
1465  }
1466 
1467  if (!zstr(terminators) && strchr(terminators, dtmf.digit) && terminator != NULL) {
1468  *terminator = dtmf.digit;
1469  switch_safe_free(abuf);
1470  return SWITCH_STATUS_SUCCESS;
1471  }
1472 
1473 
1474  buf[x++] = dtmf.digit;
1475  buf[x] = '\0';
1476 
1477  if (x >= buflen || x >= maxdigits) {
1478  switch_safe_free(abuf);
1479  return SWITCH_STATUS_SUCCESS;
1480  }
1481  }
1482  }
1483 
1484  if (switch_channel_test_flag(channel, CF_SERVICE)) {
1485  switch_cond_next();
1486  } else {
1487  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1488  if (!SWITCH_READ_ACCEPTABLE(status)) {
1489  break;
1490  }
1491 
1492  if (write_frame.data) {
1493  switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, imp.number_of_channels, sval);
1494  switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
1495  }
1496 
1497  }
1498  }
1499 
1500  if (write_frame.codec) {
1501  switch_core_codec_destroy(&codec);
1502  }
1503 
1504  switch_safe_free(abuf);
1505 
1506  return status;
1507 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:590
#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:913
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:56
#define zstr(x)
Definition: switch_utils.h:314
#define SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE
Definition: switch_types.h:131
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:70
switch_byte_t switch_byte_t * buf
uint32_t datalen
Definition: switch_frame.h:68
#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:885
An abstraction of a data frame.
Definition: switch_frame.h:54
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:1693
void switch_cond_next(void)
Definition: switch_time.c:658
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:72
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)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.

◆ switch_ivr_deactivate_unicast()

switch_status_t switch_ivr_deactivate_unicast ( switch_core_session_t session)

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

372 {
374  switch_unicast_conninfo_t *conninfo;
375  int sanity = 0;
376 
377  if (!switch_channel_test_flag(channel, CF_UNICAST)) {
378  return SWITCH_STATUS_FALSE;
379  }
380 
381  if ((conninfo = switch_channel_get_private(channel, "unicast"))) {
382  switch_status_t st;
383 
384  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Shutting down unicast connection\n");
387  switch_thread_join(&st, conninfo->thread);
388 
389  while (switch_test_flag(conninfo, SUF_THREAD_RUNNING)) {
390  switch_yield(10000);
391  if (++sanity >= 10000) {
392  break;
393  }
394  }
395  if (switch_core_codec_ready(&conninfo->read_codec)) {
397  }
398  switch_socket_close(conninfo->socket);
399  }
401  return SWITCH_STATUS_SUCCESS;
402 }
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.
_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:998
switch_codec_t read_codec
Definition: switch_ivr.h:49
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1379
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:717
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:737
switch_status_t switch_socket_shutdown(switch_socket_t *sock, switch_shutdown_how_e how)
Definition: switch_apr.c:732
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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_ivr_detect_audio()

switch_status_t switch_ivr_detect_audio ( switch_core_session_t session,
uint32_t  thresh,
uint32_t  audio_hits,
uint32_t  timeout_ms,
const char *  file 
)

Definition at line 2235 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, count, 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_DEBUG, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, SWITCH_STATUS_FALSE, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_zmalloc.

2237 {
2238  uint32_t score, count = 0, j = 0;
2239  double energy = 0;
2241  int divisor = 0;
2242  uint32_t channels;
2243  switch_frame_t *read_frame;
2245  int16_t *data;
2246  uint32_t hits = 0;
2247  switch_codec_t raw_codec = { 0 };
2248  int16_t *abuf = NULL;
2249  switch_frame_t write_frame = { 0 };
2250  switch_file_handle_t fh = { 0 };
2251  int32_t sample_count = 0;
2252  switch_codec_implementation_t read_impl = { 0 };
2253  switch_core_session_get_read_impl(session, &read_impl);
2254 
2255  if (timeout_ms) {
2256  sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
2257  }
2258 
2259  if (file) {
2260  if (switch_core_file_open(&fh,
2261  file,
2262  read_impl.number_of_channels,
2264  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failure opening playback file %s.\n", file);
2266  return SWITCH_STATUS_NOTFOUND;
2267  }
2269  write_frame.data = abuf;
2270  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2271  }
2272 
2273 
2274  if (switch_core_codec_init(&raw_codec,
2275  "L16",
2276  NULL,
2277  NULL,
2278  read_impl.actual_samples_per_second,
2279  read_impl.microseconds_per_packet / 1000,
2282 
2283  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to initialize L16 codec.\n");
2284  status = SWITCH_STATUS_FALSE;
2285  goto end;
2286  }
2287 
2288  write_frame.codec = &raw_codec;
2289 
2290  divisor = read_impl.actual_samples_per_second / 8000;
2291  channels = read_impl.number_of_channels;
2292 
2293  switch_core_session_set_read_codec(session, &raw_codec);
2294 
2295  while (switch_channel_ready(channel)) {
2296 
2297  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2298 
2299  if (!SWITCH_READ_ACCEPTABLE(status)) {
2300  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read frame.\n");
2301  break;
2302  }
2303 
2304  if (sample_count) {
2305  sample_count -= raw_codec.implementation->samples_per_packet;
2306  if (sample_count <= 0) {
2307  switch_channel_set_variable(channel, "detect_audio_timeout", "true");
2308  switch_channel_set_variable_printf(channel, "detect_audio_hits", "%d", hits);
2310  "switch_ivr_detect_audio: TIMEOUT after %d ms at %d hits\n",
2311  timeout_ms, hits);
2312  break;
2313  }
2314  }
2315 
2316  if (abuf) {
2318 
2319  if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
2320  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read file %s.\n", file);
2321  break;
2322  }
2323 
2324  write_frame.samples = (uint32_t) olen;
2325  write_frame.datalen = (uint32_t) (olen * sizeof(int16_t) * fh.channels);
2326  if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
2327  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to write frame from file %s.\n", file);
2328  break;
2329  }
2330  }
2331 
2332  data = (int16_t *) read_frame->data;
2333 
2334  for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
2335  energy += abs(data[j++]);
2336  j += channels;
2337  }
2338 
2339  score = (uint32_t) (energy / (read_frame->samples / divisor));
2340 
2341  if (score >= thresh) {
2342  hits++;
2343  } else {
2344  hits=0;
2345  }
2346 
2347  if (hits > audio_hits) {
2348  switch_channel_set_variable(channel, "detect_audio_timeout", "false");
2349  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_detect_audio: AUDIO DETECTED\n");
2350  break;
2351  }
2352  }
2353 
2355  switch_core_codec_destroy(&raw_codec);
2356 
2357  end:
2358 
2359  if (abuf) {
2360 
2362  free(abuf);
2363  }
2364 
2365  return status;
2366 }
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:1963
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:590
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:56
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:70
uint32_t datalen
Definition: switch_frame.h:68
#define switch_zmalloc(ptr, len)
An abstraction of a data frame.
Definition: switch_frame.h:54
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:1693
switch_status_t
Common return values.
uint32_t samples
Definition: switch_frame.h:72
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.
int count
Definition: switch_cJSON.h:204
#define switch_channel_set_variable(_channel, _var, _val)
#define SWITCH_READ_ACCEPTABLE(status)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.

◆ switch_ivr_detect_silence()

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

Definition at line 2368 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, count, 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_DEBUG, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, SWITCH_STATUS_FALSE, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_zmalloc.

2370 {
2371  uint32_t score, count = 0, j = 0;
2372  double energy = 0;
2374  int divisor = 0;
2375  uint32_t channels;
2376  switch_frame_t *read_frame;
2378  int16_t *data;
2379  uint32_t hits = 0;
2380  switch_codec_t raw_codec = { 0 };
2381  int16_t *abuf = NULL;
2382  switch_frame_t write_frame = { 0 };
2383  switch_file_handle_t fh = { 0 };
2384  int32_t sample_count = 0;
2385  switch_codec_implementation_t read_impl = { 0 };
2386  switch_core_session_get_read_impl(session, &read_impl);
2387 
2388 
2389  if (timeout_ms) {
2390  sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
2391  }
2392 
2393  if (file) {
2394  if (switch_core_file_open(&fh,
2395  file,
2396  read_impl.number_of_channels,
2398  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failure opening playback file %s.\n", file);
2400  return SWITCH_STATUS_NOTFOUND;
2401  }
2403  write_frame.data = abuf;
2404  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2405  }
2406 
2407 
2408  if (switch_core_codec_init(&raw_codec,
2409  "L16",
2410  NULL,
2411  NULL,
2412  read_impl.actual_samples_per_second,
2413  read_impl.microseconds_per_packet / 1000,
2416 
2417  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to initialize L16 codec.\n");
2418  status = SWITCH_STATUS_FALSE;
2419  goto end;
2420  }
2421 
2422  write_frame.codec = &raw_codec;
2423 
2424  divisor = read_impl.actual_samples_per_second / 8000;
2425  channels = read_impl.number_of_channels;
2426 
2427  switch_core_session_set_read_codec(session, &raw_codec);
2428 
2429  while (switch_channel_ready(channel)) {
2430 
2431  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2432 
2433  if (!SWITCH_READ_ACCEPTABLE(status)) {
2434  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read frame.\n");
2435  break;
2436  }
2437 
2438  if (sample_count) {
2439  sample_count -= raw_codec.implementation->samples_per_packet;
2440  if (sample_count <= 0) {
2441  switch_channel_set_variable(channel, "detect_silence_timeout", "true");
2442  switch_channel_set_variable_printf(channel, "detect_silence_hits", "%d", hits);
2444  "switch_ivr_detect_silence: TIMEOUT after %d ms at %d hits\n",
2445  timeout_ms, hits);
2446  break;
2447  }
2448  }
2449 
2450  if (abuf) {
2452 
2453  if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
2454  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read file %s.\n", file);
2455  break;
2456  }
2457 
2458  write_frame.samples = (uint32_t) olen;
2459  write_frame.datalen = (uint32_t) (olen * sizeof(int16_t) * fh.channels);
2460  if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
2461  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to write frame from file %s.\n", file);
2462  break;
2463  }
2464  }
2465 
2466  data = (int16_t *) read_frame->data;
2467 
2468  for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
2469  energy += abs(data[j++]);
2470  j += channels;
2471  }
2472 
2473  score = (uint32_t) (energy / (read_frame->samples / divisor));
2474 
2475  if (score <= thresh) {
2476  hits++;
2477  } else {
2478  hits=0;
2479  }
2480 
2481  if (hits > silence_hits) {
2482  switch_channel_set_variable(channel, "detect_silence_timeout", "false");
2483  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_detect_silence: SILENCE DETECTED\n");
2484  break;
2485  }
2486  }
2487 
2489  switch_core_codec_destroy(&raw_codec);
2490 
2491  end:
2492 
2493  if (abuf) {
2494 
2496  free(abuf);
2497  }
2498 
2499  return status;
2500 }
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:1963
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:590
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:56
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:70
uint32_t datalen
Definition: switch_frame.h:68
#define switch_zmalloc(ptr, len)
An abstraction of a data frame.
Definition: switch_frame.h:54
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:1693
switch_status_t
Common return values.
uint32_t samples
Definition: switch_frame.h:72
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.
int count
Definition: switch_cJSON.h:204
#define switch_channel_set_variable(_channel, _var, _val)
#define SWITCH_READ_ACCEPTABLE(status)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.

◆ switch_ivr_detect_speech()

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 5461 of file switch_ivr_async.c.

References speech_thread_handle::ah, asr_set_json_text_params(), 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_resume_detect_speech(), 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 CoreSession::detectSpeech(), switch_ivr_play_and_collect_input(), and switch_ivr_play_and_detect_speech().

5464 {
5467  const char *p;
5468  int resume = 0;
5469 
5470 
5471  if (!sth) {
5472  /* No speech thread handle available yet, init speech detection first. */
5473  if (switch_ivr_detect_speech_init(session, mod_name, dest, ah) != SWITCH_STATUS_SUCCESS) {
5475  }
5476 
5477  /* Fetch the new speech thread handle */
5478  if (!(sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
5480  }
5481  } else {
5482  resume = 1;
5483  }
5484 
5485  asr_set_json_text_params(session, sth->ah);
5486 
5487  if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) {
5488  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
5490  return SWITCH_STATUS_FALSE;
5491  }
5492 
5493  if (resume) {
5495  }
5496 
5497  if ((p = switch_channel_get_variable(channel, "fire_asr_events")) && switch_true(p)) {
5499  }
5500 
5501  return SWITCH_STATUS_SUCCESS;
5502 }
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
switch_asr_handle_t * ah
static void asr_set_json_text_params(switch_core_session_t *session, 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:233
_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 switch_ivr_resume_detect_speech(switch_core_session_t *session)
Resume background Speech detection on a session.
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.
const char *const name
Definition: switch_cJSON.h:250

◆ switch_ivr_detect_speech_disable_all_grammars()

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 5359 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.

Referenced by CoreSession::detectSpeech().

5360 {
5363  switch_status_t status;
5364 
5365  if (sth) {
5367  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error disabling all Grammars\n");
5369  }
5370  return status;
5371  }
5372  return SWITCH_STATUS_FALSE;
5373 }
#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:233
_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_ivr_detect_speech_disable_grammar()

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 5343 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.

Referenced by CoreSession::detectSpeech().

5344 {
5347  switch_status_t status;
5348 
5349  if (sth) {
5350  if ((status = switch_core_asr_disable_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
5351  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error disabling Grammar\n");
5353  }
5354  return status;
5355  }
5356  return SWITCH_STATUS_FALSE;
5357 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:233
_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.
const char *const name
Definition: switch_cJSON.h:250

◆ switch_ivr_detect_speech_enable_grammar()

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 5327 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.

Referenced by CoreSession::detectSpeech().

5328 {
5331  switch_status_t status;
5332 
5333  if (sth) {
5334  if ((status = switch_core_asr_enable_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
5335  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error enabling Grammar\n");
5337  }
5338  return status;
5339  }
5340  return SWITCH_STATUS_FALSE;
5341 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:233
_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.
const char *const name
Definition: switch_cJSON.h:250

◆ switch_ivr_detect_speech_init()

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 5375 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, speech_thread_handle::ah, speech_thread_handle::bug, switch_ivr_dmachine_binding::key, 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 CoreSession::detectSpeech(), and switch_ivr_detect_speech().

5377 {
5379  switch_status_t status;
5382  switch_codec_implementation_t read_impl = { 0 };
5383  const char *p;
5384  char key[512] = "";
5385 
5386  if (sth) {
5387  /* Already initialized */
5388  return SWITCH_STATUS_SUCCESS;
5389  }
5390 
5391  if (!ah) {
5392  if (!(ah = switch_core_session_alloc(session, sizeof(*ah)))) {
5393  return SWITCH_STATUS_MEMERR;
5394  }
5395  }
5396 
5397  switch_core_session_get_read_impl(session, &read_impl);
5398 
5399  if ((status = switch_core_asr_open(ah,
5400  mod_name,
5401  "L16",
5402  read_impl.actual_samples_per_second, dest, &flags,
5404  return status;
5405  }
5406 
5407  sth = switch_core_session_alloc(session, sizeof(*sth));
5408  sth->pool = switch_core_session_get_pool(session);
5409  sth->session = session;
5410  sth->ah = ah;
5411 
5412  if ((p = switch_channel_get_variable(channel, "fire_asr_events")) && switch_true(p)) {
5414  }
5415 
5416  switch_snprintf(key, sizeof(key), "%s/%s/%s/%s", mod_name, NULL, NULL, dest);
5417 
5418  if ((status = switch_core_media_bug_add(session, "detect_speech", key,
5420  switch_core_asr_close(ah, &flags);
5421  return status;
5422  }
5423 
5424  if ((status = switch_core_event_hook_add_recv_dtmf(session, speech_on_dtmf)) != SWITCH_STATUS_SUCCESS) {
5426  return status;
5427  }
5428 
5430 
5431  return SWITCH_STATUS_SUCCESS;
5432 }
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
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.
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:233
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.
char * key
Definition: switch_msrp.c:64
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session&#39;s pool.
Definition: switch_core.h:696
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_ivr_detect_speech_load_grammar()

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 5270 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.

Referenced by CoreSession::detectSpeech().

5271 {
5274  switch_status_t status;
5275 
5276  if (sth) {
5277  if ((status = switch_core_asr_load_grammar(sth->ah, grammar, name)) != SWITCH_STATUS_SUCCESS) {
5278  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
5280  }
5281  return status;
5282  }
5283  return SWITCH_STATUS_FALSE;
5284 }
#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:233
_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.
const char *const name
Definition: switch_cJSON.h:250

◆ switch_ivr_detect_speech_start_input_timers()

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 5299 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 CoreSession::detectSpeech(), switch_ivr_play_and_collect_input(), and switch_ivr_play_and_detect_speech().

5300 {
5303 
5304  if (sth) {
5306  return SWITCH_STATUS_SUCCESS;
5307  }
5308  return SWITCH_STATUS_FALSE;
5309 }
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:233
_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_ivr_detect_speech_unload_grammar()

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 5311 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.

Referenced by CoreSession::detectSpeech().

5312 {
5315  switch_status_t status;
5316 
5317  if (sth) {
5318  if ((status = switch_core_asr_unload_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) {
5319  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error unloading Grammar\n");
5321  }
5322  return status;
5323  }
5324  return SWITCH_STATUS_FALSE;
5325 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:233
_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.
const char *const name
Definition: switch_cJSON.h:250
switch_status_t switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name)
Unload a grammar from an asr handle.

◆ switch_ivr_digit_stream_destroy()

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 2447 of file switch_ivr.c.

References switch_safe_free, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

2448 {
2450 
2451  if (*stream) {
2452  switch_safe_free((*stream)->digits);
2453  free(*stream);
2454  *stream = NULL;
2455  status = SWITCH_STATUS_SUCCESS;
2456  }
2457 
2458  return status;
2459 }
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_status_t
Common return values.

◆ switch_ivr_digit_stream_new()

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 2431 of file switch_ivr.c.

References switch_ivr_digit_stream_parser::buflen, memset(), switch_assert, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_zmalloc.

2432 {
2434 
2435  /* if we have a parser object memory pool and a stream object pointer that is null */
2436  if (parser && stream && *stream == NULL) {
2437  *stream = (switch_ivr_digit_stream_t *) malloc(sizeof(**stream));
2438  switch_assert(*stream);
2439  memset(*stream, 0, sizeof(**stream));
2440  switch_zmalloc((*stream)->digits, parser->buflen + 1);
2441  status = SWITCH_STATUS_SUCCESS;
2442  }
2443 
2444  return status;
2445 }
#define switch_zmalloc(ptr, len)
switch_status_t
Common return values.
#define switch_assert(expr)
memset(buf, 0, buflen)

◆ switch_ivr_digit_stream_parser_del_event()

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 2503 of file switch_ivr.c.

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

2504 {
2506 
2507  if (parser != NULL && digits != NULL && *digits) {
2509  }
2510 
2511  if (status != SWITCH_STATUS_SUCCESS) {
2512  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to del hash for '%s'\n", digits);
2513  }
2514 
2515  return status;
2516 }
#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_ivr_digit_stream_parser_destroy()

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 2413 of file switch_ivr.c.

References switch_ivr_digit_stream_parser::hash, switch_ivr_digit_stream_parser::pool, switch_ivr_digit_stream_parser::pool_auto_created, switch_core_destroy_memory_pool, switch_core_hash_destroy(), and SWITCH_STATUS_FALSE.

2414 {
2416 
2417  if (parser != NULL) {
2418  if (parser->hash != NULL) {
2419  switch_core_hash_destroy(&parser->hash);
2420  parser->hash = NULL;
2421  }
2422  /* free the memory pool if we created it */
2423  if (parser->pool_auto_created && parser->pool != NULL) {
2424  status = switch_core_destroy_memory_pool(&parser->pool);
2425  }
2426  }
2427 
2428  return status;
2429 }
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:642
switch_status_t
Common return values.
switch_memory_pool_t * pool
Definition: switch_ivr.c:2359

◆ switch_ivr_digit_stream_parser_feed()

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 2518 of file switch_ivr.c.

References switch_ivr_digit_stream_parser::digit_timeout_ms, switch_ivr_digit_stream::digits, switch_ivr_digit_stream_parser::hash, switch_ivr_digit_stream::last_digit_time, switch_ivr_digit_stream_parser::maxlen, switch_ivr_digit_stream_parser::minlen, switch_assert, switch_core_hash_find(), switch_micro_time_now(), and switch_ivr_digit_stream_parser::terminator.

2519 {
2520  void *result = NULL;
2521  switch_size_t len;
2522 
2523  switch_assert(parser);
2524  switch_assert(stream);
2525  switch_assert(stream->digits);
2526 
2527  len = strlen(stream->digits);
2528 
2529  /* handle new digit arrivals */
2530  if (digit) {
2531  /* if it's not a terminator digit, add it to the collected digits */
2532  if (digit != parser->terminator) {
2533  /* if collected digits length >= the max length of the keys
2534  * in the hash table, then left shift the digit string
2535  */
2536  if (len > 0 && parser->maxlen != 0 && len >= parser->maxlen) {
2537  char *src = stream->digits + 1;
2538  char *dst = stream->digits;
2539 
2540  while (*src) {
2541  *(dst++) = *(src++);
2542  }
2543  *dst = digit;
2544  } else {
2545  *(stream->digits + (len++)) = digit;
2546  *(stream->digits + len) = '\0';
2547  stream->last_digit_time = switch_micro_time_now() / 1000;
2548  }
2549  }
2550  }
2551 
2552  /* don't allow collected digit string testing if there are varying sized keys until timeout */
2553  if (parser->maxlen - parser->minlen > 0 && (switch_micro_time_now() / 1000) - stream->last_digit_time < parser->digit_timeout_ms) {
2554  len = 0;
2555  }
2556  /* if we have digits to test */
2557  if (len) {
2558  result = switch_core_hash_find(parser->hash, stream->digits);
2559  /* if we matched the digit string, or this digit is the terminator
2560  * reset the collected digits for next digit string
2561  */
2562  if (result != NULL || parser->terminator == digit) {
2563  *stream->digits = '\0';
2564  }
2565  }
2566 
2567 
2568  return result;
2569 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
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:2370
uintptr_t switch_size_t
#define switch_assert(expr)

◆ switch_ivr_digit_stream_parser_new()

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 2373 of file switch_ivr.c.

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

2374 {
2376 
2377  if (parser != NULL) {
2378  int pool_auto_created = 0;
2379 
2380  /* if the caller didn't provide a pool, make one */
2381  if (pool == NULL) {
2383  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "created a memory pool\n");
2384  if (pool != NULL) {
2385  pool_auto_created = 1;
2386  }
2387  }
2388  /* if we have a pool, make a parser object */
2389  if (pool != NULL) {
2391  }
2392  /* if we have parser object, initialize it for the caller */
2393  if (pool && *parser != NULL) {
2394  memset(*parser, 0, sizeof(switch_ivr_digit_stream_parser_t));
2395  (*parser)->pool_auto_created = pool_auto_created;
2396  (*parser)->pool = pool;
2397  (*parser)->digit_timeout_ms = 1000;
2398  switch_core_hash_init(&(*parser)->hash);
2399 
2400  status = SWITCH_STATUS_SUCCESS;
2401  } else {
2402  status = SWITCH_STATUS_MEMERR;
2403  /* if we can't create a parser object,clean up the pool if we created it */
2404  if (pool != NULL && pool_auto_created) {
2406  }
2407  }
2408  }
2409 
2410  return status;
2411 }
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
#define SWITCH_CHANNEL_LOG
#define switch_core_hash_init(_hash)
Definition: switch_core.h:1431
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
switch_memory_pool_t * pool
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
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_ivr_digit_stream_parser_set_event()

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 2461 of file switch_ivr.c.

References switch_ivr_digit_stream_parser::buflen, switch_ivr_digit_stream_parser::hash, switch_ivr_digit_stream_parser::maxlen, switch_ivr_digit_stream_parser::minlen, SWITCH_CHANNEL_LOG, switch_core_hash_insert, SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_ivr_digit_stream_parser::terminator.

2462 {
2464 
2465  if (parser != NULL && digits != NULL && *digits && parser->hash != NULL) {
2466 
2467  status = switch_core_hash_insert(parser->hash, digits, data);
2468  if (status == SWITCH_STATUS_SUCCESS) {
2469  switch_size_t len = strlen(digits);
2470 
2471  /* if we don't have a terminator, then we have to try and
2472  * figure out when a digit set is completed, therefore we
2473  * keep track of the min and max digit lengths
2474  */
2475 
2476  if (len > parser->buflen) {
2477  parser->buflen = len;
2478  }
2479 
2480  if (parser->terminator == '\0') {
2481  if (len > parser->maxlen) {
2482  parser->maxlen = len;
2483  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "max len %u\n", (uint32_t) parser->maxlen);
2484  }
2485  if (parser->minlen == 0 || len < parser->minlen) {
2486  parser->minlen = len;
2487  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "min len %u\n", (uint32_t) parser->minlen);
2488  }
2489  } else {
2490  /* since we have a terminator, reset min and max */
2491  parser->minlen = 0;
2492  parser->maxlen = 0;
2493  }
2494  }
2495  }
2496  if (status != SWITCH_STATUS_SUCCESS) {
2497  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to add hash for '%s'\n", digits);
2498  }
2499 
2500  return status;
2501 }
#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:1479
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_ivr_digit_stream_parser_set_terminator()

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 2584 of file switch_ivr.c.

References switch_ivr_digit_stream_parser::maxlen, switch_ivr_digit_stream_parser::minlen, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_ivr_digit_stream_parser::terminator.

2585 {
2587 
2588  if (parser != NULL) {
2589  parser->terminator = digit;
2590  /* since we have a terminator, reset min and max */
2591  parser->minlen = 0;
2592  parser->maxlen = 0;
2593  status = SWITCH_STATUS_SUCCESS;
2594  }
2595 
2596  return status;
2597 }
switch_status_t
Common return values.

◆ switch_ivr_digit_stream_reset()

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 2571 of file switch_ivr.c.

References switch_ivr_digit_stream::digits, switch_ivr_digit_stream::last_digit_time, switch_assert, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

2572 {
2574  switch_assert(stream);
2575  switch_assert(stream->digits);
2576 
2577  *stream->digits = '\0';
2578  stream->last_digit_time = 0;
2579  status = SWITCH_STATUS_SUCCESS;
2580 
2581  return status;
2582 }
switch_time_t last_digit_time
Definition: switch_ivr.c:2370
switch_status_t
Common return values.
#define switch_assert(expr)

◆ switch_ivr_displace_session()

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

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

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 1001 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::mutex, displace_helper_t::mux, switch_codec_implementation::number_of_channels, read_displace_callback(), switch_file_handle::samplerate, SMBF_FIRST, SMBF_NO_PAUSE, SMBF_READ_REPLACE, SMBF_WRITE_REPLACE, switch_buffer_create_dynamic(), 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_pool(), 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_mutex_init(), SWITCH_MUTEX_NESTED, 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, to, displace_helper_t::wbuffer, write_displace_callback(), and zstr.

1002 {
1005  switch_status_t status;
1006  time_t to = 0;
1007  char *ext;
1008  const char *prefix;
1009  displace_helper_t *dh;
1010  const char *p;
1011  switch_bool_t hangup_on_error = SWITCH_FALSE;
1012  switch_media_bug_flag_enum_t bug_flags = 0;
1013  switch_codec_implementation_t read_impl = { 0 };
1014  switch_core_session_get_read_impl(session, &read_impl);
1015 
1016  if ((p = switch_channel_get_variable(channel, "DISPLACE_HANGUP_ON_ERROR"))) {
1017  hangup_on_error = switch_true(p);
1018  }
1019 
1020  if (zstr(file)) {
1021  return SWITCH_STATUS_FALSE;
1022  }
1023 
1025  return SWITCH_STATUS_FALSE;
1026  }
1027 
1028  if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
1029  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not displace session. Media not enabled on channel\n");
1030  return SWITCH_STATUS_FALSE;
1031  }
1032 
1033  if ((bug = switch_channel_get_private(channel, file))) {
1034  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only 1 of the same file per channel please!\n");
1035  return SWITCH_STATUS_FALSE;
1036  }
1037 
1038  if (!(dh = switch_core_session_alloc(session, sizeof(*dh)))) {
1039  return SWITCH_STATUS_MEMERR;
1040  }
1041 
1042  if (!(prefix = switch_channel_get_variable(channel, "sound_prefix"))) {
1043  prefix = SWITCH_GLOBAL_dirs.base_dir;
1044  }
1045 
1046  if (!strstr(file, SWITCH_URL_SEPARATOR)) {
1047  if (!switch_is_file_path(file)) {
1048  char *tfile = NULL;
1049  char *e;
1050 
1051  if (*file == '[') {
1052  tfile = switch_core_session_strdup(session, file);
1053  if ((e = switch_find_end_paren(tfile, '[', ']'))) {
1054  *e = '\0';
1055  file = e + 1;
1056  } else {
1057  tfile = NULL;
1058  }
1059  }
1060 
1061  file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
1062  }
1063  if ((ext = strrchr(file, '.'))) {
1064  ext++;
1065  } else {
1066  ext = read_impl.iananame;
1067  file = switch_core_session_sprintf(session, "%s.%s", file, ext);
1068  }
1069  }
1070 
1071  dh->fh.channels = read_impl.number_of_channels;
1072  dh->fh.samplerate = read_impl.actual_samples_per_second;
1073  dh->file = switch_core_session_strdup(session, file);
1074 
1075  if (switch_core_file_open(&dh->fh,
1076  file,
1077  read_impl.number_of_channels,
1079  if (hangup_on_error) {
1082  }
1083  return SWITCH_STATUS_GENERR;
1084  }
1085 
1086  if (limit) {
1087  to = switch_epoch_time_now(NULL) + limit;
1088  }
1089 
1090  if (flags && strchr(flags, 'm')) {
1091  dh->mux++;
1092  }
1093 
1094  if (flags && strchr(flags, 'l')) {
1095  dh->loop++;
1096  }
1097 
1098  if (flags && strchr(flags, 'f')) {
1099  bug_flags |= SMBF_FIRST;
1100  }
1101 
1102  if (flags && strchr(flags, 'r')) {
1103  if (strchr(flags, 'w')) { // r&w mode, both sides can hear the same file
1104  int len = dh->fh.samplerate / 10 * 2 * dh->fh.channels; // init with 100ms
1105 
1107  switch_buffer_create_dynamic(&dh->wbuffer, len, len, 0);
1108  }
1109 
1110  status = switch_core_media_bug_add(session, "displace", file,
1112  } else {
1113  status = switch_core_media_bug_add(session, "displace", file,
1115  }
1116 
1117  if (status != SWITCH_STATUS_SUCCESS) {
1118  switch_core_file_close(&dh->fh);
1119  return status;
1120  }
1121 
1122  switch_channel_set_private(channel, file, bug);
1123 
1124  return SWITCH_STATUS_SUCCESS;
1125 }
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it&#39;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 ...
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#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:796
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:1963
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_buffer_t * wbuffer
cJSON *const to
switch_bool_t
Definition: switch_types.h:437
#define SWITCH_URL_SEPARATOR
Definition: switch_types.h:126
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.
#define zstr(x)
Definition: switch_utils.h:314
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_MUTEX_NESTED
Definition: switch_apr.h:318
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
switch_file_handle_t fh
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
switch_media_bug_flag_enum_t
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
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:322
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session&#39;s pool.
Definition: switch_core.h:696
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&#39;s pool.
Definition: switch_core.h:719
switch_mutex_t * mutex
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_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_ivr_eavesdrop_exec_all()

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

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

2233 {
2234  struct exec_cb_data *data = NULL;
2235 
2236  data = switch_core_session_alloc(session, sizeof(*data));
2237  data->var = switch_core_session_strdup(session, app);
2238  data->val = switch_core_session_strdup(session, arg);
2239  data->caller = session;
2240 
2241  return switch_core_media_bug_exec_all(session, "eavesdrop", exec_cb, data);
2242 }
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&#39;s pool.
Definition: switch_core.h:696
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session&#39;s pool.
Definition: switch_core.h:719
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_ivr_eavesdrop_pop_eavesdropper()

switch_status_t switch_ivr_eavesdrop_pop_eavesdropper ( switch_core_session_t session,
switch_core_session_t **  sessionp 
)

Definition at line 2172 of file switch_ivr_async.c.

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

2173 {
2174  switch_media_bug_t *bug;
2176 
2177  if (switch_core_media_bug_pop(session, "eavesdrop", &bug) == SWITCH_STATUS_SUCCESS) {
2179 
2180  if (ep && ep->eavesdropper && ep->eavesdropper != session) {
2182  *sessionp = ep->eavesdropper;
2184  status = SWITCH_STATUS_SUCCESS;
2185  }
2186  }
2187  }
2188 
2189 
2190  return status;
2191 }
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)
switch_status_t
Common return values.

◆ switch_ivr_eavesdrop_session()

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 2285 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::channels, 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, ED_STEREO, ED_TAP_READ, ED_TAP_WRITE, eavesdrop_pvt::flags, switch_core_session_message::from, switch_codec_implementation::iananame, switch_codec::implementation, switch_core_session_message::message_id, switch_codec_implementation::microseconds_per_packet, eavesdrop_pvt::mutex, name, 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_STEREO, SMBF_TAP_NATIVE_READ, SMBF_TAP_NATIVE_WRITE, 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_get_real_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_goto_status, SWITCH_IO_FLAG_NONE, switch_ivr_phrase_macro, switch_lcm(), 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.

2287 {
2288  switch_core_session_t *tsession;
2291  int codec_initialized = 0;
2292  const char *name, *num;
2293 
2294  if ((tsession = switch_core_session_locate(uuid))) {
2295  struct eavesdrop_pvt *ep = NULL;
2296  switch_media_bug_t *bug = NULL;
2297  switch_channel_t *tchannel = switch_core_session_get_channel(tsession);
2298  switch_frame_t *read_frame, write_frame = { 0 };
2299  switch_codec_t codec = { 0 };
2300  int16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE / 2];
2301  uint32_t tlen;
2302  const char *macro_name = "eavesdrop_announce";
2303  const char *id_name = NULL;
2305  switch_core_session_message_t msg = { 0 };
2306  char cid_buf[1024] = "";
2307  switch_caller_profile_t *cp = NULL;
2308  uint32_t sanity = 600;
2309  switch_media_bug_flag_t read_flags = 0, write_flags = 0, stereo_flag = 0;
2310  const char *vval;
2311  int buf_size = 0;
2312  int channels;
2313  int lcm, buff_min_len, buffered = 1;
2314 
2315  if (!switch_channel_media_up(channel)) {
2316  goto end;
2317  }
2318 
2319  if (tsession == session) {
2320  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Eavesdrop target invalid.\n");
2321  goto end;
2322  }
2323 
2324  while(switch_channel_state_change_pending(tchannel) || !switch_channel_media_up(tchannel)) {
2325  switch_yield(10000);
2326  if (!--sanity) break;
2327  }
2328 
2329  if (!switch_channel_media_up(tchannel)) {
2330  goto end;
2331  }
2332 
2333  if ((flags & ED_TAP_READ) || (flags & ED_TAP_WRITE)) {
2334  switch_core_session_get_real_read_impl(tsession, &tread_impl);
2336 
2337  if (strcasecmp(tread_impl.iananame, read_impl.iananame)) {
2338  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codecs do not match which is required for this mode\n");
2339  goto end;
2340  }
2341  }
2342 
2343  switch_core_session_get_read_impl(tsession, &tread_impl);
2345 
2346  if ((id_name = switch_channel_get_variable(tchannel, "eavesdrop_announce_id"))) {
2347  const char *tmp = switch_channel_get_variable(tchannel, "eavesdrop_announce_macro");
2348  if (tmp) {
2349  macro_name = tmp;
2350  }
2351 
2352  switch_ivr_phrase_macro(session, macro_name, id_name, NULL, NULL);
2353  }
2354 
2355 
2356  if (!zstr(require_group)) {
2357  int argc, i;
2358  int ok = 0;
2359  char *argv[10] = { 0 };
2360  char *data;
2361 
2362  const char *group_name = switch_channel_get_variable(tchannel, "eavesdrop_group");
2363  /* If we don't have a group, then return */
2364  if (!group_name) {
2366  }
2367  /* Separate the group */
2368  data = strdup(group_name);
2369  if ((argc = switch_separate_string(data, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
2370  for (i = 0; i < argc; i++) {
2371  /* If one of the group matches, then ok */
2372  if (argv[i] && !strcmp(argv[i], require_group)) {
2373  ok = 1;
2374  }
2375  }
2376  }
2377  switch_safe_free(data);
2378  /* If we didn't find any match, then end */
2379  if (!ok) {
2381  }
2382  }
2383 
2384 
2385  ep = switch_core_session_alloc(session, sizeof(*ep));
2386 
2387 
2389  goto end;
2390  }
2391 
2393  if (switch_core_codec_init(&codec,
2394  "L16",
2395  NULL,
2396  NULL,
2402  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
2403  goto end;
2404  }
2405  } else {
2406  if (switch_core_codec_init(&codec,
2407  "L16",
2408  NULL,
2409  NULL,
2410  tread_impl.actual_samples_per_second,
2411  tread_impl.microseconds_per_packet / 1000,
2412  tread_impl.number_of_channels,
2415  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
2416  goto end;
2417  }
2418  buffered = 0;
2419  }
2420 
2421  ep->read_impl = read_impl;
2422  ep->tread_impl = tread_impl;
2423 
2424  codec_initialized = 1;
2425 
2426  switch_core_session_set_read_codec(session, &codec);
2427  write_frame.codec = &codec;
2428  write_frame.data = buf;
2429  write_frame.buflen = sizeof(buf);
2430  write_frame.rate = codec.implementation->actual_samples_per_second;
2431 
2432  /* Make sure that at least one leg is bridged, default to both */
2433  if (! (flags & (ED_BRIDGE_READ | ED_BRIDGE_WRITE))) {
2435  }
2436 
2437  buf_size = codec.implementation->decoded_bytes_per_packet * 10;
2438 
2439  ep->eavesdropper = session;
2440  ep->flags = flags;
2441 
2442  if (!(flags & ED_TAP_READ) && !(flags & ED_TAP_WRITE)) {
2444  switch_buffer_create_dynamic(&ep->buffer, buf_size, buf_size, buf_size);
2446 
2448  switch_buffer_create_dynamic(&ep->w_buffer, buf_size, buf_size, buf_size);
2450 
2452  switch_buffer_create_dynamic(&ep->r_buffer, buf_size, buf_size, buf_size);
2454  }
2455 
2456  if (flags & ED_BRIDGE_READ) {
2457  read_flags = SMBF_READ_STREAM | SMBF_READ_REPLACE;
2458  }
2459 
2460  if (flags & ED_BRIDGE_WRITE) {
2461  write_flags = SMBF_WRITE_STREAM | SMBF_WRITE_REPLACE;
2462  }
2463 
2464  if (flags & ED_TAP_READ) {
2465  read_flags = SMBF_TAP_NATIVE_READ;
2466  write_flags = 0;
2467  }
2468 
2469  if (flags & ED_TAP_WRITE) {
2470  write_flags = SMBF_TAP_NATIVE_WRITE;
2471  read_flags = 0;
2472  }
2473 
2474  if (flags & ED_STEREO) {
2475  stereo_flag = SMBF_STEREO;
2476  }
2477 
2479  if ((vval = switch_channel_get_variable(session->channel, "eavesdrop_show_listener_video"))) {
2480  if (switch_true(vval) || !strcasecmp(vval, "aleg") || !strcasecmp(vval, "bleg") || !strcasecmp(vval, "both")) {
2481  read_flags |= SMBF_SPY_VIDEO_STREAM;
2482  }
2483  if (switch_true(vval) || !strcasecmp(vval, "bleg") || !strcasecmp(vval, "both")) {
2484  read_flags |= SMBF_SPY_VIDEO_STREAM_BLEG;
2485  }
2486  }
2487 
2488  if ((vval = switch_channel_get_variable(session->channel, "eavesdrop_concat_video")) && switch_true(vval)) {
2489  read_flags |= SMBF_READ_VIDEO_STREAM;
2490  read_flags |= SMBF_WRITE_VIDEO_STREAM;
2491  } else {
2492  read_flags |= SMBF_READ_VIDEO_PING;
2493  }
2494  } else {
2495  read_flags &= ~SMBF_READ_VIDEO_PING;
2496  read_flags &= ~SMBF_READ_VIDEO_STREAM;
2497  read_flags &= ~SMBF_WRITE_VIDEO_STREAM;
2498  read_flags &= ~SMBF_SPY_VIDEO_STREAM;
2499  read_flags &= ~SMBF_SPY_VIDEO_STREAM_BLEG;
2500  }
2501 
2502 
2503  if (switch_core_media_bug_add(tsession, "eavesdrop", uuid,
2504  eavesdrop_callback, ep, 0,
2505  read_flags | write_flags | SMBF_READ_PING | SMBF_THREAD_LOCK | SMBF_NO_PAUSE | stereo_flag,
2506  &bug) != SWITCH_STATUS_SUCCESS) {
2507  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot attach bug\n");
2508  goto end;
2509  }
2510 
2511  if ((vval = switch_channel_get_variable(session->channel, "eavesdrop_video_spy_fmt"))) {
2513  }
2514 
2515  msg.from = __FILE__;
2516 
2517  /* Tell the channel we are going to be in a bridge */
2519  switch_core_session_receive_message(session, &msg);
2520  cp = switch_channel_get_caller_profile(tchannel);
2521 
2522  name = cp->caller_id_name;
2523  num = cp->caller_id_number;
2524 
2525  if ((flags & ED_TAP_READ) || (flags & ED_TAP_WRITE)) {
2526  flags &= ~ED_DTMF;
2527  flags &= ~ED_BRIDGE_READ;
2528  flags &= ~ED_BRIDGE_WRITE;
2529  }
2530 
2531  if (flags & ED_COPY_DISPLAY) {
2533  name = cp->callee_id_name;
2534  num = cp->callee_id_number;
2535  } else {
2536  name = cp->caller_id_name;
2537  num = cp->caller_id_number;
2538  }
2539  }
2540 
2541  sanity = 300;
2542  while(switch_channel_up(channel) && !switch_channel_media_ack(channel) && --sanity) {
2543  switch_yield(10000);
2544  }
2545 
2546 
2547  switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", name, num);
2548  msg.string_arg = cid_buf;
2550  switch_core_session_receive_message(session, &msg);
2551 
2552  if (switch_channel_test_flag(tchannel, CF_VIDEO)) {
2553 
2555 
2556  switch_core_session_receive_message(tsession, &msg);
2557  }
2558 
2560 
2561  while (switch_channel_up_nosig(tchannel) && switch_channel_ready(channel)) {
2562  uint32_t len = sizeof(buf);
2563  switch_event_t *event = NULL;
2564  char *fcommand = NULL;
2565  char db[2] = "";
2566  int vid_bug = 0, vid_dual = 0;
2567 
2568  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2569 
2570  if (!SWITCH_READ_ACCEPTABLE(status)) {
2571  goto end_loop;
2572  }
2573 
2575  char *command = switch_event_get_header(event, "eavesdrop-command");
2576  if (command) {
2577  fcommand = switch_core_session_strdup(session, command);
2578  }
2579  switch_event_destroy(&event);
2580  }
2581 
2582  if ((flags & ED_DTMF) && switch_channel_has_dtmf(channel)) {
2583  switch_dtmf_t dtmf = { 0 };
2584  switch_channel_dequeue_dtmf(channel, &dtmf);
2585  db[0] = dtmf.digit;
2586  fcommand = db;
2587  }
2588 
2591  vid_dual = 1;
2592  }
2593 
2594  if (vid_dual || switch_core_media_bug_test_flag(bug, SMBF_READ_VIDEO_PING)) {
2595  vid_bug = 1;
2596  }
2597 
2598  if (fcommand) {
2599  char *d;
2600  for (d = fcommand; *d; d++) {
2601  int z = 1;
2602 
2603  switch (*d) {
2604  case '1':
2607  if (vid_bug) {
2611  }
2612  break;
2613  case '2':
2616  if (vid_bug) {
2620  }
2621  break;
2622  case '3':
2625  if (vid_bug) {
2629  }
2630  break;
2631 
2632  case '4':
2634  break;
2635  case '5':
2637  break;
2638  case '6':
2640  break;
2641  case '0':
2644  if (vid_bug) {
2648  }
2649  break;
2650  case '*':
2651  goto end_loop;
2652  default:
2653  z = 0;
2654  break;
2655 
2656  }
2657 
2658  if (z) {
2659  if (ep->r_buffer) {
2663  }
2664 
2665  if (ep->w_buffer) {
2669  }
2670  }
2671  }
2672  }
2673 
2674  if (ep->r_buffer && ep->w_buffer && !switch_test_flag(read_frame, SFF_CNG)) {
2676  switch_buffer_zwrite(ep->r_buffer, read_frame->data, read_frame->datalen);
2678 
2680  switch_buffer_zwrite(ep->w_buffer, read_frame->data, read_frame->datalen);
2682  }
2683 
2684  channels = switch_core_media_bug_test_flag(bug, SMBF_STEREO) ? 2 : tread_impl.number_of_channels;
2685 
2686  if (channels == 0) {
2687  channels = 1;
2688  }
2689 
2690  tlen = ep->read_impl.decoded_bytes_per_packet * channels;
2691 
2692  if (len > tlen) {
2693  len = tlen;
2694  }
2695 
2696  if (buffered) {
2697  buff_min_len = lcm * 2;
2698  if (switch_buffer_inuse(ep->buffer) < buff_min_len) {
2699  continue;
2700  }
2701  } else {
2702  buff_min_len = len;
2703  }
2704 
2705  if (ep->buffer) {
2707  while (switch_buffer_inuse(ep->buffer) >= buff_min_len) {
2708  int tchanged = 0, changed = 0;
2709 
2710  write_frame.datalen = (uint32_t) switch_buffer_read(ep->buffer, buf, len);
2711  write_frame.samples = write_frame.datalen / 2 / channels;
2712  write_frame.channels = channels;
2713 
2714  switch_core_session_get_read_impl(tsession, &tread_impl);
2716 
2717  if (tread_impl.number_of_channels != ep->tread_impl.number_of_channels ||
2719  tchanged = 1;
2720  }
2721 
2724  changed = 1;
2725  }
2726 
2727  if (changed || tchanged) {
2728 
2729  if (changed) {
2731  "SPYING CHANNEL CODEC CHANGE FROM %dhz@%dc to %dhz@%dc\n",
2736 
2737  tlen = read_impl.decoded_bytes_per_packet * channels;
2738 
2739  if (len > tlen) {
2740  len = tlen;
2741  }
2742 
2743  }
2744 
2745  if (tchanged) {
2747  "SPYED CHANNEL CODEC CHANGE FROM %dhz@%dc to %dhz@%dc\n",
2750  tread_impl.actual_samples_per_second,
2751  tread_impl.number_of_channels);
2752  }
2753 
2754 
2755  switch_core_codec_destroy(&codec);
2756 
2758  if (switch_core_codec_init(&codec,
2759  "L16",
2760  NULL,
2761  NULL,
2767  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
2769  goto end;
2770  }
2771  buffered = 1;
2773  } else {
2774  if (switch_core_codec_init(&codec,
2775  "L16",
2776  NULL,
2777  NULL,
2778  tread_impl.actual_samples_per_second,
2779  tread_impl.microseconds_per_packet / 1000,
2780  tread_impl.number_of_channels,
2783  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
2785  goto end;
2786  }
2787  if (buffered == 1) {
2788  buffered = 0;
2789  }
2790  }
2791 
2792  ep->read_impl = read_impl;
2793  ep->tread_impl = tread_impl;
2794  }
2795 
2796 
2798  uint32_t rlen = write_frame.datalen / 2 / ep->tread_impl.number_of_channels;
2799 
2800  switch_mux_channels((int16_t *) write_frame.data, rlen, ep->tread_impl.number_of_channels, ep->read_impl.number_of_channels);
2801  write_frame.datalen = rlen * 2 * ep->read_impl.number_of_channels;
2802  write_frame.samples = write_frame.datalen / 2;
2803  }
2804 
2805  if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
2806  break;
2807  }
2808 
2811 
2813  /* push just the number of samples worth of a packet. */
2814  break;
2815  }
2816  }
2818  }
2819  }
2820 
2821  end_loop:
2822 
2823  /* Tell the channel we are no longer going to be in a bridge */
2825  switch_core_session_receive_message(session, &msg);
2826 
2827  status = SWITCH_STATUS_SUCCESS;
2828  end:
2829 
2830  if (codec_initialized)
2831  switch_core_codec_destroy(&codec);
2832 
2833  if (bug) {
2834  switch_core_media_bug_remove(tsession, &bug);
2835  }
2836 
2837  if (ep) {
2838  if (ep->buffer) {
2840  }
2841 
2842  if (ep->r_buffer) {
2844  }
2845 
2846  if (ep->w_buffer) {
2848  }
2849  }
2850 
2851  switch_core_session_rwunlock(tsession);
2852 
2854  }
2855 
2856  return status;
2857 }
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#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:700
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:183
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:590
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)
switch_status_t switch_core_session_get_real_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
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.
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:56
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:179
#define zstr(x)
Definition: switch_utils.h:314
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:724
#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:70
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:998
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:68
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
#define switch_core_session_request_video_refresh(_s)
Definition: switch_core.h:2881
uint32_t rate
Definition: switch_frame.h:74
#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:885
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
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:54
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:1693
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:1247
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
Common return values.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:287
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&#39;s uuid.
Definition: switch_core.h:932
int switch_channel_state_change_pending(switch_channel_t *channel)
uint32_t samples
Definition: switch_frame.h:72
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
uint32_t channels
Definition: switch_frame.h:76
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&#39;s pool.
Definition: switch_core.h:696
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:693
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:936
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.
const char *const name
Definition: switch_cJSON.h:250
#define switch_channel_up_nosig(_channel)
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session&#39;s pool.
Definition: switch_core.h:719
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&#39;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.
static uint32_t switch_lcm(uint32_t x, uint32_t y)
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
#define SWITCH_READ_ACCEPTABLE(status)
#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_ivr_eavesdrop_update_display()

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

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

2246 {
2247  struct exec_cb_data *data = NULL;
2250 
2251  data = switch_core_session_alloc(session, sizeof(*data));
2252  data->var = switch_core_session_strdup(session, name);
2253  data->val = switch_core_session_strdup(session, number);
2254  data->caller = session;
2255 
2256  if (!switch_channel_test_app_flag_key("EAVESDROP", channel, 1)) {
2257  switch_channel_set_app_flag_key("EAVESDROP", channel, 1);
2258  status = switch_core_media_bug_exec_all(session, "eavesdrop", display_exec_cb, data);
2259  switch_channel_clear_app_flag_key("EAVESDROP", channel, 1);
2260  }
2261 
2262  return status;
2263 }
const char *const const double number
Definition: switch_cJSON.h:254
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&#39;s pool.
Definition: switch_core.h:696
const char *const name
Definition: switch_cJSON.h:250
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session&#39;s pool.
Definition: switch_core.h:719
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_ivr_enterprise_originate()

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,
switch_dial_handle_list_t hl 
)

Definition at line 1567 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::dh, enterprise_originate_ringback_thread(), enterprise_originate_thread(), switch_dial_handle_list_s::global_vars, switch_dial_handle_list_s::handle_idx, switch_dial_handle_list_s::handles, switch_event::headers, 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_clone(), switch_caller_profile_dup(), SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, SWITCH_CAUSE_LOSE_RACE, SWITCH_CAUSE_NO_ANSWER, SWITCH_CAUSE_NO_PICKUP, SWITCH_CAUSE_ORIGINATOR_CANCEL, 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_originatee_caller_profile(), switch_channel_set_originator_caller_profile(), 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_dial_handle_destroy(), switch_dial_handle_dup(), 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_event_merge(), 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_enterprise_orig_and_bridge(), and switch_ivr_originate().

1579 {
1580  int x_argc = 0;
1581  char *x_argv[MAX_PEERS] = { 0 };
1582  enterprise_originate_handle_t *hp = NULL, handles[MAX_PEERS] = { {0} };
1583  int i;
1584  switch_caller_profile_t *cp = NULL;
1585  switch_channel_t *channel = NULL;
1586  char *data = NULL;
1588  switch_threadattr_t *thd_attr = NULL;
1589  int running = 0, over = 0;
1592  switch_event_header_t *hi = NULL;
1593  struct ent_originate_ringback rb_data = { 0 };
1594  const char *ringback_data = NULL;
1595  switch_event_t *var_event = NULL;
1596  int getcause = 1;
1597 
1598  *cause = SWITCH_CAUSE_SUCCESS;
1599 
1601 
1602  if (zstr(bridgeto) && (!hl || hl->handle_idx == 0)) {
1604  getcause = 0;
1606  }
1607 
1608  if (!hl) {
1609  data = switch_core_strdup(pool, bridgeto);
1610  }
1611 
1612  if (session) {
1613  switch_caller_profile_t *cpp = NULL;
1614  channel = switch_core_session_get_channel(session);
1615  if ((cpp = switch_channel_get_caller_profile(channel))) {
1616  cp = switch_caller_profile_dup(pool, cpp);
1617  }
1618  }
1619 
1620  if (ovars) {
1621  var_event = ovars;
1622  } else {
1624  abort();
1625  }
1626  }
1627 
1628  if (session) {
1629  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ent_originate_aleg_uuid", switch_core_session_get_uuid(session));
1630  }
1631 
1632  if (channel) {
1633  const char *tmp_var = NULL;
1634 
1636 
1637  if ((tmp_var = switch_channel_get_variable(channel, "effective_ani"))) {
1638  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_ani", tmp_var);
1639  }
1640 
1641  if ((tmp_var = switch_channel_get_variable(channel, "effective_aniii"))) {
1642  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_aniii", tmp_var);
1643  }
1644 
1645  if ((tmp_var = switch_channel_get_variable(channel, "effective_caller_id_name"))) {
1646  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_name", tmp_var);
1647  }
1648 
1649  if ((tmp_var = switch_channel_get_variable(channel, "effective_caller_id_number"))) {
1650  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_number", tmp_var);
1651  }
1652  }
1653 
1654  /* strip leading spaces */
1655  while (data && *data && *data == ' ') {
1656  data++;
1657  }
1658 
1659  /* extract channel variables, allowing multiple sets of braces */
1660  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing ultra-global variables\n");
1661  while (data && *data == '<') {
1662  char *parsed = NULL;
1663 
1664  if (switch_event_create_brackets(data, '<', '>', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
1665  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
1667  }
1668 
1669  data = parsed;
1670  }
1671  if (hl && hl->global_vars) {
1672  switch_event_merge(var_event, hl->global_vars);
1673  }
1674 
1675  /* strip leading spaces (again) */
1676  while (data && *data && *data == ' ') {
1677  data++;
1678  }
1679 
1680  if (ovars && ovars != var_event) {
1681  for (hi = ovars->headers; hi; hi = hi->next) {
1683  }
1684  }
1685 
1686  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
1687 
1688  if (data) {
1689  if (!(x_argc = switch_separate_string_string(data, SWITCH_ENT_ORIGINATE_DELIM, x_argv, MAX_PEERS))) {
1691  getcause = 0;
1693  }
1694  } else if (hl) {
1695  x_argc = hl->handle_idx;
1696  }
1697 
1698  switch_threadattr_create(&thd_attr, pool);
1700 
1701  for (i = 0; i < x_argc; i++) {
1702  handles[i].session = session;
1703  handles[i].bleg = NULL;
1704  handles[i].cause = 0;
1705  handles[i].cancel_cause = 0;
1706  handles[i].bridgeto = x_argv[i];
1707  handles[i].timelimit_sec = timelimit_sec;
1708  handles[i].table = table;
1709  handles[i].cid_name_override = cid_name_override;
1710  handles[i].cid_num_override = cid_num_override;
1711  handles[i].caller_profile_override = cp;
1712  switch_event_dup(&handles[i].ovars, var_event);
1713  handles[i].flags = flags;
1714  if (hl) {
1715  switch_dial_handle_dup(&handles[i].dh, hl->handles[i]);
1716  }
1717  switch_mutex_init(&handles[i].mutex, SWITCH_MUTEX_NESTED, pool);
1718  switch_mutex_init(&handles[i].fence_mutex, SWITCH_MUTEX_NESTED, pool);
1719  switch_mutex_lock(handles[i].mutex);
1720  switch_thread_create(&handles[i].thread, thd_attr, enterprise_originate_thread, &handles[i], pool);
1721  }
1722 
1723  if (channel && !switch_channel_test_flag(channel, CF_PROXY_MODE) && !switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
1724  if (switch_channel_test_flag(channel, CF_ANSWERED)) {
1725  ringback_data = switch_channel_get_variable(channel, "transfer_ringback");
1726  }
1727 
1728  if (!ringback_data) {
1729  ringback_data = switch_channel_get_variable(channel, "ringback");
1730  }
1731 
1732  if (ringback_data || switch_channel_media_ready(channel)) {
1733  rb_data.ringback_data = ringback_data;
1734  rb_data.session = session;
1735  rb_data.running = 1;
1736  if (!switch_channel_media_ready(channel)) {
1738  goto done;
1739  }
1740  }
1741  switch_thread_create(&rb_data.thread, thd_attr, enterprise_originate_ringback_thread, &rb_data, pool);
1742  }
1743  }
1744 
1745 
1746  for (;;) {
1747  running = 0;
1748  over = 0;
1749 
1750  if (channel && !switch_channel_ready(channel)) {
1751  break;
1752  }
1753 
1754  if (cancel_cause && *cancel_cause > 0) {
1755  break;
1756  }
1757 
1758  for (i = 0; i < x_argc; i++) {
1759 
1760  switch_mutex_lock(handles[i].fence_mutex);
1761  if (handles[i].done == 0) {
1762  running++;
1763  } else if (handles[i].done == 1) {
1764  if (handles[i].status == SWITCH_STATUS_SUCCESS) {
1765  handles[i].done = 2;
1766  hp = &handles[i];
1767  switch_mutex_unlock(handles[i].fence_mutex);
1768  goto done;
1769  } else {
1770  handles[i].done = -1;
1771  }
1772  } else {
1773  over++;
1774  }
1775 
1776  switch_mutex_unlock(handles[i].fence_mutex);
1777 
1778  switch_yield(10000);
1779  }
1780 
1781  if (!running || over == x_argc) {
1782  break;
1783  }
1784  }
1785 
1786 
1787  done:
1788 
1789  if (hp) {
1790  *cause = hp->cause;
1791  getcause = 0;
1792  status = hp->status;
1793  *bleg = hp->bleg;
1794  if (*bleg) {
1796  switch_caller_profile_t *cloned_profile;
1797 
1798  if (session) {
1799  cloned_profile = switch_caller_profile_clone(*bleg, cp);
1800  switch_channel_set_originator_caller_profile(bchan, cloned_profile);
1801 
1802  cloned_profile = switch_caller_profile_clone(session, switch_channel_get_caller_profile(bchan));
1803  switch_channel_set_originatee_caller_profile(channel, cloned_profile);
1804  }
1805  }
1807  switch_thread_join(&tstatus, hp->thread);
1810  }
1811 
1812  for (i = 0; i < x_argc; i++) {
1813  if (hp == &handles[i]) {
1814  continue;
1815  }
1816 
1817  if (cancel_cause && *cancel_cause > 0) {
1818  handles[i].cancel_cause = *cancel_cause;
1819  } else {
1820  /* Was this call taken by another destination? */
1821  if (hp != NULL && hp->cause == SWITCH_CAUSE_SUCCESS) {
1822  /* Yes, the race was lost */
1823  handles[i].cancel_cause = SWITCH_CAUSE_LOSE_RACE;
1824  } else {
1825  /* No, something else happened, probably Originator Cancel */
1826  handles[i].cancel_cause = SWITCH_CAUSE_ORIGINATOR_CANCEL;
1827  }
1828  }
1829  }
1830 
1831  for (i = 0; i < x_argc; i++) {
1832 
1833  if (hp == &handles[i]) {
1834  continue;
1835  }
1836 
1837  if (getcause && channel && handles[i].cause && handles[i].cause != SWITCH_CAUSE_SUCCESS) {
1838  switch_channel_handle_cause(channel, handles[i].cause);
1839  }
1840 
1841  switch_mutex_unlock(handles[i].mutex);
1842 
1843  if (getcause && *cause != handles[i].cause && handles[i].cause != SWITCH_CAUSE_LOSE_RACE && handles[i].cause != SWITCH_CAUSE_NO_PICKUP) {
1844  *cause = handles[i].cause;
1845  getcause++;
1846  }
1847 
1848  switch_thread_join(&tstatus, handles[i].thread);
1849  switch_event_destroy(&handles[i].ovars);
1850  switch_dial_handle_destroy(&handles[i].dh);
1851  }
1852 
1853  if (channel && rb_data.thread) {
1855  switch_thread_join(&tstatus, rb_data.thread);
1857  }
1858 
1859 
1860  end:
1861 
1862  if (getcause == 1 && *cause == SWITCH_CAUSE_SUCCESS) {
1863  *cause = SWITCH_CAUSE_NO_ANSWER;
1864  }
1865 
1866  if (channel) {
1867  if (*cause == SWITCH_CAUSE_SUCCESS) {
1868  switch_channel_set_variable(channel, "originate_disposition", "success");
1869  } else {
1870  switch_channel_set_variable(channel, "originate_disposition", "failure");
1871  switch_channel_set_variable(channel, "hangup_cause", switch_channel_cause2str(*cause));
1872  }
1873  }
1874 
1875 
1876  if (var_event && var_event != ovars) {
1877  switch_event_destroy(&var_event);
1878  }
1879 
1881 
1882  return status;
1883 
1884 }
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
#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:733
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:683
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
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
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.
#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:486
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:314
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
_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:998
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:308
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:584
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:293
#define SWITCH_ENT_ORIGINATE_DELIM
Definition: switch_types.h:47
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1379
void switch_channel_set_originator_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
Set the given channel&#39;s originator caller profile.
#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:386
static int32_t running
void switch_dial_handle_destroy(switch_dial_handle_t **handle)
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:287
struct switch_event_header * next
Definition: switch_event.h:76
void switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
Set the given channel&#39;s originatee caller profile.
#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.
static switch_status_t switch_dial_handle_dup(switch_dial_handle_t **handle, switch_dial_handle_t *todup)
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:665
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:698
struct fspr_pool_t switch_memory_pool_t
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)
switch_dial_handle_t * handles[MAX_PEERS]
#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&#39;s caller profile.
switch_event_header_t * headers
Definition: switch_event.h:90
#define SWITCH_EXPORT_VARS_VARIABLE
Definition: switch_types.h:195
void switch_channel_handle_cause(switch_channel_t *channel, switch_call_cause_t cause)

◆ switch_ivr_generate_json_cdr()

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 3335 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_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_app_log::stamp, SWITCH_CALL_DIRECTION_OUTBOUND, switch_channel_direction(), switch_channel_get_caller_profile(), switch_channel_get_cap_string(), switch_channel_get_flag_string(), switch_channel_get_state(), switch_channel_state_name(), switch_core_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().

3336 {
3337  cJSON *cdr = cJSON_CreateObject();
3339  switch_caller_profile_t *caller_profile;
3340  cJSON *variables, *j_main_cp, *j_caller_profile, *j_caller_extension, *j_caller_extension_apps, *j_times, *j_application,
3341  *j_callflow, *j_profile, *j_inner_extension, *j_app_log, *j_apps, *j_o, *j_o_profiles, *j_channel_data, *callStats;
3342  switch_app_log_t *app_log;
3343  char tmp[512], *f;
3344 
3345  cJSON_AddItemToObject(cdr, "core-uuid", cJSON_CreateString(switch_core_get_uuid()));
3346  cJSON_AddItemToObject(cdr, "switchname", cJSON_CreateString(switch_core_get_switchname()));
3347  j_channel_data = cJSON_CreateObject();
3348 
3349  cJSON_AddItemToObject(cdr, "channel_data", j_channel_data);
3350 
3351  cJSON_AddItemToObject(j_channel_data, "state", cJSON_CreateString((char *) switch_channel_state_name(switch_channel_get_state(channel))));
3352  cJSON_AddItemToObject(j_channel_data, "direction", cJSON_CreateString(switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"));
3353 
3354  switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel));
3355  cJSON_AddItemToObject(j_channel_data, "state_number", cJSON_CreateString((char *) tmp));
3356 
3357  if ((f = switch_channel_get_flag_string(channel))) {
3358  cJSON_AddItemToObject(j_channel_data, "flags", cJSON_CreateString((char *) f));
3359  free(f);
3360  }
3361 
3362  if ((f = switch_channel_get_cap_string(channel))) {
3363  cJSON_AddItemToObject(j_channel_data, "caps", cJSON_CreateString((char *) f));
3364  free(f);
3365  }
3366 
3367  callStats = cJSON_CreateObject();
3368  cJSON_AddItemToObject(cdr, "callStats", callStats);
3371 
3372  variables = cJSON_CreateObject();
3373  cJSON_AddItemToObject(cdr, "variables", variables);
3374  switch_ivr_set_json_chan_vars(variables, channel, urlencode);
3375 
3376 
3377  if ((app_log = switch_core_session_get_app_log(session))) {
3378  switch_app_log_t *ap;
3379 
3380  j_app_log = cJSON_CreateObject();
3381  j_apps = cJSON_CreateArray();
3382 
3383  cJSON_AddItemToObject(cdr, "app_log", j_app_log);
3384  cJSON_AddItemToObject(j_app_log, "applications", j_apps);
3385 
3386  for (ap = app_log; ap; ap = ap->next) {
3387  j_application = cJSON_CreateObject();
3388 
3389  cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->app));
3390  cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(ap->arg));
3391  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, ap->stamp);
3392  cJSON_AddItemToObject(j_application, "app_stamp", cJSON_CreateString(tmp));
3393 
3394  cJSON_AddItemToArray(j_apps, j_application);
3395  }
3396  }
3397 
3398 
3399  caller_profile = switch_channel_get_caller_profile(channel);
3400 
3401  j_callflow = cJSON_CreateArray();
3402  cJSON_AddItemToObject(cdr, "callflow", j_callflow);
3403 
3404  while (caller_profile) {
3405 
3406  j_profile = cJSON_CreateObject();
3407 
3408  if (!zstr(caller_profile->dialplan)) {
3409  cJSON_AddItemToObject(j_profile, "dialplan", cJSON_CreateString((char *)caller_profile->dialplan));
3410  }
3411 
3412  if (!zstr(caller_profile->profile_index)) {
3413  cJSON_AddItemToObject(j_profile, "profile_index", cJSON_CreateString((char *)caller_profile->profile_index));
3414  }
3415 
3416  if (caller_profile->caller_extension) {
3418 
3419  j_caller_extension = cJSON_CreateObject();
3420  j_caller_extension_apps = cJSON_CreateArray();
3421 
3422  cJSON_AddItemToObject(j_profile, "extension", j_caller_extension);
3423 
3424  cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(caller_profile->caller_extension->extension_name));
3425  cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(caller_profile->caller_extension->extension_number));
3426  cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps);
3427 
3428  if (caller_profile->caller_extension->current_application) {
3429  cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(caller_profile->caller_extension->current_application->application_name));
3430  }
3431 
3432  for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
3433  j_application = cJSON_CreateObject();
3434 
3435  cJSON_AddItemToArray(j_caller_extension_apps, j_application);
3436 
3437  if (ap == caller_profile->caller_extension->current_application) {
3438  cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true"));
3439  }
3440  cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name));
3441  cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)));
3442  }
3443 
3444  if (caller_profile->caller_extension->children) {
3445  switch_caller_profile_t *cp = NULL;
3446  j_inner_extension = cJSON_CreateArray();
3447  cJSON_AddItemToObject(j_caller_extension, "sub_extensions", j_inner_extension);
3448  for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {
3449 
3450  if (!cp->caller_extension) {
3451  continue;
3452  }
3453 
3454  j_caller_extension = cJSON_CreateObject();
3455  cJSON_AddItemToArray(j_inner_extension, j_caller_extension);
3456 
3457  cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(cp->caller_extension->extension_name));
3458  cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(cp->caller_extension->extension_number));
3459 
3460  cJSON_AddItemToObject(j_caller_extension, "dialplan", cJSON_CreateString((char *)cp->dialplan));
3461 
3463  cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(cp->caller_extension->current_application->application_name));
3464  }
3465 
3466  j_caller_extension_apps = cJSON_CreateArray();
3467  cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps);
3468  for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
3469  j_application = cJSON_CreateObject();
3470  cJSON_AddItemToArray(j_caller_extension_apps, j_application);
3471 
3472  if (ap == cp->caller_extension->current_application) {
3473  cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true"));
3474  }
3475  cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name));
3476  cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)));
3477  }
3478  }
3479  }
3480  }
3481 
3482  j_main_cp = cJSON_CreateObject();
3483  cJSON_AddItemToObject(j_profile, "caller_profile", j_main_cp);
3484 
3485  switch_ivr_set_json_profile_data(j_main_cp, caller_profile);
3486 
3487  if (caller_profile->originator_caller_profile) {
3488  switch_caller_profile_t *cp = NULL;
3489 
3490  j_o = cJSON_CreateObject();
3491  cJSON_AddItemToObject(j_main_cp, "originator", j_o);
3492 
3493  j_o_profiles = cJSON_CreateArray();
3494  cJSON_AddItemToObject(j_o, "originator_caller_profiles", j_o_profiles);
3495 
3496  for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
3497  j_caller_profile = cJSON_CreateObject();
3498  cJSON_AddItemToArray(j_o_profiles, j_caller_profile);
3499 
3500  switch_ivr_set_json_profile_data(j_caller_profile, cp);
3501  }
3502  }
3503 
3504  if (caller_profile->originatee_caller_profile) {
3505  switch_caller_profile_t *cp = NULL;
3506 
3507  j_o = cJSON_CreateObject();
3508  cJSON_AddItemToObject(j_main_cp, "originatee", j_o);
3509 
3510  j_o_profiles = cJSON_CreateArray();
3511  cJSON_AddItemToObject(j_o, "originatee_caller_profiles", j_o_profiles);
3512 
3513  for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {
3514  j_caller_profile = cJSON_CreateObject();
3515  cJSON_AddItemToArray(j_o_profiles, j_caller_profile);
3516 
3517  switch_ivr_set_json_profile_data(j_caller_profile, cp);
3518  }
3519  }
3520 
3521  if (caller_profile->times) {
3522 
3523  j_times = cJSON_CreateObject();
3524  cJSON_AddItemToObject(j_profile, "times", j_times);
3525 
3526  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
3527  cJSON_AddItemToObject(j_times, "created_time", cJSON_CreateString(tmp));
3528 
3529  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
3530  cJSON_AddItemToObject(j_times, "profile_created_time", cJSON_CreateString(tmp));
3531 
3532  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
3533  cJSON_AddItemToObject(j_times, "progress_time", cJSON_CreateString(tmp));
3534 
3535  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
3536  cJSON_AddItemToObject(j_times, "progress_media_time", cJSON_CreateString(tmp));
3537 
3538  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
3539  cJSON_AddItemToObject(j_times, "answered_time", cJSON_CreateString(tmp));
3540 
3541  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
3542  cJSON_AddItemToObject(j_times, "bridged_time", cJSON_CreateString(tmp));
3543 
3544  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->last_hold);
3545  cJSON_AddItemToObject(j_times, "last_hold_time", cJSON_CreateString(tmp));
3546 
3547  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum);
3548  cJSON_AddItemToObject(j_times, "hold_accum_time", cJSON_CreateString(tmp));
3549 
3550  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
3551  cJSON_AddItemToObject(j_times, "hangup_time", cJSON_CreateString(tmp));
3552 
3553  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
3554  cJSON_AddItemToObject(j_times, "resurrect_time", cJSON_CreateString(tmp));
3555 
3556  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->transferred);
3557  cJSON_AddItemToObject(j_times, "transfer_time", cJSON_CreateString(tmp));
3558 
3559  }
3560  cJSON_AddItemToArray(j_callflow, j_profile);
3561  caller_profile = caller_profile->next;
3562  }
3563 
3564  *json_cdr = cdr;
3565 
3566  return SWITCH_STATUS_SUCCESS;
3567 
3568 }
char * switch_channel_get_cap_string(switch_channel_t *channel)
switch_time_t stamp
Definition: switch_core.h:62
const char * switch_core_get_switchname(void)
Definition: switch_core.c:361
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
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:3211
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:314
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:495
switch_caller_application_t * applications
struct switch_caller_profile * children
#define SWITCH_TIME_T_FMT
switch_time_t profile_created
const char * profile_index
struct switch_caller_profile * originator_caller_profile
switch_caller_application_t * current_application
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
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
static void switch_ivr_set_json_chan_vars(cJSON *json, switch_channel_t *channel, switch_bool_t urlencode)
Definition: switch_ivr.c:3304
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel&#39;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:3232
switch_time_t progress_media
struct switch_app_log * next
Definition: switch_core.h:63
struct switch_caller_extension * caller_extension

◆ switch_ivr_generate_xml_cdr()

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 2862 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_core_session_get_text_buffer(), 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().

2863 {
2865  switch_caller_profile_t *caller_profile;
2866  switch_xml_t call_stats, variables, cdr, x_main_cp, x_caller_profile, x_caller_extension, x_times, time_tag,
2867  x_application, x_callflow, x_inner_extension, x_apps, x_o, x_channel_data, x_field, xhr, x_hold;
2868  switch_app_log_t *app_log;
2869  char tmp[512], *f;
2870  int cdr_off = 0, cd_off = 0;
2871  switch_hold_record_t *hold_record = switch_channel_get_hold_record(channel), *hr;
2872  const char *text_buffer = NULL;
2873 
2874  if (*xml_cdr) {
2875  cdr = *xml_cdr;
2876  } else {
2877  if (!(cdr = switch_xml_new("cdr"))) {
2878  return SWITCH_STATUS_SUCCESS;
2879  }
2880  }
2881 
2882  switch_xml_set_attr_d(cdr, "core-uuid", switch_core_get_uuid());
2883  switch_xml_set_attr_d(cdr, "switchname", switch_core_get_switchname());
2884 
2885  if (!(x_channel_data = switch_xml_add_child_d(cdr, "channel_data", cdr_off++))) {
2886  goto error;
2887  }
2888 
2889  x_field = switch_xml_add_child_d(x_channel_data, "state", cd_off++);
2891 
2892  x_field = switch_xml_add_child_d(x_channel_data, "direction", cd_off++);
2893  switch_xml_set_txt_d(x_field, switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
2894 
2895 
2896  if ((text_buffer = switch_core_session_get_text_buffer(session))) {
2897  x_field = switch_xml_add_child_d(x_channel_data, "textlog", cd_off++);
2898  switch_xml_set_txt_d(x_field, text_buffer);
2899  }
2900 
2901  x_field = switch_xml_add_child_d(x_channel_data, "state_number", cd_off++);
2902  switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel));
2903  switch_xml_set_txt_d(x_field, tmp);
2904 
2905  if ((f = switch_channel_get_flag_string(channel))) {
2906  x_field = switch_xml_add_child_d(x_channel_data, "flags", cd_off++);
2907  switch_xml_set_txt_d(x_field, f);
2908  free(f);
2909  }
2910 
2911  if ((f = switch_channel_get_cap_string(channel))) {
2912  x_field = switch_xml_add_child_d(x_channel_data, "caps", cd_off++);
2913  switch_xml_set_txt_d(x_field, f);
2914  free(f);
2915  }
2916 
2917  if (!(call_stats = switch_xml_add_child_d(cdr, "call-stats", cdr_off++))) {
2918  goto error;
2919  }
2920 
2921  switch_ivr_set_xml_call_stats(call_stats, session, 0, SWITCH_MEDIA_TYPE_AUDIO);
2922  switch_ivr_set_xml_call_stats(call_stats, session, 0, SWITCH_MEDIA_TYPE_VIDEO);
2923 
2924 
2925  if (!(variables = switch_xml_add_child_d(cdr, "variables", cdr_off++))) {
2926  goto error;
2927  }
2928 
2929  switch_ivr_set_xml_chan_vars(variables, channel, 0);
2930 
2931 
2932  if ((app_log = switch_core_session_get_app_log(session))) {
2933  int app_off = 0;
2934  switch_app_log_t *ap;
2935 
2936  if (!(x_apps = switch_xml_add_child_d(cdr, "app_log", cdr_off++))) {
2937  goto error;
2938  }
2939  for (ap = app_log; ap; ap = ap->next) {
2940  char tmp[128];
2941 
2942  if (!(x_application = switch_xml_add_child_d(x_apps, "application", app_off++))) {
2943  goto error;
2944  }
2945 
2946  switch_xml_set_attr_d(x_application, "app_name", ap->app);
2947  switch_xml_set_attr_d(x_application, "app_data", ap->arg);
2948 
2949  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, ap->stamp);
2950  switch_xml_set_attr_d_buf(x_application, "app_stamp", tmp);
2951  }
2952  }
2953 
2954  if (hold_record) {
2955  int cf_off = 0;
2956 
2957  if (!(xhr = switch_xml_add_child_d(cdr, "hold-record", cdr_off++))) {
2958  goto error;
2959  }
2960 
2961  for (hr = hold_record; hr; hr = hr->next) {
2962  char *t = tmp;
2963  if (!(x_hold = switch_xml_add_child_d(xhr, "hold", cf_off++))) {
2964  goto error;
2965  }
2966 
2967  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, hr->on);
2968  switch_xml_set_attr_d(x_hold, "on", t);
2969 
2970  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, hr->off);
2971  switch_xml_set_attr_d(x_hold, "off", t);
2972 
2973  if (hr->uuid) {
2974  switch_xml_set_attr_d(x_hold, "bridged-to", hr->uuid);
2975  }
2976 
2977 
2978  }
2979 
2980 
2981  }
2982 
2983 
2984 
2985  caller_profile = switch_channel_get_caller_profile(channel);
2986 
2987  while (caller_profile) {
2988  int cf_off = 0;
2989  int cp_off = 0;
2990 
2991  if (!(x_callflow = switch_xml_add_child_d(cdr, "callflow", cdr_off++))) {
2992  goto error;
2993  }
2994 
2995  if (!zstr(caller_profile->dialplan)) {
2996  switch_xml_set_attr_d(x_callflow, "dialplan", caller_profile->dialplan);
2997  }
2998 
2999  if (!zstr(caller_profile->uuid_str)) {
3000  switch_xml_set_attr_d(x_callflow, "unique-id", caller_profile->uuid_str);
3001  }
3002 
3003  if (!zstr(caller_profile->clone_of)) {
3004  switch_xml_set_attr_d(x_callflow, "clone-of", caller_profile->clone_of);
3005  }
3006 
3007  if (!zstr(caller_profile->profile_index)) {
3008  switch_xml_set_attr_d(x_callflow, "profile_index", caller_profile->profile_index);
3009  }
3010 
3011  if (caller_profile->caller_extension) {
3013  int app_off = 0;
3014 
3015  if (!(x_caller_extension = switch_xml_add_child_d(x_callflow, "extension", cf_off++))) {
3016  goto error;
3017  }
3018 
3019  switch_xml_set_attr_d(x_caller_extension, "name", caller_profile->caller_extension->extension_name);
3020  switch_xml_set_attr_d(x_caller_extension, "number", caller_profile->caller_extension->extension_number);
3021  if (caller_profile->caller_extension->current_application) {
3022  switch_xml_set_attr_d(x_caller_extension, "current_app", caller_profile->caller_extension->current_application->application_name);
3023  }
3024 
3025  for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
3026  if (!(x_application = switch_xml_add_child_d(x_caller_extension, "application", app_off++))) {
3027  goto error;
3028  }
3029  if (ap == caller_profile->caller_extension->current_application) {
3030  switch_xml_set_attr_d(x_application, "last_executed", "true");
3031  }
3032  switch_xml_set_attr_d(x_application, "app_name", ap->application_name);
3033  switch_xml_set_attr_d(x_application, "app_data", ap->application_data);
3034  }
3035 
3036  if (caller_profile->caller_extension->children) {
3037  switch_caller_profile_t *cp = NULL;
3038  int i_off = 0, i_app_off = 0;
3039  for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {
3040 
3041  if (!cp->caller_extension) {
3042  continue;
3043  }
3044  if (!(x_inner_extension = switch_xml_add_child_d(x_caller_extension, "sub_extensions", app_off++))) {
3045  goto error;
3046  }
3047 
3048  if (!(x_caller_extension = switch_xml_add_child_d(x_inner_extension, "extension", i_off++))) {
3049  goto error;
3050  }
3051  switch_xml_set_attr_d(x_caller_extension, "name", cp->caller_extension->extension_name);
3052  switch_xml_set_attr_d(x_caller_extension, "number", cp->caller_extension->extension_number);
3053  switch_xml_set_attr_d(x_caller_extension, "dialplan", cp->dialplan);
3055  switch_xml_set_attr_d(x_caller_extension, "current_app", cp->caller_extension->current_application->application_name);
3056  }
3057 
3058  for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
3059  if (!(x_application = switch_xml_add_child_d(x_caller_extension, "application", i_app_off++))) {
3060  goto error;
3061  }
3062  if (ap == cp->caller_extension->current_application) {
3063  switch_xml_set_attr_d(x_application, "last_executed", "true");
3064  }
3065  switch_xml_set_attr_d(x_application, "app_name", ap->application_name);
3066  switch_xml_set_attr_d(x_application, "app_data", ap->application_data);
3067  }
3068  }
3069  }
3070  }
3071 
3072  if (!(x_main_cp = switch_xml_add_child_d(x_callflow, "caller_profile", cf_off++))) {
3073  goto error;
3074  }
3075 
3076  cp_off += switch_ivr_set_xml_profile_data(x_main_cp, caller_profile, 0);
3077 
3078  if (caller_profile->origination_caller_profile) {
3079  switch_caller_profile_t *cp = NULL;
3080  int off = 0;
3081  if (!(x_o = switch_xml_add_child_d(x_main_cp, "origination", cp_off++))) {
3082  goto error;
3083  }
3084 
3085  for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) {
3086  if (!(x_caller_profile = switch_xml_add_child_d(x_o, "origination_caller_profile", off++))) {
3087  goto error;
3088  }
3089  switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
3090  }
3091  }
3092 
3093  if (caller_profile->originator_caller_profile) {
3094  switch_caller_profile_t *cp = NULL;
3095  int off = 0;
3096  if (!(x_o = switch_xml_add_child_d(x_main_cp, "originator", cp_off++))) {
3097  goto error;
3098  }
3099 
3100  for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
3101  if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originator_caller_profile", off++))) {
3102  goto error;
3103  }
3104  switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
3105  }
3106  }
3107 
3108  if (caller_profile->originatee_caller_profile) {
3109  switch_caller_profile_t *cp = NULL;
3110  int off = 0;
3111  if (!(x_o = switch_xml_add_child_d(x_main_cp, "originatee", cp_off++))) {
3112  goto error;
3113  }
3114  for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {
3115  if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originatee_caller_profile", off++))) {
3116  goto error;
3117  }
3118  switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
3119  }
3120  }
3121 
3122  if (caller_profile->times) {
3123  int t_off = 0;
3124  if (!(x_times = switch_xml_add_child_d(x_callflow, "times", cf_off++))) {
3125  goto error;
3126  }
3127  if (!(time_tag = switch_xml_add_child_d(x_times, "created_time", t_off++))) {
3128  goto error;
3129  }
3130  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
3131  switch_xml_set_txt_d(time_tag, tmp);
3132 
3133  if (!(time_tag = switch_xml_add_child_d(x_times, "profile_created_time", t_off++))) {
3134  goto error;
3135  }
3136  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
3137  switch_xml_set_txt_d(time_tag, tmp);
3138 
3139  if (!(time_tag = switch_xml_add_child_d(x_times, "progress_time", t_off++))) {
3140  goto error;
3141  }
3142  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
3143  switch_xml_set_txt_d(time_tag, tmp);
3144 
3145 
3146  if (!(time_tag = switch_xml_add_child_d(x_times, "progress_media_time", t_off++))) {
3147  goto error;
3148  }
3149  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
3150  switch_xml_set_txt_d(time_tag, tmp);
3151 
3152  if (!(time_tag = switch_xml_add_child_d(x_times, "answered_time", t_off++))) {
3153  goto error;
3154  }
3155  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
3156  switch_xml_set_txt_d(time_tag, tmp);
3157 
3158  if (!(time_tag = switch_xml_add_child_d(x_times, "bridged_time", t_off++))) {
3159  goto error;
3160  }
3161  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
3162  switch_xml_set_txt_d(time_tag, tmp);
3163 
3164  if (!(time_tag = switch_xml_add_child_d(x_times, "last_hold_time", t_off++))) {
3165  goto error;
3166  }
3167  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->last_hold);
3168  switch_xml_set_txt_d(time_tag, tmp);
3169 
3170  if (!(time_tag = switch_xml_add_child_d(x_times, "hold_accum_time", t_off++))) {
3171  goto error;
3172  }
3173  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum);
3174  switch_xml_set_txt_d(time_tag, tmp);
3175 
3176  if (!(time_tag = switch_xml_add_child_d(x_times, "hangup_time", t_off++))) {
3177  goto error;
3178  }
3179  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
3180  switch_xml_set_txt_d(time_tag, tmp);
3181 
3182  if (!(time_tag = switch_xml_add_child_d(x_times, "resurrect_time", t_off++))) {
3183  goto error;
3184  }
3185  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
3186  switch_xml_set_txt_d(time_tag, tmp);
3187 
3188  if (!(time_tag = switch_xml_add_child_d(x_times, "transfer_time", t_off++))) {
3189  goto error;
3190  }
3191  switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->transferred);
3192  switch_xml_set_txt_d(time_tag, tmp);
3193  }
3194 
3195  caller_profile = caller_profile->next;
3196  }
3197 
3198  *xml_cdr = cdr;
3199 
3200  return SWITCH_STATUS_SUCCESS;
3201 
3202  error:
3203 
3204  if (cdr) {
3205  switch_xml_free(cdr);
3206  }
3207 
3208  return SWITCH_STATUS_FALSE;
3209 }
char * switch_channel_get_cap_string(switch_channel_t *channel)
switch_xml_t switch_xml_set_attr_d_buf(switch_xml_t xml, const char *name, const char *value)
Wrapper for switch_xml_set_attr() that strdup()s name/value. Value cannot be NULL.
Definition: switch_xml.c:3085
switch_xml_t switch_xml_add_child_d(_In_ switch_xml_t xml, _In_z_ const char *name, _In_ switch_size_t off)
wrapper for switch_xml_add_child() that strdup()s name
switch_time_t stamp
Definition: switch_core.h:62
const char * switch_core_get_switchname(void)
Definition: switch_core.c:361
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:2599
Call Specific Data.
Definition: switch_caller.h:73
switch_xml_t switch_xml_set_attr_d(switch_xml_t xml, const char *name, const char *value)
Wrapper for switch_xml_set_attr() that strdup()s name/value. Value cannot be NULL.
Definition: switch_xml.c:3077
struct switch_hold_record_s * next
Definition: switch_core.h:78
switch_hold_record_t * switch_channel_get_hold_record(switch_channel_t *channel)
struct switch_caller_profile * originatee_caller_profile
An Abstract Representation of a dialplan Application.
A representation of an XML tree.
Definition: switch_xml.h:79
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
switch_xml_t switch_xml_set_txt_d(switch_xml_t xml, const char *txt)
wrapper for switch_xml_set_txt() that strdup()s txt \ sets the character content for the given tag an...
Definition: switch_xml.c:3005
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:2715
#define zstr(x)
Definition: switch_utils.h:314
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.
Definition: cJSON.c:68
char * switch_core_get_uuid(void)
Retrieve the unique identifier from the core.
Definition: switch_core.c:495
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
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:2838
const char * switch_core_session_get_text_buffer(switch_core_session_t *session)
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel&#39;s caller profile.
switch_time_t progress_media
struct switch_app_log * next
Definition: switch_core.h:63
struct switch_caller_extension * caller_extension

◆ switch_ivr_gentones()

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 1073 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, arg_recursion_check_start, arg_recursion_check_stop, switch_input_args_t::buf, switch_frame::buflen, switch_input_args_t::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, switch_input_args_t::dmachine, switch_input_args_t::input_callback, memset(), switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, teletone_generation_session::rate, switch_input_args_t::read_frame_callback, 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_input_args_t::user_data.

Referenced by enterprise_originate_ringback_thread().

1074 {
1076  switch_dtmf_t dtmf = { 0 };
1077  switch_buffer_t *audio_buffer;
1078  switch_frame_t *read_frame = NULL;
1079  switch_codec_t write_codec = { 0 };
1080  switch_frame_t write_frame = { 0 };
1083  switch_codec_implementation_t read_impl = { 0 };
1084  switch_core_session_get_read_impl(session, &read_impl);
1085 
1087  return SWITCH_STATUS_FALSE;
1088  }
1089 
1090  if (switch_core_codec_init(&write_codec,
1091  "L16",
1092  NULL,
1093  NULL,
1094  read_impl.actual_samples_per_second,
1095  read_impl.microseconds_per_packet / 1000,
1098 
1099  return SWITCH_STATUS_FALSE;
1100  }
1101 
1103 
1104  memset(&ts, 0, sizeof(ts));
1105  write_frame.codec = &write_codec;
1106  write_frame.data = data;
1107  write_frame.buflen = sizeof(data);
1108 
1109  switch_buffer_create_dynamic(&audio_buffer, 512, 1024, 0);
1110  teletone_init_session(&ts, 0, teletone_handler, audio_buffer);
1111  ts.rate = read_impl.actual_samples_per_second;
1112  ts.channels = read_impl.number_of_channels;
1113  teletone_run(&ts, script);
1114 
1115  if (loops) {
1116  switch_buffer_set_loops(audio_buffer, loops);
1117  }
1118 
1119  for (;;) {
1120  switch_status_t status;
1121 
1122  if (!switch_channel_ready(channel)) {
1123  break;
1124  }
1125 
1126  if (switch_channel_test_flag(channel, CF_BREAK)) {
1128  break;
1129  }
1130 
1131  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1132 
1133  if (!SWITCH_READ_ACCEPTABLE(status)) {
1134  break;
1135  }
1136 
1137  if (args && args->dmachine) {
1138  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1139  break;
1140  }
1141  }
1142 
1143  if (args && (args->read_frame_callback)) {
1144  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
1145  break;
1146  }
1147  }
1148 
1149  switch_ivr_parse_all_events(session);
1150 
1151  if (args) {
1152  /*
1153  dtmf handler function you can hook up to be executed when a digit is dialed during gentones
1154  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
1155  */
1156  if (switch_channel_has_dtmf(channel)) {
1157  if (!args->input_callback && !args->buf && !args->dmachine) {
1158  break;
1159  }
1160  switch_channel_dequeue_dtmf(channel, &dtmf);
1161 
1162  if (args->dmachine) {
1163  char ds[2] = {dtmf.digit, '\0'};
1164  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
1165  break;
1166  }
1167  }
1168 
1169  if (args->input_callback) {
1170  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
1171  } else if (args->buf) {
1172  *((char *) args->buf) = dtmf.digit;
1173  status = SWITCH_STATUS_BREAK;
1174  }
1175  }
1176 
1177  if (args->input_callback) {
1178  switch_event_t *event;
1179 
1181  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
1182  if (ostatus != SWITCH_STATUS_SUCCESS) {
1183  status = ostatus;
1184  }
1185  switch_event_destroy(&event);
1186  }
1187  }
1188 
1189  if (status != SWITCH_STATUS_SUCCESS) {
1190  break;
1191  }
1192  }
1193 
1194  if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(audio_buffer, write_frame.data, read_impl.decoded_bytes_per_packet)) <= 0) {
1195  break;
1196  }
1197 
1198  write_frame.samples = write_frame.datalen / 2;
1199 
1201  break;
1202  }
1203  }
1204 
1205  switch_core_codec_destroy(&write_codec);
1206  switch_buffer_destroy(&audio_buffer);
1208 
1210 
1211  return SWITCH_STATUS_SUCCESS;
1212 }
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:590
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:913
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:56
uint8_t switch_byte_t
Definition: switch_types.h:256
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:70
uint32_t datalen
Definition: switch_frame.h:68
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:54
#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:1693
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:72
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)
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_ivr_hold()

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 1525 of file switch_ivr.c.

References CCS_HELD, 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_callstate(), switch_channel_get_hold_music(), switch_channel_get_partner_uuid(), SWITCH_CHANNEL_SESSION_LOG, 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_log_printf(), SWITCH_LOG_WARNING, SWITCH_MESSAGE_INDICATE_HOLD, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_hold_toggle_uuid(), and switch_ivr_hold_uuid().

1526 {
1527  switch_core_session_message_t msg = { 0 };
1529  const char *stream;
1530  const char *other_uuid;
1531  switch_event_t *event;
1532 
1533  if (channel) {
1534  switch_channel_callstate_t callstate;
1535 
1536  callstate = switch_channel_get_callstate(channel);
1537  if (callstate == CCS_HELD) {
1538  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Call is already on hold. No need to hold again.\n");
1539  return SWITCH_STATUS_FALSE;
1540  }
1541  }
1542 
1544  msg.string_arg = message;
1545  msg.from = __FILE__;
1546 
1547  switch_channel_set_flag(channel, CF_HOLD);
1549 
1550  switch_core_session_receive_message(session, &msg);
1551 
1552  if (moh && (stream = switch_channel_get_hold_music(channel))) {
1553  if ((other_uuid = switch_channel_get_partner_uuid(channel))) {
1554  switch_ivr_broadcast(other_uuid, stream, SMF_ECHO_ALEG | SMF_LOOP);
1555  }
1556  }
1557 
1559  switch_channel_event_set_data(channel, event);
1560  switch_event_fire(&event);
1561  }
1562 
1563 
1564  return SWITCH_STATUS_SUCCESS;
1565 }
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
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:179
_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)
switch_channel_callstate_t
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
#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:384
#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_channel_callstate_t switch_channel_get_callstate(switch_channel_t *channel)

◆ switch_ivr_hold_toggle_uuid()

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 1580 of file switch_ivr.c.

References CCS_ACTIVE, CCS_HELD, CCS_UNHELD, 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.

1581 {
1583  switch_channel_t *channel;
1584  switch_channel_callstate_t callstate;
1586 
1587  if ((session = switch_core_session_locate(uuid))) {
1588  if ((channel = switch_core_session_get_channel(session))) {
1589  callstate = switch_channel_get_callstate(channel);
1590 
1591  if (callstate == CCS_ACTIVE || callstate == CCS_UNHELD) {
1592  status = switch_ivr_hold(session, message, moh);
1593  } else if (callstate == CCS_HELD) {
1594  status = switch_ivr_unhold(session);
1595  }
1596  }
1598  }
1599 
1600  return status;
1601 }
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:1525
_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
Common return values.
switch_status_t switch_ivr_unhold(switch_core_session_t *session)
Signal the session with a protocol specific unhold message.
Definition: switch_ivr.c:1603
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932
switch_channel_callstate_t switch_channel_get_callstate(switch_channel_t *channel)

◆ switch_ivr_hold_uuid()

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 1567 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().

1568 {
1571 
1572  if ((session = switch_core_session_locate(uuid))) {
1573  status = switch_ivr_hold(session, message, moh);
1575  }
1576 
1577  return status;
1578 }
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:1525
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
Common return values.
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932

◆ switch_ivr_inband_dtmf_generate_session()

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 4090 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.

4091 {
4093  switch_media_bug_t *bug;
4094  switch_status_t status;
4096 
4097  if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
4098  return SWITCH_STATUS_FALSE;
4099  }
4100 
4101  if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
4102  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not install inband dtmf generate. Media not enabled on channel\n");
4103  return status;
4104  }
4105 
4106  if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
4107  return SWITCH_STATUS_MEMERR;
4108  }
4109 
4110  pvt->session = session;
4111  pvt->read = !!read_stream;
4112 
4113  if ((status = switch_core_media_bug_add(session, "inband_dtmf_generate", NULL,
4116  return status;
4117  }
4118 
4119  switch_channel_set_private(channel, "dtmf_generate", bug);
4120 
4121  return SWITCH_STATUS_SUCCESS;
4122 }
#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&#39;s pool.
Definition: switch_core.h:696
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_ivr_inband_dtmf_session()

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 3854 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().

3855 {
3857  switch_media_bug_t *bug;
3858  switch_status_t status;
3859  switch_inband_dtmf_t *pvt;
3860  switch_codec_implementation_t read_impl = { 0 };
3861 
3862  switch_core_session_get_read_impl(session, &read_impl);
3863 
3864  if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
3865  return SWITCH_STATUS_MEMERR;
3866  }
3867 
3869 
3870  pvt->session = session;
3871 
3872 
3874  return SWITCH_STATUS_FALSE;
3875  }
3876 
3877  if ((status = switch_core_media_bug_add(session, "inband_dtmf", NULL,
3879  return status;
3880  }
3881 
3882  switch_channel_set_private(channel, "dtmf", bug);
3883 
3884  return SWITCH_STATUS_SUCCESS;
3885 }
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&#39;s pool.
Definition: switch_core.h:696
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_ivr_media()

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 1773 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().

1774 {
1775  const char *other_uuid = NULL;
1776  switch_channel_t *channel, *other_channel = NULL;
1777  switch_core_session_t *session, *other_session;
1778  switch_core_session_message_t msg = { 0 };
1780  uint8_t swap = 0;
1781  switch_frame_t *read_frame = NULL;
1782 
1784  msg.from = __FILE__;
1785 
1786  if ((session = switch_core_session_locate(uuid))) {
1787  channel = switch_core_session_get_channel(session);
1788 
1789  if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) {
1791 
1792  return SWITCH_STATUS_INUSE;
1793  }
1794 
1796 
1797  if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
1798  swap = 1;
1799  }
1800 
1801  if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
1803 
1804  status = SWITCH_STATUS_SUCCESS;
1805 
1806  /* If we had early media in bypass mode before, it is no longer relevant */
1807  if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
1808  switch_core_session_message_t msg2 = { 0 };
1809 
1811  msg2.from = __FILE__;
1812  switch_core_session_receive_message(session, &msg2);
1813  }
1814 
1815  if ((flags & SMF_REPLYONLY_A)) {
1816  msg.numeric_arg = 1;
1817  }
1818 
1820  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't re-establsh media on %s\n", switch_channel_get_name(channel));
1822 
1823  return SWITCH_STATUS_GENERR;
1824  }
1825 
1826  if ((flags & SMF_REPLYONLY_B)) {
1827  msg.numeric_arg = 1;
1828  } else {
1829  msg.numeric_arg = 0;
1830  }
1831 
1832  if ((flags & SMF_IMMEDIATE)) {
1834  switch_yield(250000);
1835  } else {
1836  switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1837  switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1838  switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1839  res = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1840  }
1841 
1842  if ((flags & SMF_REBRIDGE)
1844  && (other_session = switch_core_session_locate(other_uuid))) {
1845  other_channel = switch_core_session_get_channel(other_session);
1846  switch_assert(other_channel != NULL);
1847  switch_core_session_receive_message(other_session, &msg);
1848  switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
1849  switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1850  switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
1851  res = switch_core_session_read_frame(other_session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1852  switch_channel_clear_state_handler(other_channel, NULL);
1853  switch_core_session_rwunlock(other_session);
1854  }
1855 
1856  (void)res;
1857 
1858  if (other_channel) {
1859  switch_channel_clear_state_handler(channel, NULL);
1860  }
1861  }
1862 
1865 
1866  if (other_channel) {
1867  if (swap) {
1868  switch_ivr_uuid_bridge(other_uuid, uuid);
1869  } else {
1870  switch_ivr_uuid_bridge(uuid, other_uuid);
1871  }
1872 
1873  switch_channel_wait_for_flag(channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
1874  switch_channel_wait_for_flag(other_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
1875  }
1876  }
1877 
1878  return status;
1879 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:202
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
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:179
_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:998
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:54
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
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&#39;s uuid.
Definition: switch_core.h:932
#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_ivr_multi_threaded_bridge()

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(), fs_switch_ivr_originate(), switch_ivr_enterprise_orig_and_bridge(), and switch_ivr_orig_and_bridge().

◆ switch_ivr_nomedia()

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 1987 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 audio_bridge_thread(), media_thread_run(), and switch_ivr_parse_event().

1988 {
1989  const char *other_uuid;
1990  switch_channel_t *channel, *other_channel = NULL;
1991  switch_core_session_t *session, *other_session = NULL;
1992  switch_core_session_message_t msg = { 0 };
1994  uint8_t swap = 0;
1995 
1997  msg.from = __FILE__;
1998 
1999  if ((session = switch_core_session_locate(uuid))) {
2000 
2001  status = SWITCH_STATUS_SUCCESS;
2002  channel = switch_core_session_get_channel(session);
2003 
2004  if (switch_channel_test_flag(channel, CF_SECURE)) {
2007  "Cannot bypass %s due to secure connection.\n", switch_channel_get_name(channel));
2008  return SWITCH_STATUS_FALSE;
2009  }
2010 
2011  if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) {
2013  return SWITCH_STATUS_INUSE;
2014  }
2015 
2017 
2018  if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
2019  swap = 1;
2020  }
2021 
2024 
2025  if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_PROXY_MODE)) {
2026  if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
2027  (other_session = switch_core_session_locate(other_uuid))) {
2028  other_channel = switch_core_session_get_channel(other_session);
2029 
2030  switch_channel_set_flag(other_channel, CF_RESET);
2031  switch_channel_set_flag(other_channel, CF_REDIRECT);
2032 
2033  if (!switch_core_session_in_thread(session)) {
2035  }
2036  switch_channel_set_state(other_channel, CS_PARK);
2037  if (switch_core_session_in_thread(session)) {
2038  switch_yield(100000);
2039  } else {
2040  switch_channel_wait_for_state(other_channel, channel, CS_PARK);
2041  }
2042  switch_core_session_receive_message(other_session, &msg);
2043  switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
2044  //switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
2045  switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
2046  }
2047 
2048  switch_core_session_receive_message(session, &msg);
2049 
2050  if (other_channel) {
2051  if (!switch_core_session_in_thread(session)) {
2052  switch_channel_wait_for_state(channel, NULL, CS_PARK);
2053  switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
2054  switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
2055  switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
2056  }
2057 
2058  if (swap) {
2059  switch_ivr_signal_bridge(other_session, session);
2060  } else {
2061  switch_ivr_signal_bridge(session, other_session);
2062  }
2063 
2064  if (switch_core_session_in_thread(session)) {
2065  switch_yield(100000);
2066  } else {
2067  switch_channel_wait_for_state(other_channel, channel, CS_HIBERNATE);
2068  }
2069 
2070  if (!switch_core_session_in_thread(session)) {
2071  switch_channel_wait_for_state(channel, other_channel, CS_HIBERNATE);
2072  }
2073  switch_core_session_rwunlock(other_session);
2074  }
2075  }
2076 
2079  }
2080 
2081 
2082 
2083  return status;
2084 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
#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:179
_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:998
#define switch_channel_get_variable(_c, _v)
switch_core_session_t * session
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:200
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
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&#39;s uuid.
Definition: switch_core.h:932
#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_ivr_originate()

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,
switch_dial_handle_t dh 
)

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

switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE) &&

Definition at line 2064 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, switch_caller_profile::chan_name, switch_file_handle::channels, check_channel_status(), check_per_channel_timeouts(), originate_global_t::check_vars, switch_frame::codec, originate_global_t::confirm_read_timeout, 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, originate_global_t::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_uuid(), switch_channel_get_variable, switch_channel_hangup, switch_channel_has_dtmf(), switch_channel_media_ready, switch_channel_media_up, 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, switch_channel_up_nosig, switch_channel_var_true(), 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_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_DEFAULT_TIMEOUT, switch_dial_handle_get_global_vars(), switch_dial_handle_get_peers(), switch_dial_handle_get_total(), switch_dial_handle_get_vars(), 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_event_serialize(), 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_INT64_T_FMT, SWITCH_IO_FLAG_NONE, switch_is_number(), 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_transfer_recordings(), switch_ivr_uuid_bridge(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, SWITCH_LOG_INFO, SWITCH_LOG_NOTICE, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS, switch_micro_time_now(), 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_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, originate_status_t::tagged, teletone_destroy_session(), to, 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(), CoreSession::originate(), and switch_ivr_orig_and_bridge().

2076 {
2077  //originate_status_t originate_status[MAX_PEERS] = { {0} };
2078  switch_originate_flag_t dftflags = SOF_NONE, myflags;
2079  char *pipe_names[MAX_PEERS] = { 0 };
2080  char *data = NULL;
2082  switch_channel_t *caller_channel = NULL;
2083  char *peer_names[MAX_PEERS] = { 0 };
2084  switch_event_t *peer_vars[MAX_PEERS] = { 0 };
2085  switch_core_session_t *new_session = NULL, *peer_session = NULL;
2086  switch_caller_profile_t *new_profile = NULL, *caller_caller_profile;
2087  char *chan_type = NULL, *chan_data;
2088  switch_channel_t *peer_channel = NULL;
2089  ringback_t ringback = { 0 };
2090  time_t start, global_start;
2091  switch_time_t last_retry_start = 0;
2092  switch_frame_t *read_frame = NULL;
2093  int r = 0, i, and_argc = 0, or_argc = 0;
2094  int32_t sleep_ms = 1000, try = 0, retries = 1, retry_timelimit_sec = 0;
2095  int32_t min_retry_period_ms = sleep_ms;
2096  switch_codec_t write_codec = { 0 };
2097  switch_frame_t write_frame = { 0 };
2098  char *odata, *var;
2100  switch_call_cause_t force_reason = SWITCH_CAUSE_NONE;
2101  uint8_t to = 0;
2102  char *var_val;
2103  const char *ringback_data = NULL;
2104  switch_event_t *var_event = NULL;
2105  int8_t fail_on_single_reject = 0;
2106  int8_t hangup_on_single_reject = 0;
2107  char *fail_on_single_reject_var = NULL;
2108  char *loop_data = NULL;
2109  uint32_t progress_timelimit_sec = 0;
2110  const char *cid_tmp, *lc;
2111  originate_global_t oglobals = { 0 };
2112  int cdr_total = 0;
2113  int local_clobber = 0;
2114  const char *cancel_key = NULL;
2115  const char *holding = NULL;
2116  const char *soft_holding = NULL;
2117  early_state_t early_state = { 0 };
2118  int read_packet = 0;
2119  int check_reject = 1;
2120  switch_codec_implementation_t read_impl = { 0 };
2121  const char *ani_override = NULL;
2122  const char *aniii_override = NULL;
2123  const char *ent_aleg_uuid = NULL;
2124  switch_core_session_t *a_session = session, *l_session = NULL;
2125  char *event_string;
2126 
2127  if (!bridgeto || dh) {
2128  bridgeto = "";
2129  }
2130 
2131  if (session) {
2132  caller_channel = switch_core_session_get_channel(session);
2133 
2134  if (switch_false(switch_channel_get_variable(caller_channel, "preserve_originated_vars"))) {
2135  switch_channel_set_variable(caller_channel, "originated_legs", NULL);
2136  switch_channel_set_variable(caller_channel, "originate_causes", NULL);
2137  }
2138  }
2139 
2140 
2141  if (strstr(bridgeto, SWITCH_ENT_ORIGINATE_DELIM)) {
2142  return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override,
2143  caller_profile_override, ovars, flags, cancel_cause, NULL);
2144  }
2145 
2146  oglobals.check_vars = SWITCH_TRUE;
2147  oglobals.ringback_ok = 1;
2148  oglobals.bridge_early_media = -1;
2149  oglobals.file = NULL;
2150  oglobals.error_file = NULL;
2151  switch_core_new_memory_pool(&oglobals.pool);
2152 
2153  if (caller_profile_override) {
2154  oglobals.caller_profile_override = switch_caller_profile_dup(oglobals.pool, caller_profile_override);
2155  } else if (session) {
2157 
2158  if (cp) {
2159  oglobals.caller_profile_override = switch_caller_profile_dup(oglobals.pool, cp);
2160  }
2161  }
2162 
2163  if (session) {
2164  const char *to_var, *bypass_media = NULL, *proxy_media = NULL;
2165  switch_channel_set_flag(caller_channel, CF_ORIGINATOR);
2166  oglobals.session = session;
2167 
2170 
2171  switch_core_session_get_read_impl(session, &read_impl);
2172 
2173  if ((to_var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
2174  timelimit_sec = atoi(to_var);
2175  }
2176 
2177  proxy_media = switch_channel_get_variable(caller_channel, SWITCH_PROXY_MEDIA_VARIABLE);
2178  bypass_media = switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_VARIABLE);
2179 
2180  if (!zstr(proxy_media)) {
2181  if (switch_true(proxy_media)) {
2182  switch_channel_set_flag(caller_channel, CF_PROXY_MEDIA);
2183  } else if (switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
2184  switch_channel_clear_flag(caller_channel, CF_PROXY_MEDIA);
2185  }
2186  }
2187 
2188  if (bypass_media && switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
2189  switch_core_session_message_t msg = { 0 };
2190 
2192  msg.from = __FILE__;
2193  switch_core_session_receive_message(session, &msg);
2194  }
2195 
2196 
2197  if (!zstr(bypass_media) && !switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
2198  if (switch_true(bypass_media)) {
2199  switch_channel_set_flag(caller_channel, CF_PROXY_MODE);
2200  } else if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
2201  if (!switch_channel_test_flag(caller_channel, CF_ANSWERED) && switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
2202  switch_channel_set_variable(caller_channel, SWITCH_B_SDP_VARIABLE, NULL);
2203  switch_channel_answer(caller_channel);
2205  "Must answer channel %s due to SIP PARADOX\n", switch_channel_get_name(caller_channel));
2206  }
2207  switch_channel_set_variable(caller_channel, SWITCH_B_SDP_VARIABLE, NULL);
2209  }
2210  }
2211 
2212  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
2214  "Channel is already up, delaying proxy mode 'till both legs are answered.\n");
2215  switch_channel_set_variable(caller_channel, "bypass_media_after_bridge", "true");
2217  switch_channel_clear_flag(caller_channel, CF_PROXY_MODE);
2218  }
2219  }
2220 
2221  if (timelimit_sec <= 0) {
2222  timelimit_sec = SWITCH_DEFAULT_TIMEOUT;
2223  }
2224 
2225 
2226  oglobals.idx = IDX_NADA;
2227  oglobals.early_ok = 1;
2228 
2229  *bleg = NULL;
2230 
2232  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2233 
2234  odata = strdup(bridgeto);
2235 
2236  if (!odata) {
2237  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error!\n");
2238  status = SWITCH_STATUS_MEMERR;
2239  goto done;
2240  }
2241 
2242  data = odata;
2243 
2244 
2245  /* Some channel are created from an originating channel and some aren't so not all outgoing calls have a way to get params
2246  so we will normalize dialstring params and channel variables (when there is an originator) into an event that we
2247  will use as a pseudo hash to consult for params as needed.
2248  */
2249 
2250  if (ovars) {
2251  var_event = ovars;
2252  } else {
2254  abort();
2255  }
2256  }
2257 
2258  ent_aleg_uuid = switch_event_get_header(var_event, "ent_originate_aleg_uuid");
2259 
2260  if (caller_channel) {
2261  switch_channel_process_export(caller_channel, NULL, var_event, SWITCH_EXPORT_VARS_VARIABLE);
2262  }
2263 
2264  /* strip leading spaces */
2265  while (data && *data && *data == ' ') {
2266  data++;
2267  }
2268 
2269  if ((ovars && switch_true(switch_event_get_header(ovars,"origination_nested_vars"))) ||
2270  (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "origination_nested_vars")))
2271  || switch_true(switch_core_get_variable("origination_nested_vars")) || switch_stristr("origination_nested_vars=true", data)) {
2272  oglobals.check_vars = SWITCH_FALSE;
2273  }
2274 
2275  if (dh) {
2277  if (vp) {
2278  if (var_event && var_event != ovars) {
2279  switch_event_destroy(&var_event);
2280  }
2281  switch_event_dup(&var_event, vp);
2282  }
2283  }
2284 
2285  /* extract channel variables, allowing multiple sets of braces */
2286  if (*data == '<') {
2287  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing ultra-global variables\n");
2288  while (*data == '<') {
2289  char *parsed = NULL;
2290 
2291  if (switch_event_create_brackets(data, '<', '>', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
2292  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
2294  }
2295 
2296  data = parsed;
2297  }
2298  }
2299 
2300  /* extract channel variables, allowing multiple sets of braces */
2301  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing global variables\n");
2302  while (*data == '{') {
2303  char *parsed = NULL;
2304 
2305  if (switch_event_create_brackets(data, '{', '}', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
2306  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
2308  }
2309 
2310  data = parsed;
2311  }
2312 
2313  if (dh && var_event && switch_event_serialize(var_event, &event_string, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
2314  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Global Vars\n======================\n%s\n", event_string);
2315  switch_safe_free(event_string);
2316  }
2317 
2318  /* strip leading spaces (again) */
2319  while (data && *data && *data == ' ') {
2320  data++;
2321  }
2322 
2323  if (zstr(data) && !dh) {
2324  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "No origination URL specified!\n");
2325  status = SWITCH_STATUS_GENERR;
2326  goto done;
2327  }
2328 
2329  if (!(flags & SOF_NOBLOCK) && var_event && (var = switch_event_get_header(var_event, "originate_delay_start"))) {
2330  int tmp = atoi(var);
2331  if (tmp > 0) {
2332  while (tmp && (!cancel_cause || *cancel_cause == 0)) {
2333  switch_cond_next();
2334  tmp--;
2335  }
2336  }
2337  }
2338 
2339  if (oglobals.session) {
2341  const char *cdr_total_var;
2342  const char *cdr_var;
2343  const char *json_cdr_var;
2344 
2345  if (switch_channel_var_true(caller_channel, "originate_xfer_zombie")) {
2346  switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
2347  oglobals.early_ok = 0;
2348  oglobals.ignore_early_media = 1;
2349  }
2350 
2351  if ((cdr_var = switch_channel_get_variable(caller_channel, "failed_xml_cdr_prefix"))) {
2352  char buf[128] = "";
2353  switch_snprintf(buf, sizeof(buf), "%s_total", cdr_var);
2354  if ((cdr_total_var = switch_channel_get_variable(caller_channel, buf))) {
2355  int tmp = atoi(cdr_total_var);
2356  if (tmp > 0) {
2357  cdr_total = tmp;
2358  }
2359  }
2360  }
2361 
2362  if ((json_cdr_var = switch_channel_get_variable(caller_channel, "failed_json_cdr_prefix"))) {
2363  char buf[128] = "";
2364  switch_snprintf(buf, sizeof(buf), "%s_total", json_cdr_var);
2365  if ((cdr_total_var = switch_channel_get_variable(caller_channel, buf))) {
2366  int tmp = atoi(cdr_total_var);
2367  if (tmp > 0) {
2368  cdr_total = tmp;
2369  }
2370  }
2371  }
2372 
2373  /* Copy all the missing applicable channel variables from A-leg into the event */
2374  if ((hi = switch_channel_variable_first(caller_channel))) {
2375  for (; hi; hi = hi->next) {
2376  int ok = 0;
2377  if (!strcasecmp((char *) hi->name, "group_confirm_key")) {
2378  ok = 1;
2379  } else if (!strcasecmp((char *) hi->name, "group_confirm_file")) {
2380  ok = 1;
2381  } else if (!strcasecmp((char *) hi->name, "group_confirm_read_timeout")) {
2382  ok = 1;
2383  } else if (!strcasecmp((char *) hi->name, "group_confirm_cancel_timeout")) {
2384  ok = 1;
2385  } else if (!strcasecmp((char *) hi->name, "group_confirm_timeout")) {
2386  ok = 1;
2387  } else if (!strcasecmp((char *) hi->name, "forked_dial")) {
2388  ok = 1;
2389  } else if (!strcasecmp((char *) hi->name, "fail_on_single_reject")) {
2390  ok = 1;
2391  } else if (!strcasecmp((char *) hi->name, "hangup_on_single_reject")) {
2392  ok = 1;
2393  } else if (!strcasecmp((char *) hi->name, "ignore_early_media")) {
2394  ok = 1;
2395  } else if (!strcasecmp((char *) hi->name, "bridge_early_media")) {
2396  ok = 1;
2397  } else if (!strcasecmp((char *) hi->name, "originate_continue_on_timeout")) {
2398  ok = 1;
2399  } else if (!strcasecmp((char *) hi->name, "ignore_ring_ready")) {
2400  ok = 1;
2401  } else if (!strcasecmp((char *) hi->name, "monitor_early_media_ring")) {
2402  ok = 1;
2403  } else if (!strcasecmp((char *) hi->name, "monitor_early_media_ring_total")) {
2404  ok = 1;
2405  } else if (!strcasecmp((char *) hi->name, "monitor_early_media_fail")) {
2406  ok = 1;
2407  } else if (!strcasecmp((char *) hi->name, "return_ring_ready")) {
2408  ok = 1;
2409  } else if (!strcasecmp((char *) hi->name, "ring_ready")) {
2410  ok = 1;
2411  } else if (!strcasecmp((char *) hi->name, "instant_ringback")) {
2412  ok = 1;
2413  } else if (!strcasecmp((char *) hi->name, "progress_timeout")) {
2414  ok = 1;
2415  } else if (!strcasecmp((char *) hi->name, "language")) {
2416  ok = 1;
2417  }
2418 
2419  if (ok && !switch_event_get_header(var_event, hi->name)) {
2420  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, (char *) hi->name, (char *) hi->value);
2421  }
2422  }
2423  switch_channel_variable_last(caller_channel);
2424  }
2425  /*
2426  if ((hi = switch_channel_variable_first(caller_channel))) {
2427  for (; hi; hi = switch_core_hash_next(&hi)) {
2428  switch_core_hash_this(hi, &vvar, NULL, &vval);
2429  if (vvar && vval) {
2430  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, (void *) vvar, (char *) vval);
2431  }
2432  }
2433  switch_channel_variable_last(caller_channel);
2434  }
2435  */
2436  }
2437 
2438  if (caller_channel) { /* ringback is only useful when there is an originator */
2439  ringback_data = NULL;
2440  cancel_key = switch_channel_get_variable(caller_channel, "origination_cancel_key");
2441 
2442  if (switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
2443  ringback_data = switch_channel_get_variable(caller_channel, "transfer_ringback");
2444  }
2445 
2446  if (!ringback_data) {
2447  ringback_data = switch_channel_get_variable(caller_channel, "ringback");
2448  }
2449 
2450  switch_channel_set_variable(caller_channel, "originate_disposition", "failure");
2451  switch_channel_set_variable(caller_channel, "DIALSTATUS", "INVALIDARGS");
2452 
2453  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
2454  ringback_data = NULL;
2455  }
2456  }
2457 #if 0
2458  /* changing behaviour ignore_early_media=true must also be explicitly set for previous behaviour */
2459  if (ringback_data) {
2460  oglobals.early_ok = 0;
2461  }
2462 #endif
2463 
2464  if ((var = switch_event_get_header(var_event, "group_confirm_timeout"))) {
2465  // has precedence over group_confirm_cancel_timeout
2466  if (switch_is_number(var)) {
2467  oglobals.confirm_timeout = atoi(var);
2468  if (oglobals.confirm_timeout == 0) {
2469  oglobals.cancel_timeout = SWITCH_TRUE;
2470  }
2471  }
2472  } else if (switch_true(switch_event_get_header(var_event, "group_confirm_cancel_timeout"))) {
2473  oglobals.cancel_timeout = SWITCH_TRUE;
2474  }
2475 
2476  if ((var = switch_event_get_header(var_event, "group_confirm_early_ok"))) {
2477  oglobals.early_ok = switch_true(var);
2478  }
2479 
2480  if ((var = switch_event_get_header(var_event, "group_confirm_key"))) {
2481  switch_copy_string(oglobals.key, var, sizeof(oglobals.key));
2482  if ((var = switch_event_get_header(var_event, "group_confirm_file"))) {
2483  oglobals.file = strdup(var);
2484  }
2485  if ((var = switch_event_get_header(var_event, "group_confirm_error_file"))) {
2486  oglobals.error_file = strdup(var);
2487  }
2488  if ((var = switch_event_get_header(var_event, "group_confirm_read_timeout"))) {
2489  int tmp = atoi(var);
2490 
2491  if (tmp >= 0) {
2492  oglobals.confirm_read_timeout = tmp;
2493  }
2494 
2495  }
2496  }
2497  /* When using the AND operator, the fail_on_single_reject flag may be set in order to indicate that a single
2498  rejections should terminate the attempt rather than a timeout, answer, or rejection by all.
2499  If the value is set to 'true' any fail cause will end the attempt otherwise it can contain a comma (,) separated
2500  list of cause names which should be considered fatal
2501  */
2502  if ((var = switch_event_get_header(var_event, "hangup_on_single_reject"))) {
2503  hangup_on_single_reject = switch_true(var);
2504  }
2505 
2506  if ((var = switch_event_get_header(var_event, "fail_on_single_reject")) || hangup_on_single_reject) {
2507  if (var) {
2508  fail_on_single_reject_var = strdup(var);
2509  }
2510 
2511  if (switch_true(var)) {
2512  fail_on_single_reject = 1;
2513  } else {
2514  fail_on_single_reject = -1;
2515  }
2516  }
2517 
2518  if ((!zstr(oglobals.file)) && (!strcmp(oglobals.file, "undef"))) {
2519  switch_safe_free(oglobals.file);
2520  oglobals.file = NULL;
2521  }
2522  if ((!zstr(oglobals.error_file)) && (!strcmp(oglobals.error_file, "undef"))) {
2523  switch_safe_free(oglobals.error_file);
2524  oglobals.error_file = NULL;
2525  }
2526 
2527  if ((var_val = switch_event_get_header(var_event, "bridge_early_media"))) {
2528  if (switch_true(var_val)) {
2529  oglobals.early_ok = 0;
2530  oglobals.ignore_early_media = 3;
2531  }
2532  }
2533 
2534  if ((var_val = switch_event_get_header(var_event, "ignore_early_media"))) {
2535  if (switch_true(var_val)) {
2536  oglobals.early_ok = 0;
2537  oglobals.ignore_early_media = 1;
2538  } else if (!strcmp(var_val, "consume")) {
2539  oglobals.early_ok = 0;
2540  oglobals.ignore_early_media = 4;
2541  } else if (!strcmp(var_val, "ring_ready")) {
2542  oglobals.early_ok = 0;
2543  oglobals.ignore_early_media = 2;
2544  }
2545  }
2546 
2547  if ((var_val = switch_event_get_header(var_event, "originate_continue_on_timeout")) && switch_true(var_val)) {
2548  oglobals.continue_on_timeout = 1;
2549  }
2550 
2551  if ((var_val = switch_event_get_header(var_event, "ignore_ring_ready")) && switch_true(var_val)) {
2552  oglobals.ignore_ring_ready = 1;
2553  }
2554 
2555  if ((var_val = switch_event_get_header(var_event, "monitor_early_media_ring")) && switch_true(var_val)) {
2556  oglobals.early_ok = 0;
2557  oglobals.monitor_early_media_ring = 1;
2558  }
2559 
2560  if ((var_val = switch_event_get_header(var_event, "monitor_early_media_fail")) && switch_true(var_val)) {
2561  oglobals.early_ok = 0;
2562  oglobals.monitor_early_media_fail = 1;
2563  }
2564 
2565  if ((var_val = switch_event_get_header(var_event, "return_ring_ready")) && switch_true(var_val)) {
2566  oglobals.return_ring_ready = 1;
2567  }
2568 
2569  if ((var_val = switch_event_get_header(var_event, "ring_ready")) && switch_true(var_val)) {
2570  oglobals.ring_ready = 1;
2571  }
2572 
2573  if ((var_val = switch_event_get_header(var_event, "instant_ringback")) && switch_true(var_val)) {
2574  oglobals.instant_ringback = 1;
2575  }
2576 
2577  if ((var_val = switch_event_get_header(var_event, "originate_timeout"))) {
2578  int tmp = atoi(var_val);
2579  if (tmp > 0) {
2580  timelimit_sec = (uint32_t) tmp;
2581  }
2582  }
2583 
2584  if ((var_val = switch_event_get_header(var_event, "progress_timeout"))) {
2585  int tmp = atoi(var_val);
2586  if (tmp > 0) {
2587  progress_timelimit_sec = (uint32_t) tmp;
2588  }
2589  }
2590 
2591  if ((var_val = switch_event_get_header(var_event, "originate_retry_timeout")) && switch_true(var_val)) {
2592  int32_t tmp;
2593  tmp = atoi(var_val);
2594  if (tmp > 0) {
2595  retry_timelimit_sec = tmp;
2596  } else {
2598  "Invalid originate_retry_timeout setting of %s ignored, value must be > 0\n", var_val);
2599  }
2600  }
2601 
2602  if ((var_val = switch_event_get_header(var_event, "originate_retries")) && switch_true(var_val)) {
2603  int32_t tmp;
2604  tmp = atoi(var_val);
2605  /* allow large number of retries if timeout is set */
2606  if (tmp > 0 && (retry_timelimit_sec > 0 || tmp < 101)) {
2607  retries = tmp;
2608  } else {
2610  "Invalid originate_retries setting of %d ignored, value must be between 1 and 100\n", tmp);
2611  }
2612  }
2613 
2614  if ((var_val = switch_event_get_header(var_event, "originate_retry_sleep_ms")) && switch_true(var_val)) {
2615  int32_t tmp;
2616  tmp = atoi(var_val);
2617  if (tmp >= 500 && tmp <= 60000) {
2618  sleep_ms = tmp;
2619  } else {
2621  "Invalid originate_retry_sleep_ms setting of %d ignored, value must be between 500 and 60000\n", tmp);
2622  }
2623  }
2624 
2625  if ((var_val = switch_event_get_header(var_event, "originate_retry_min_period_ms")) && switch_true(var_val)) {
2626  int32_t tmp;
2627  tmp = atoi(var_val);
2628  if (tmp >= 500 && tmp <= 300000) {
2629  min_retry_period_ms = tmp;
2630  } else {
2632  "Invalid originate_retry_min_period_ms setting of %d ignored, value must be between 500 and 300000\n", tmp);
2633  }
2634  }
2635 
2636  /* variable to force ANI / ANIII */
2637  ani_override = switch_event_get_header(var_event, "origination_ani");
2638  aniii_override = switch_event_get_header(var_event, "origination_aniii");
2639 
2640  if ((cid_tmp = switch_event_get_header(var_event, "origination_caller_id_name"))) {
2641  cid_name_override = cid_tmp;
2642  }
2643 
2644  if (cid_name_override) {
2645  if (!cid_tmp) {
2646  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_name", cid_name_override);
2647  }
2648  } else {
2649  cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
2650  }
2651 
2652  if ((cid_tmp = switch_event_get_header(var_event, "origination_caller_id_number"))) {
2653  cid_num_override = cid_tmp;
2654  }
2655 
2656  if (cid_num_override) {
2657  if (!cid_tmp) {
2658  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_caller_id_number", cid_num_override);
2659  }
2660  } else {
2661  cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
2662  }
2663 
2664  if (flags & SOF_NO_LIMITS) {
2665  dftflags |= SOF_NO_LIMITS;
2666  }
2667 
2668  if (ani_override) {
2669  dftflags |= SOF_NO_EFFECTIVE_ANI;
2670  }
2671 
2672  if (aniii_override) {
2673  dftflags |= SOF_NO_EFFECTIVE_ANIII;
2674  }
2675 
2676  if (cid_num_override) {
2677  dftflags |= SOF_NO_EFFECTIVE_CID_NUM;
2678  }
2679 
2680  if (cid_name_override) {
2681  dftflags |= SOF_NO_EFFECTIVE_CID_NAME;
2682  }
2683 
2684  if (!progress_timelimit_sec) {
2685  progress_timelimit_sec = timelimit_sec;
2686  }
2687 
2688  switch_epoch_time_now(&global_start);
2689  last_retry_start = switch_micro_time_now();
2690 
2691  for (try = 0; try < retries; try++) {
2692 
2693  if (try > 0) {
2694  int64_t elapsed = switch_epoch_time_now(NULL) - global_start;
2695 
2696  /* check if retry time limit has been exceeded */
2697  if (retry_timelimit_sec > 0) {
2698  if (elapsed > retry_timelimit_sec) {
2700  "Elapsed = %"SWITCH_INT64_T_FMT", originate retry timeout.\n", elapsed);
2701  break;
2702  } else if (cancel_cause && *cancel_cause != 0) {
2703  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Originate cancelled\n");
2704  break;
2705  } else {
2707  "Elapsed = %"SWITCH_INT64_T_FMT", originate retry not timed out yet\n", elapsed);
2708  }
2709  }
2710 
2711  /* don't allow retry to start too quickly since last attempt */
2712  if (min_retry_period_ms > sleep_ms) {
2713  int64_t retry_sleep_ms = min_retry_period_ms - sleep_ms - ((switch_micro_time_now() - last_retry_start) / 1000);
2714  if (retry_sleep_ms > 0 && retry_sleep_ms <= 300000) {
2715  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Minimum retry period has not elapsed yet, waiting %"SWITCH_INT64_T_FMT" ms\n", retry_sleep_ms);
2716  if (caller_channel) {
2717  switch_ivr_sleep(oglobals.session, retry_sleep_ms, SWITCH_TRUE, NULL);
2718  if (!switch_channel_ready(caller_channel)) {
2719  status = SWITCH_STATUS_FALSE;
2720  goto done;
2721  }
2722  } else {
2723  switch_yield(retry_sleep_ms * 1000);
2724  }
2725  }
2726  }
2727  }
2728 
2729  switch_safe_free(loop_data);
2730  loop_data = strdup(data);
2731  switch_assert(loop_data);
2732 
2733  if (dh) {
2734  or_argc = switch_dial_handle_get_total(dh);
2735  } else {
2736  or_argc = switch_separate_string(loop_data, '|', pipe_names, (sizeof(pipe_names) / sizeof(pipe_names[0])));
2737  }
2738 
2739  if ((flags & SOF_NOBLOCK) && or_argc > 1) {
2740  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Only calling the first element in the list in this mode.\n");
2741  or_argc = 1;
2742  }
2743 
2744  if (or_argc <= 0) {
2745  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Nothing to do\n");
2746  goto outer_for;
2747  }
2748 
2749  for (r = 0; r < or_argc && (!cancel_cause || *cancel_cause == 0); r++) {
2750  char *p, *end = NULL;
2751  int q = 0, alt = 0;
2752 
2753  check_reject = 1;
2754 
2755  oglobals.hups = 0;
2756 
2757  reason = SWITCH_CAUSE_NONE;
2758  memset(peer_names, 0, sizeof(peer_names));
2759  peer_session = NULL;
2760  memset(oglobals.originate_status, 0, sizeof(oglobals.originate_status));
2761  new_profile = NULL;
2762  new_session = NULL;
2763  chan_type = NULL;
2764  chan_data = NULL;
2765  peer_channel = NULL;
2766  start = 0;
2767  read_frame = NULL;
2768  oglobals.ringback_ok = 1;
2769  var = NULL;
2770  to = 0;
2771  oglobals.sent_ring = 0;
2772  oglobals.progress = 0;
2773  myflags = dftflags;
2774 
2775 
2776  if (try > 0) {
2777  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Originate attempt %d/%d in %d ms\n", try + 1, retries,
2778  sleep_ms);
2779  if (caller_channel) {
2780  switch_ivr_sleep(oglobals.session, sleep_ms, SWITCH_TRUE, NULL);
2781  if (!switch_channel_ready(caller_channel)) {
2782  status = SWITCH_STATUS_FALSE;
2783  /* set try and retries to 0 */
2784  try = 0;
2785  retries = 0;
2786  goto done;
2787  }
2788  } else {
2789  switch_yield(sleep_ms * 1000);
2790  }
2791  }
2792 
2793  if (r == 0) {
2794  last_retry_start = switch_micro_time_now();
2795  }
2796 
2797  if (!dh) {
2798  p = pipe_names[r];
2799 
2800  while (p && *p) {
2801  if (!end && *p == '[') {
2802  end = switch_find_end_paren(p, '[', ']');
2803  if (*(p+1) == '^' && *(p + 2) == '^') {
2804  alt = 1;
2805  } else {
2806  alt = 0;
2807  }
2808  q = 0;
2809  }
2810 
2811  if (*p == '\'') {
2812  q = !q;
2813  }
2814 
2815  if (end && p < end && *p == ',' && *(p-1) != '\\') {
2816 
2817  if (q || alt) {
2818  *p = QUOTED_ESC_COMMA;
2819  } else {
2820  *p = UNQUOTED_ESC_COMMA;
2821  }
2822  }
2823 
2824  if (p == end) {
2825  end = NULL;
2826  }
2827 
2828  p++;
2829  }
2830 
2831  and_argc = switch_separate_string(pipe_names[r], ',', peer_names, (sizeof(peer_names) / sizeof(peer_names[0])));
2832  } else {
2833  and_argc = switch_dial_handle_get_peers(dh, r, peer_names, MAX_PEERS);
2834  switch_dial_handle_get_vars(dh, r, peer_vars, MAX_PEERS);
2835  }
2836 
2837  if ((flags & SOF_NOBLOCK) && and_argc > 1) {
2838  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Only calling the first element in the list in this mode.\n");
2839  and_argc = 1;
2840  }
2841 
2842  for (i = 0; i < and_argc; i++) {
2843  const char *current_variable;
2844  switch_event_t *local_var_event = NULL, *originate_var_event = NULL;
2845 
2846  end = NULL;
2847 
2848  if (!(chan_type = peer_names[i])) {
2849  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Empty dial string\n");
2851  }
2852 
2853 
2854  /* strip leading spaces */
2855  while (chan_type && *chan_type && *chan_type == ' ') {
2856  chan_type++;
2857  }
2858 
2859  /* extract channel variables, allowing multiple sets of braces */
2860 
2861  if (*chan_type == '[') {
2863  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Parsing session specific variables\n");
2864  }
2865 
2866  while (*chan_type == '[') {
2867  char *parsed = NULL;
2868  char *bend = switch_find_end_paren(chan_type, '[', ']');
2869 
2870  for (p = chan_type + 1; p && p < bend && *p; p++) {
2871  if (*p == QUOTED_ESC_COMMA) {
2872  *p = ',';
2873  }
2874  }
2875 
2876  if (switch_event_create_brackets(chan_type, '[', ']', UNQUOTED_ESC_COMMA,
2877  &local_var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
2878  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
2880  }
2881 
2882  if (chan_type == parsed) {
2883  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
2885  } else {
2886  chan_type = parsed;
2887  }
2888  }
2889 
2890  if (peer_vars[i]) {
2891  if (local_var_event) {
2892  switch_event_merge(local_var_event, peer_vars[i]);
2893  } else {
2894  switch_event_dup(&local_var_event, peer_vars[i]);
2895  }
2896 
2897  if (dh && local_var_event && switch_event_serialize(local_var_event, &event_string, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
2898  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Local Vars for %s\n======================\n%s\n",
2899  peer_names[i], event_string);
2900  switch_safe_free(event_string);
2901  }
2902  }
2903 
2904  /* strip leading spaces (again) */
2905  while (chan_type && *chan_type && *chan_type == ' ') {
2906  chan_type++;
2907  }
2908 
2909  if ((chan_data = strchr(chan_type, '/')) != 0) {
2910  *chan_data = '\0';
2911  chan_data++;
2912  }
2913 
2914  if (oglobals.session) {
2915  if (!switch_channel_ready(caller_channel)) {
2916  status = SWITCH_STATUS_FALSE;
2917  if (local_var_event) switch_event_destroy(&local_var_event);
2918  goto done;
2919  }
2920 
2921  if ((caller_caller_profile = oglobals.caller_profile_override)) {
2922  new_profile = switch_caller_profile_dup(oglobals.pool, caller_caller_profile);
2923  } else {
2924  new_profile = switch_caller_profile_new(oglobals.pool,
2925  NULL,
2926  NULL,
2927  cid_name_override, cid_num_override, NULL, ani_override, aniii_override, NULL, __FILE__, NULL, chan_data);
2928  }
2929 
2930  new_profile->uuid = SWITCH_BLANK_STRING;
2931  new_profile->chan_name = SWITCH_BLANK_STRING;
2932  new_profile->destination_number = switch_core_strdup(new_profile->pool, chan_data);
2933 
2934  if (ani_override) {
2935  new_profile->ani = switch_core_strdup(new_profile->pool, ani_override);
2936  }
2937  if (aniii_override) {
2938  new_profile->aniii = switch_core_strdup(new_profile->pool, aniii_override);
2939  }
2940  if (cid_name_override) {
2941  new_profile->caller_id_name = switch_core_strdup(new_profile->pool, cid_name_override);
2942  }
2943  if (cid_num_override) {
2944  new_profile->caller_id_number = switch_core_strdup(new_profile->pool, cid_num_override);
2945  }
2946  } else {
2947  if (oglobals.caller_profile_override) {
2948  new_profile = switch_caller_profile_dup(oglobals.pool, oglobals.caller_profile_override);
2949  new_profile->destination_number = switch_core_strdup(new_profile->pool, switch_str_nil(chan_data));
2950  new_profile->uuid = SWITCH_BLANK_STRING;
2951  new_profile->chan_name = SWITCH_BLANK_STRING;
2952  } else {
2953  if (!cid_name_override) {
2954  cid_name_override = SWITCH_DEFAULT_CLID_NAME;
2955  }
2956  if (!cid_num_override) {
2957  cid_num_override = SWITCH_DEFAULT_CLID_NUMBER;
2958  }
2959 
2960  new_profile = switch_caller_profile_new(oglobals.pool,
2961  NULL,
2962  NULL,
2963  cid_name_override, cid_num_override, NULL, ani_override, aniii_override, NULL, __FILE__, NULL, chan_data);
2964  }
2965  }
2966 
2967  if (zstr(new_profile->destination_number)) {
2968  new_profile->destination_number = switch_core_strdup(new_profile->pool, "service");
2969  }
2970 
2971  new_profile->callee_id_name = switch_core_strdup(new_profile->pool, "Outbound Call");
2972  new_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(new_profile->pool, new_profile->destination_number));
2973 
2974  oglobals.originate_status[i].caller_profile = NULL;
2975  oglobals.originate_status[i].peer_channel = NULL;
2976  oglobals.originate_status[i].peer_session = NULL;
2977 
2978  new_session = NULL;
2979 
2980  if (and_argc > 1 || or_argc > 1) {
2981  myflags |= SOF_FORKED_DIAL;
2982  }
2983 
2984  if (var_event) {
2985  const char *vvar;
2986  if ((vvar = switch_event_get_header(var_event, "forked_dial")) && switch_true(vvar)) {
2987  myflags |= SOF_FORKED_DIAL;
2988  }
2989  if ((vvar = switch_event_get_header(var_event, "no_throttle_limits")) && switch_true(vvar)) {
2990  myflags |= SOF_NO_LIMITS;
2991  }
2992  }
2993 
2994 
2995  /* Valid in both {} and [] with [] taking precedence */
2996 
2997  /* make a special var event with mixture of the {} and the [] vars to pass down as global vars to the outgoing channel
2998  so if something like the user channel does another originate our options will be passed down properly
2999  */
3000 
3001  switch_event_dup(&originate_var_event, var_event);
3002 
3003  if (local_var_event) {
3004  switch_event_merge(originate_var_event, local_var_event);
3005  }
3006 
3007  if ((current_variable = switch_event_get_header(originate_var_event, "origination_ani"))) {
3008  new_profile->ani = switch_core_strdup(new_profile->pool, current_variable);
3009  myflags |= SOF_NO_EFFECTIVE_ANI;
3010  }
3011 
3012  if ((current_variable = switch_event_get_header(originate_var_event, "origination_aniii"))) {
3013  new_profile->aniii = switch_core_strdup(new_profile->pool, current_variable);
3014  myflags |= SOF_NO_EFFECTIVE_ANIII;
3015  }
3016 
3017  if ((current_variable = switch_event_get_header(originate_var_event, "origination_caller_id_number"))) {
3018  new_profile->caller_id_number = switch_core_strdup(new_profile->pool, current_variable);
3019  myflags |= SOF_NO_EFFECTIVE_CID_NUM;
3020  }
3021 
3022  if ((current_variable = switch_event_get_header(originate_var_event, "origination_caller_id_name"))) {
3023  new_profile->caller_id_name = switch_core_strdup(new_profile->pool, current_variable);
3024  myflags |= SOF_NO_EFFECTIVE_CID_NAME;
3025  }
3026 
3027  if ((current_variable = switch_event_get_header(originate_var_event, "origination_privacy"))) {
3028  new_profile->flags = SWITCH_CPF_NONE;
3029 
3030  if (switch_stristr("screen", current_variable)) {
3031  switch_set_flag(new_profile, SWITCH_CPF_SCREEN);
3032  }
3033 
3034  if (switch_stristr("hide_name", current_variable)) {
3035  switch_set_flag(new_profile, SWITCH_CPF_HIDE_NAME);
3036  }
3037 
3038  if (switch_stristr("hide_number", current_variable)) {
3040  }
3041  }
3042 
3043  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "originate_early_media", oglobals.early_ok ? "true" : "false");
3044 
3045 
3046  if (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "push_channel_name"))) {
3047  char *new_name = switch_core_session_sprintf(session, "%s__B", switch_channel_get_name(caller_channel));
3048  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "origination_channel_name", new_name);
3049  new_name = switch_core_session_sprintf(session, "_%s", switch_channel_get_name(caller_channel));
3050  switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "sip_h_X-FS-Channel-Name", new_name);
3051  }
3052 
3053 
3054  reason = switch_core_session_outgoing_channel(oglobals.session, originate_var_event, chan_type,
3055  new_profile, &new_session, NULL, myflags, cancel_cause);
3056  switch_event_destroy(&originate_var_event);
3057 
3058  if (reason != SWITCH_CAUSE_SUCCESS) {
3059  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Cannot create outgoing channel of type [%s] cause: [%s]\n",
3060  chan_type, switch_channel_cause2str(reason));
3061  if (local_var_event) switch_event_destroy(&local_var_event);
3062 
3063  if (fail_on_single_reject_var) {
3064  const char *cause_str = switch_channel_cause2str(reason);
3065  int neg = *fail_on_single_reject_var == '!';
3066  int pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
3067 
3068  if (neg) {
3069  pos = !pos;
3070  }
3071 
3072  check_reject = 0;
3073 
3074  if (fail_on_single_reject == 1 || pos) {
3075  force_reason = reason;
3076  status = SWITCH_STATUS_FALSE;
3077  goto outer_for;
3078  }
3079  }
3080  continue;
3081  }
3082 
3084  status = SWITCH_STATUS_FALSE;
3085  if (local_var_event) switch_event_destroy(&local_var_event);
3086  goto done;
3087  }
3088 
3091  oglobals.originate_status[i].peer_session = new_session;
3092 
3094 
3095  if (caller_channel) {
3096  switch_channel_set_variable(oglobals.originate_status[i].peer_channel, "call_uuid", switch_channel_get_variable(caller_channel, "call_uuid"));
3097  }
3098 
3099 
3100  if (local_var_event) {
3101  const char *device_id = switch_event_get_header(local_var_event, "device_id");
3102  switch_channel_set_profile_var(oglobals.originate_status[i].peer_channel, "device_id", device_id);
3103  }
3104 
3105  if ((lc = switch_event_get_header(var_event, "local_var_clobber"))) {
3106  local_clobber = switch_true(lc);
3107  }
3108 
3110  if (var_event) {
3111  switch_event_del_header(var_event, "presence_id");
3112  }
3113  if (local_var_event) {
3114  switch_event_del_header(local_var_event, "presence_id");
3115  }
3116  }
3117 
3118 
3119  if (local_clobber) {
3120  if (var_event) {
3121  switch_event_header_t *header;
3122  /* install the vars from the {} params */
3123  for (header = var_event->headers; header; header = header->next) {
3125  }
3126  }
3127  }
3128 
3129  /* copy local originate vars to the channel */
3130  if (local_var_event) {
3131  switch_event_header_t *header;
3132  for (header = local_var_event->headers; header; header = header->next) {
3134  }
3135  switch_event_destroy(&local_var_event);
3136  }
3137 
3138  if (!local_clobber) {
3139  if (var_event) {
3140  switch_event_header_t *header;
3141  /* install the vars from the {} params */
3142  for (header = var_event->headers; header; header = header->next) {
3144  }
3145  }
3146  }
3147 
3148  if (oglobals.originate_status[i].peer_channel) {
3149  const char *vvar;
3150 
3151  if (switch_true(switch_channel_get_variable(oglobals.originate_status[i].peer_channel, "leg_required"))) {
3152  oglobals.originate_status[i].tagged = 1;
3153  }
3154 
3155  if ((vvar = switch_channel_get_variable(oglobals.originate_status[i].peer_channel, "origination_channel_name"))) {
3157  }
3158 
3159  if ((vvar = switch_channel_get_variable(oglobals.originate_status[i].peer_channel, "origination_callee_id_name"))) {
3160  switch_channel_set_profile_var(oglobals.originate_status[i].peer_channel, "callee_id_name", vvar);
3161  }
3162 
3163  if ((vvar = switch_channel_get_variable(oglobals.originate_status[i].peer_channel, "origination_callee_id_number"))) {
3164  switch_channel_set_profile_var(oglobals.originate_status[i].peer_channel, "callee_id_number", vvar);
3165  }
3166 
3167  if ((vvar = switch_channel_get_variable(oglobals.originate_status[i].peer_channel, "leg_timeout"))) {
3168  int val = atoi(vvar);
3169 
3170  if (val > 0) {
3171  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg timeout to %d\n",
3173  oglobals.originate_status[i].per_channel_timelimit_sec = (uint32_t) val;
3174  }
3175  }
3176 
3177  if ((vvar = switch_channel_get_variable(oglobals.originate_status[i].peer_channel, "leg_progress_timeout"))) {
3178  int val = atoi(vvar);
3179  if (val > 0) {
3180  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg progress timeout to %d\n",
3182  oglobals.originate_status[i].per_channel_progress_timelimit_sec = (uint32_t) val;
3183  }
3184  }
3185 
3186  if ((vvar = switch_channel_get_variable(oglobals.originate_status[i].peer_channel, "leg_delay_start"))) {
3187  int val = atoi(vvar);
3188  if (val > 0) {
3189  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Setting leg delay start to %d\n",
3191  oglobals.originate_status[i].per_channel_delay_start = (uint32_t) val;
3192 
3195  }
3196 
3197  if (oglobals.originate_status[i].per_channel_timelimit_sec != 0) {
3199  }
3200  }
3201  }
3202 
3203  if (!zstr(ent_aleg_uuid)) {
3204  l_session = switch_core_session_locate(ent_aleg_uuid);
3205  a_session = l_session;
3206  }
3207 
3208  if (a_session) {
3209  switch_channel_t *channel = switch_core_session_get_channel(a_session);
3210  char *val =
3211  switch_core_session_sprintf(a_session, "%s;%s;%s",
3214  switch_str_nil(switch_channel_get_variable(oglobals.originate_status[i].peer_channel, "callee_id_number")));
3215 
3216 
3217  switch_channel_set_variable(oglobals.originate_status[i].peer_channel, "originating_leg_uuid", switch_core_session_get_uuid(a_session));
3218 
3219  switch_channel_add_variable_var_check(channel, "originated_legs", val, SWITCH_FALSE, SWITCH_STACK_PUSH);
3220 
3221  }
3222 
3223  if (l_session) {
3224  switch_core_session_rwunlock(l_session);
3225  l_session = NULL;
3226  }
3227 
3228  switch_channel_set_variable(oglobals.originate_status[i].peer_channel, "originate_endpoint", chan_type);
3231  }
3232 
3233  if (table) {
3235  }
3236 
3237  if (oglobals.monitor_early_media_ring || oglobals.monitor_early_media_fail || oglobals.ignore_early_media == 4) {
3239  }
3240 
3242 
3243  if ((flags & SOF_NOBLOCK) && oglobals.originate_status[i].peer_session) {
3244  status = SWITCH_STATUS_SUCCESS;
3245  *bleg = oglobals.originate_status[i].peer_session;
3246  *cause = SWITCH_CAUSE_SUCCESS;
3247  goto outer_for;
3248  }
3249 
3251  if (oglobals.originate_status[i].per_channel_delay_start) {
3253  }
3255  }
3256  }
3257 
3258  switch_epoch_time_now(&start);
3259 
3260  for (;;) {
3261  uint32_t valid_channels = 0;
3262  for (i = 0; i < and_argc; i++) {
3263  int state;
3264  time_t elapsed;
3265 
3266  if (!oglobals.originate_status[i].peer_channel) {
3267  continue;
3268  }
3269 
3271 
3272  if (state < CS_HANGUP) {
3273  valid_channels++;
3274  } else {
3275  continue;
3276  }
3277 
3278  if (state >= CS_ROUTING) {
3279  goto endfor1;
3280  }
3281 
3282  if (caller_channel && !switch_channel_ready(caller_channel)) {
3283  goto notready;
3284  }
3285 
3286  elapsed = switch_epoch_time_now(NULL) - start;
3287 
3288  if (elapsed > (time_t) timelimit_sec) {
3289  to++;
3290  oglobals.idx = IDX_TIMEOUT;
3291  goto notready;
3292  }
3293 
3294  if (!oglobals.sent_ring && !oglobals.ignore_ring_ready &&
3295  !oglobals.progress && (progress_timelimit_sec && elapsed > (time_t) progress_timelimit_sec)) {
3296  to++;
3297  oglobals.idx = IDX_TIMEOUT;
3298  if (force_reason == SWITCH_CAUSE_NONE) {
3299  force_reason = SWITCH_CAUSE_PROGRESS_TIMEOUT;
3300  }
3301  goto notready;
3302  }
3303 
3304  switch_cond_next();
3305  }
3306 
3307  check_per_channel_timeouts(&oglobals, and_argc, start, &force_reason);
3308 
3309 
3310  if (valid_channels == 0) {
3311  status = SWITCH_STATUS_GENERR;
3312  goto done;
3313  }
3314 
3315  }
3316 
3317  endfor1:
3318 
3319  if (caller_channel) {
3320  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) ||
3322  ringback_data = NULL;
3323  }
3324  }
3325 
3326 
3327 #if 0
3328  /* changing behaviour ignore_early_media=true must also be explicitly set for previous behaviour */
3329  if (ringback_data) {
3330  oglobals.early_ok = 0;
3331  }
3332 #endif
3333 
3334  if (ringback_data) {
3335  oglobals.sending_ringback = 1;
3336  } else {
3337  oglobals.ringback_ok = 0;
3338  }
3339 
3340  if (caller_channel) {
3341  soft_holding = switch_channel_get_variable(caller_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
3342  }
3343 
3344  while ((!caller_channel || switch_channel_ready(caller_channel) || switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) &&
3345  check_channel_status(&oglobals, and_argc, &force_reason, start)) {
3346  time_t elapsed = switch_epoch_time_now(NULL) - start;
3347  read_packet = 0;
3348 
3349  if (cancel_cause && *cancel_cause > 0) {
3350  if (force_reason == SWITCH_CAUSE_NONE) {
3351  force_reason = *cancel_cause;
3352  }
3353  oglobals.idx = IDX_CANCEL;
3354  goto notready;
3355  }
3356 
3357  check_per_channel_timeouts(&oglobals, and_argc, start, &force_reason);
3358 
3359  if (oglobals.session) {
3361  }
3362 
3363  if (!oglobals.sent_ring && !oglobals.progress && (progress_timelimit_sec && elapsed > (time_t) progress_timelimit_sec)) {
3364  oglobals.idx = IDX_TIMEOUT;
3365  if (force_reason == SWITCH_CAUSE_NONE) {
3366  force_reason = SWITCH_CAUSE_PROGRESS_TIMEOUT;
3367  }
3368  goto notready;
3369  }
3370 
3371  if ((to = (uint8_t) (elapsed >= (time_t) timelimit_sec)) || (fail_on_single_reject && oglobals.hups)) {
3372  int ok = 0;
3373 
3374  if (fail_on_single_reject_var) {
3375  if (!switch_true(fail_on_single_reject_var)) {
3376  ok = 1;
3377 
3378  for (i = 0; i < and_argc; i++) {
3379  switch_channel_t *pchannel;
3380  const char *cause_str;
3381 
3382  if (!oglobals.originate_status[i].peer_session) {
3383  continue;
3384  }
3386 
3387  if (switch_channel_down_nosig(pchannel)) {
3388  int neg, pos;
3389  cause_str = switch_channel_cause2str(switch_channel_get_cause(pchannel));
3390  neg = *fail_on_single_reject_var == '!';
3391  pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
3392 
3393  if (neg) {
3394  pos = !pos;
3395  }
3396 
3397  if (pos) {
3398  ok = 0;
3399  break;
3400  }
3401  }
3402  }
3403  }
3404  }
3405  if (!ok) {
3406  oglobals.idx = IDX_TIMEOUT;
3407  goto notready;
3408  }
3409  }
3410 
3411  /* read from the channel while we wait if the audio is up on it */
3412  if (oglobals.session &&
3413  !switch_channel_test_flag(caller_channel, CF_PROXY_MODE) &&
3414  !switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) &&
3415  //!switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE) &&
3416  switch_channel_up(caller_channel) &&
3417  (oglobals.ringback_ok
3418  || (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)))) {
3419 
3421  int silence = 0;
3422 
3423  if (caller_channel && cancel_key) {
3424  if (switch_channel_has_dtmf(caller_channel)) {
3425  switch_dtmf_t dtmf = { 0, 0 };
3426  if (switch_channel_dequeue_dtmf(caller_channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
3427  if (dtmf.digit == *cancel_key) {
3428  oglobals.idx = IDX_KEY_CANCEL;
3429  goto notready;
3430  }
3431  }
3432  }
3433  }
3434 
3435  if (switch_channel_media_ready(caller_channel)) {
3436  tstatus = switch_core_session_read_frame(oglobals.session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
3437  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
3438  if (soft_holding) {
3439  switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
3440  }
3441 
3442  if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
3443  goto do_continue;
3444  }
3445  break;
3446  }
3447 
3448  read_packet++;
3449  } else {
3450  read_frame = NULL;
3451  }
3452 
3453 
3454  if (oglobals.ringback_ok && (oglobals.ring_ready || oglobals.instant_ringback ||
3455  oglobals.sending_ringback > 1 || oglobals.bridge_early_media > -1)) {
3456  if (oglobals.ringback_ok == 1) {
3457  switch_status_t rst;
3458 
3459  rst = setup_ringback(&oglobals, oglobals.originate_status, and_argc, ringback_data, &ringback, &write_frame, &write_codec);
3460 
3461  if (oglobals.bridge_early_media > -1) {
3462  switch_threadattr_t *thd_attr = NULL;
3465  early_state.oglobals = &oglobals;
3466  //early_state.originate_status = oglobals.originate_status;
3467  early_state.ready = 1;
3468  early_state.ringback = &ringback;
3469  early_state.ttl = and_argc;
3471  switch_buffer_create_dynamic(&early_state.buffer, 1024, 1024, 0);
3472  switch_thread_create(&oglobals.ethread, thd_attr, early_thread_run, &early_state, switch_core_session_get_pool(session));
3473  }
3474 
3475 
3476  switch (rst) {
3477  case SWITCH_STATUS_SUCCESS:
3478  oglobals.ringback_ok++;
3479  break;
3480  case SWITCH_STATUS_FALSE:
3481  goto notready;
3482  break;
3483  case SWITCH_STATUS_BREAK:
3484  status = SWITCH_STATUS_FALSE;
3485  goto done;
3486  break;
3487  default:
3488  ringback_data = NULL;
3489  oglobals.ringback_ok = 0;
3490  oglobals.sending_ringback = 0;
3491  break;
3492  }
3493 
3494  goto do_continue;
3495  }
3496 
3497  if (oglobals.bridge_early_media > -1) {
3498  write_frame.datalen = 0;
3499  switch_mutex_lock(early_state.mutex);
3500  if (ringback.asis) {
3501  uint16_t mlen;
3503  if (buflen > sizeof(uint16_t)) {
3504  switch_buffer_peek(early_state.buffer, &mlen, sizeof(uint16_t));
3505  if (buflen >= (mlen + sizeof(uint16_t))) {
3506  switch_buffer_toss(early_state.buffer, sizeof(uint16_t));
3507  write_frame.datalen = (uint32_t)switch_buffer_read(early_state.buffer, write_frame.data, mlen);
3508  }
3509  }
3510  } else {
3511  if (write_frame.codec && switch_buffer_inuse(early_state.buffer) >= write_frame.codec->implementation->decoded_bytes_per_packet) {
3512  write_frame.datalen = (uint32_t)switch_buffer_read(early_state.buffer, write_frame.data,
3514  }
3515  }
3516  switch_mutex_unlock(early_state.mutex);
3517  } else if (ringback.fh) {
3518  switch_size_t mlen, olen;
3519  unsigned int pos = 0;
3520 
3521  if (ringback.asis) {
3522  mlen = write_frame.codec->implementation->encoded_bytes_per_packet;
3523  } else {
3524  mlen = write_frame.codec->implementation->samples_per_packet;
3525  }
3526 
3527  olen = mlen;
3528 
3529  //if (ringback.fh->resampler && ringback.fh->resampler->rfactor > 1) {
3530  //olen = (switch_size_t) (olen * ringback.fh->resampler->rfactor);
3531  //}
3532 
3533  switch_core_file_read(ringback.fh, write_frame.data, &olen);
3534 
3535  if (olen == 0) {
3536  olen = mlen;
3537  ringback.fh->speed = 0;
3538  switch_core_file_seek(ringback.fh, &pos, 0, SEEK_SET);
3539  switch_core_file_read(ringback.fh, write_frame.data, &olen);
3540  if (olen == 0) {
3541  break;
3542  }
3543  }
3544  write_frame.datalen = (uint32_t) (ringback.asis ? olen : olen * 2 * ringback.fh->channels);
3545  write_frame.samples = (uint32_t) olen;
3546 
3547  } else if (ringback.audio_buffer) {
3548  if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(ringback.audio_buffer,
3549  write_frame.data,
3550  write_frame.codec->implementation->decoded_bytes_per_packet)) <=
3551  0) {
3552 
3553  if (soft_holding) {
3554  switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
3555  goto do_continue;
3556  }
3557 
3558  break;
3559  }
3560  } else if (ringback.silence) {
3561  silence = ringback.silence;
3562  }
3563  } else {
3564  silence = 600;
3565  }
3566 
3567  if ((ringback.fh || silence || ringback.audio_buffer || oglobals.bridge_early_media > -1) && write_frame.codec && write_frame.codec->implementation && write_frame.datalen) {
3568  if (silence) {
3569  write_frame.datalen = read_impl.decoded_bytes_per_packet;
3570  switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, write_frame.codec->implementation->number_of_channels, silence);
3571  }
3572 
3574  if (soft_holding) {
3575  switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE);
3576  }
3577  if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
3578  goto do_continue;
3579  }
3580  break;
3581  }
3582  }
3583 
3584  }
3585 
3586  do_continue:
3587 
3588  if (!read_packet) {
3589  switch_yield(20000);
3590  }
3591  }
3592 
3593  notready:
3594 
3595  if (caller_channel) {
3596  holding = switch_channel_get_variable(caller_channel, SWITCH_HOLDING_UUID_VARIABLE);
3598 
3599  if (soft_holding && switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
3600  holding = soft_holding;
3601  soft_holding = NULL;
3603  }
3604  }
3605 
3606  if (caller_channel && !switch_channel_ready(caller_channel) && !switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
3607  oglobals.idx = IDX_CANCEL;
3608  }
3609 
3610  if (oglobals.session && (ringback_data || !(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) ||
3611  switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)))) {
3613  }
3614 
3615  if (holding) {
3616  if (oglobals.idx > IDX_NADA) {
3617  peer_session = oglobals.originate_status[oglobals.idx].peer_session;
3618  peer_channel = oglobals.originate_status[oglobals.idx].peer_channel;
3619  oglobals.originate_status[oglobals.idx].peer_channel = NULL;
3620  } else if (and_argc == 1) {
3621  peer_session = oglobals.originate_status[0].peer_session;
3622  peer_channel = oglobals.originate_status[0].peer_channel;
3623  oglobals.originate_status[0].peer_channel = NULL;
3624  } else {
3625  for (i = 0; i < and_argc; i++) {
3626  if (!peer_eligible(oglobals.originate_status[i].peer_channel)) {
3627  continue;
3628  }
3630  peer_session = oglobals.originate_status[i].peer_session;
3631  peer_channel = oglobals.originate_status[i].peer_channel;
3632  oglobals.originate_status[i].peer_channel = NULL;
3633  goto end_search;
3634  }
3635  }
3636  for (i = 0; i < and_argc; i++) {
3637  if (!peer_eligible(oglobals.originate_status[i].peer_channel)) {
3638  continue;
3639  }
3641  peer_session = oglobals.originate_status[i].peer_session;
3642  peer_channel = oglobals.originate_status[i].peer_channel;
3643  oglobals.originate_status[i].peer_channel = NULL;
3644  break;
3645  }
3646  }
3647  }
3648 
3649  end_search:
3650 
3651  if (peer_channel && switch_channel_down_nosig(peer_channel)) {
3652  switch_core_session_rwunlock(peer_session);
3653  peer_session = NULL;
3654  peer_channel = NULL;
3655 
3656  }
3657 
3658  if (oglobals.idx == IDX_TIMEOUT || to || oglobals.idx == IDX_KEY_CANCEL || oglobals.idx == IDX_CANCEL ||
3659  (!peer_session && oglobals.idx == IDX_NADA)) {
3660  const char *dest = NULL;
3661  const char *context = NULL;
3662  const char *dialplan = NULL;
3663  switch_core_session_t *holding_session;
3664 
3665  if (caller_channel) {
3666  if (zstr(context)) {
3667  context = switch_channel_get_variable(caller_channel, "context");
3668  }
3669  if (zstr(dialplan)) {
3670  dialplan = switch_channel_get_variable(caller_channel, "dialplan");
3671  }
3672  }
3673 
3674  if (zstr(context)) {
3675  context = "default";
3676  }
3677 
3678  if (zstr(context)) {
3679  dialplan = "XML";
3680  }
3681 
3682  if ((holding_session = switch_core_session_locate(holding))) {
3683  switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
3685 
3686  if (caller_channel) {
3687  if ((mstatus = switch_channel_caller_extension_masquerade(caller_channel, holding_channel, 0)) == SWITCH_STATUS_SUCCESS) {
3688  switch_channel_restart(holding_channel);
3689  }
3690  }
3691 
3692  if (mstatus != SWITCH_STATUS_SUCCESS) {
3693  if (peer_channel) {
3694  dest = switch_channel_get_variable(peer_channel, "destination_number");
3695  context = switch_channel_get_variable(peer_channel, "context");
3696  dialplan = switch_channel_get_variable(peer_channel, "dialplan");
3697  } else if (caller_channel) {
3698  dest = switch_channel_get_variable(caller_channel, "destination_number");
3699  }
3700  if (dest) {
3701  switch_ivr_session_transfer(holding_session, dest, dialplan, context);
3702  }
3703  }
3704 
3705  switch_core_session_rwunlock(holding_session);
3706  holding = NULL;
3707  holding_session = NULL;
3708  }
3709 
3710  if (peer_channel) {
3712  switch_core_session_rwunlock(peer_session);
3713  }
3714  if (force_reason == SWITCH_CAUSE_NONE) {
3715  force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
3716  }
3717  } else if (zstr(soft_holding)) {
3718 
3719  if (peer_channel && switch_channel_ready(peer_channel)) {
3720  switch_core_session_t *holding_session;
3721 
3722  if (force_reason == SWITCH_CAUSE_NONE) {
3723  force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
3724  }
3725 
3726  if ((holding_session = switch_core_session_locate(holding))) {
3728  switch_core_session_rwunlock(holding_session);
3729  }
3731  switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(peer_session));
3732  holding = NULL;
3733  oglobals.idx = IDX_XFER;
3734  if (caller_channel && switch_channel_up_nosig(caller_channel) && !switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
3736  }
3737  caller_channel = NULL;
3738  oglobals.session = NULL;
3739  session = NULL;
3740  switch_core_session_rwunlock(peer_session);
3741  } else {
3742  switch_core_session_t *holding_session;
3743 
3744  if ((holding_session = switch_core_session_locate(holding))) {
3745  switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
3746 
3747  if (caller_channel && switch_channel_ready(caller_channel)) {
3750  holding = NULL;
3751  } else {
3753  }
3754  switch_core_session_rwunlock(holding_session);
3755  }
3756  }
3757  }
3758 
3759  peer_session = NULL;
3760  peer_channel = NULL;
3761  }
3762 
3763  for (i = 0; i < and_argc; i++) {
3764  if (!peer_eligible(oglobals.originate_status[i].peer_channel)) {
3765  continue;
3766  }
3767 
3768  if (i != oglobals.idx) {
3769  holding = NULL;
3770 
3771  if (oglobals.idx == IDX_TIMEOUT || to) {
3772  reason = SWITCH_CAUSE_NO_ANSWER;
3773  } else {
3774  if (oglobals.idx == IDX_CANCEL) {
3776  } else {
3777  if (and_argc > 1) {
3778  reason = SWITCH_CAUSE_LOSE_RACE;
3779  } else if (!switch_channel_ready(oglobals.originate_status[i].peer_channel)) {
3783  }
3784  } else {
3785  reason = SWITCH_CAUSE_NO_ANSWER;
3786  }
3787  }
3788  }
3790  if (caller_channel && i == 0) {
3793  }
3794 
3795  if (holding && oglobals.idx != IDX_TIMEOUT && oglobals.idx != IDX_KEY_CANCEL && oglobals.idx < 0) {
3796  switch_core_session_t *holding_session;
3797 
3798  if ((holding_session = switch_core_session_locate(holding))) {
3799  switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
3800 
3802 
3803  if (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "recording_follow_transfer"))) {
3805  }
3806 
3807  if (switch_true(switch_channel_get_variable(holding_channel, "recording_follow_transfer"))) {
3808  switch_ivr_transfer_recordings(holding_session, oglobals.originate_status[i].peer_session);
3809  }
3810 
3811  switch_core_session_rwunlock(holding_session);
3812  }
3815  holding = NULL;
3816  } else {
3817  if (force_reason == SWITCH_CAUSE_LOSE_RACE || reason == SWITCH_CAUSE_LOSE_RACE) {
3818  switch_channel_set_variable(oglobals.originate_status[i].peer_channel, "group_dial_status", "loser");
3819  }
3820  switch_channel_hangup(oglobals.originate_status[i].peer_channel, force_reason ? force_reason : reason);
3821  }
3822  }
3823  }
3824  }
3825 
3826 
3827 
3828  if (oglobals.idx > IDX_NADA) {
3829  if ((peer_session = oglobals.originate_status[oglobals.idx].peer_session)) {
3830  peer_channel = switch_core_session_get_channel(oglobals.originate_status[oglobals.idx].peer_session);
3831  }
3832  } else {
3833  status = SWITCH_STATUS_FALSE;
3834  if (caller_channel && peer_channel) {
3835  switch_process_import(oglobals.session, peer_channel, "import", NULL);
3836  }
3837  peer_channel = NULL;
3838  goto done;
3839  }
3840 
3841  if (caller_channel) {
3842 
3843  if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE) && !switch_channel_up(caller_channel)) {
3844  if (switch_channel_media_up(peer_channel)) {
3845  oglobals.idx = IDX_XFER;
3846  reason = force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
3847  switch_channel_execute_on(peer_channel, "execute_on_orphaned_bleg");
3848  switch_channel_api_on(peer_channel, "api_on_orphaned_bleg");
3849  }
3850  } else if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
3851  switch_channel_pass_callee_id(peer_channel, caller_channel);
3852  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
3853  status = SWITCH_STATUS_SUCCESS;
3854  } else {
3855  status = switch_channel_answer(caller_channel);
3856  }
3857  } else if (switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
3858  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
3859  status = SWITCH_STATUS_SUCCESS;
3860  } else {
3861  switch_channel_pass_callee_id(peer_channel, caller_channel);
3862  status = switch_channel_pre_answer(caller_channel);
3863  }
3864  } else {
3865  status = SWITCH_STATUS_SUCCESS;
3866  }
3867 
3868  if (status != SWITCH_STATUS_SUCCESS) {
3869  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(peer_channel), SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n",
3870  switch_channel_get_name(caller_channel));
3872  }
3873  }
3874 
3875  if (switch_channel_test_flag(peer_channel, CF_ANSWERED) ||
3876  (oglobals.early_ok && switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) ||
3877  (oglobals.return_ring_ready && switch_channel_test_flag(peer_channel, CF_RING_READY))
3878  ) {
3879  *bleg = peer_session;
3880 
3881  if (oglobals.monitor_early_media_ring || oglobals.monitor_early_media_fail) {
3883  switch_channel_set_private(peer_channel, "_oglobals_", NULL);
3884  }
3885 
3886  status = SWITCH_STATUS_SUCCESS;
3887  } else {
3888  status = SWITCH_STATUS_FALSE;
3889  }
3890 
3891  done:
3892 
3893  *cause = SWITCH_CAUSE_NONE;
3894 
3895  if (caller_channel && !switch_channel_ready(caller_channel)) {
3896  status = SWITCH_STATUS_FALSE;
3897  }
3898 
3899  if (status == SWITCH_STATUS_SUCCESS) {
3900  if (caller_channel) {
3901  switch_channel_set_variable(caller_channel, "originate_disposition", "call accepted");
3902  if (peer_channel) {
3903  switch_process_import(oglobals.session, peer_channel, "import", NULL);
3904 
3905  if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
3906  switch_channel_set_variable(caller_channel, "DIALSTATUS", "EARLY");
3907  } else {
3908  switch_channel_set_variable(caller_channel, "DIALSTATUS", "ANSWER");
3909  }
3910 
3911  }
3912  }
3913  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oglobals.session), SWITCH_LOG_DEBUG, "Originate Resulted in Success: [%s] Peer UUID: %s\n",
3914  switch_channel_get_name(peer_channel), switch_channel_get_uuid(peer_channel));
3915  *cause = SWITCH_CAUSE_SUCCESS;
3916 
3917  } else {
3918  const char *cdr_var = NULL;
3919  const char *json_cdr_var = NULL;
3920 
3921  switch_xml_t cdr = NULL;
3922  cJSON *json_cdr = NULL;
3923 
3924  char *json_text;
3925  char *xml_text;
3926  char buf[128] = "", buf2[128] = "";
3927 
3928  if (caller_channel) {
3929  cdr_var = switch_channel_get_variable(caller_channel, "failed_xml_cdr_prefix");
3930  }
3931 
3932  if (caller_channel) {
3933  json_cdr_var = switch_channel_get_variable(caller_channel, "failed_json_cdr_prefix");
3934  }
3935 
3936  if (peer_channel) {
3937  wait_for_cause(peer_channel);
3938  *cause = switch_channel_get_cause(peer_channel);
3939  } else {
3940  for (i = 0; i < and_argc; i++) {
3941  if (!oglobals.originate_status[i].peer_channel) {
3942  continue;
3943  }
3945  break;
3946  }
3947  }
3948 
3949  if (cdr_var) {
3950  for (i = 0; i < and_argc; i++) {
3951  switch_channel_t *channel;
3952 
3953  if (!oglobals.originate_status[i].peer_session) {
3954  continue;
3955  }
3956 
3958 
3960 
3961  if (!switch_channel_test_flag(channel, CF_TIMESTAMP_SET)) {
3963  }
3964 
3966  if ((xml_text = switch_xml_toxml(cdr, SWITCH_FALSE))) {
3967  switch_snprintf(buf, sizeof(buf), "%s_%d", cdr_var, ++cdr_total);
3968  switch_channel_set_variable(caller_channel, buf, xml_text);
3969  switch_safe_free(xml_text);
3970  }
3971  switch_xml_free(cdr);
3972  cdr = NULL;
3973  }
3974 
3975  }
3976  switch_snprintf(buf, sizeof(buf), "%s_total", cdr_var);
3977  switch_snprintf(buf2, sizeof(buf2), "%d", cdr_total ? cdr_total : 0);
3978  switch_channel_set_variable(caller_channel, buf, buf2);
3979  }
3980 
3981  if (json_cdr_var) {
3982  for (i = 0; i < and_argc; i++) {
3983  switch_channel_t *channel;
3984 
3985  if (!oglobals.originate_status[i].peer_session) {
3986  continue;
3987  }
3988 
3990 
3992 
3993  if (!switch_channel_test_flag(channel, CF_TIMESTAMP_SET)) {
3995  }
3996 
3998  json_text = cJSON_PrintUnformatted(json_cdr);
3999  switch_snprintf(buf, sizeof(buf), "%s_%d", json_cdr_var, ++cdr_total);
4000  switch_channel_set_variable(caller_channel, buf, json_text);
4001  // switch_safe_free(json_text);
4002  cJSON_Delete(json_cdr);
4003  json_cdr = NULL;
4004  }
4005 
4006  }
4007  switch_snprintf(buf, sizeof(buf), "%s_total", json_cdr_var);
4008  switch_snprintf(buf2, sizeof(buf2), "%d", cdr_total ? cdr_total : 0);
4009  switch_channel_set_variable(caller_channel, buf, buf2);
4010  }
4011 
4012  if (caller_channel && switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
4013  *cause = SWITCH_CAUSE_PICKED_OFF;
4014  }
4015 
4016  if (!*cause) {
4017  if (reason) {
4018  *cause = reason;
4019  } else if (caller_channel) {
4020  *cause = switch_channel_get_cause(caller_channel);
4021  } else {
4023  for (i = 0; i < and_argc; i++) {
4024  if (!peer_eligible(oglobals.originate_status[i].peer_channel)) {
4025  continue;
4026  }
4027 
4029 
4032  break;
4033  }
4034 
4035  }
4036  }
4037  }
4038 
4039  if (*cause == SWITCH_CAUSE_SUCCESS || *cause == SWITCH_CAUSE_NONE) {
4041  }
4042 
4043  if (oglobals.idx == IDX_CANCEL) {
4046  "Originate Cancelled by originator termination Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
4047 
4048  } else if (oglobals.idx == IDX_TIMEOUT) {
4049  *cause = SWITCH_CAUSE_NO_ANSWER;
4050  } else {
4051  if (oglobals.idx == IDX_XFER) {
4053  "Originate Resulted in Attended Transfer Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
4054  } else {
4055 
4057  "Originate Resulted in Error Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
4058  }
4059  }
4060  }
4061 
4062  if (caller_channel) {
4063  switch_channel_set_variable(caller_channel, "originate_disposition", switch_channel_cause2str(*cause));
4064 
4065  switch (*cause) {
4067  switch_channel_set_variable(caller_channel, "DIALSTATUS", "CANCEL");
4068  break;
4070  switch_channel_set_variable(caller_channel, "DIALSTATUS", "BUSY");
4071  break;
4073  switch_channel_set_variable(caller_channel, "DIALSTATUS", "NOANSWER");
4074  break;
4077  switch_channel_set_variable(caller_channel, "DIALSTATUS", "INVALIDARGS");
4078  break;
4080  switch_channel_set_variable(caller_channel, "DIALSTATUS", "DONTCALL");
4081  break;
4082  default:
4083  switch_channel_set_variable(caller_channel, "DIALSTATUS", switch_channel_cause2str(*cause));
4084  break;
4085  }
4086  }
4087 
4088  early_state.ready = 0;
4089 
4090  if (oglobals.ethread) {
4091  switch_status_t st;
4092  switch_thread_join(&st, oglobals.ethread);
4093  }
4094 
4095  if (early_state.buffer) {
4096  switch_buffer_destroy(&early_state.buffer);
4097  }
4098 
4099  if (ringback.fh) {
4100  switch_core_file_close(ringback.fh);
4101  ringback.fh = NULL;
4102  } else if (ringback.audio_buffer) {
4103  teletone_destroy_session(&ringback.ts);
4104  switch_safe_free(ringback.mux_buf);
4106  }
4107 
4108  if (oglobals.session) {
4110  }
4111 
4112  if (switch_core_codec_ready(&write_codec)) {
4113  switch_core_codec_destroy(&write_codec);
4114  }
4115 
4116  for (i = 0; i < and_argc; i++) {
4117  switch_channel_state_t state;
4118  switch_core_session_t *peer_session;
4119  char *val;
4120 
4121  if (!oglobals.originate_status[i].peer_channel) {
4122  continue;
4123  }
4124 
4125  if (session) {
4126  val = switch_core_session_sprintf(oglobals.originate_status[i].peer_session, "%s;%s",
4129 
4131  }
4132 
4133  if (status == SWITCH_STATUS_SUCCESS) {
4135  if (bleg && *bleg && *bleg == oglobals.originate_status[i].peer_session) {
4136  continue;
4137  }
4138  } else if ((state = switch_channel_get_state(oglobals.originate_status[i].peer_channel)) < CS_HANGUP &&
4143  if (caller_channel && switch_channel_test_flag(caller_channel, CF_INTERCEPTED)) {
4145  }
4147  }
4148  }
4150 
4151  peer_session = oglobals.originate_status[i].peer_session;
4152  oglobals.originate_status[i].down_session = oglobals.originate_status[i].peer_session;
4153  oglobals.originate_status[i].peer_session = NULL;
4154  oglobals.originate_status[i].peer_channel = NULL;
4155 
4156  switch_core_session_rwunlock(peer_session);
4157  }
4158 
4159  if (status == SWITCH_STATUS_SUCCESS || oglobals.idx == IDX_XFER) {
4160  goto outer_for;
4161  } else {
4162  int ok = 1;
4163 
4164  if (fail_on_single_reject && check_reject && !switch_true(fail_on_single_reject_var)) {
4165  for (i = 0; i < and_argc; i++) {
4166  switch_channel_t *pchannel;
4167  const char *cause_str;
4168 
4169  if (!oglobals.originate_status[i].down_session) {
4170  continue;
4171  }
4172 
4174  wait_for_cause(pchannel);
4175 
4176  if (switch_channel_down_nosig(pchannel)) {
4177  int neg, pos;
4178 
4179  cause_str = switch_channel_cause2str(switch_channel_get_cause(pchannel));
4180 
4181  neg = *fail_on_single_reject_var == '!';
4182  pos = !!switch_stristr(cause_str, fail_on_single_reject_var);
4183 
4184  if (neg) {
4185  pos = !pos;
4186  }
4187 
4188  if (pos) {
4189  ok = 0;
4190  break;
4191  }
4192  }
4193  }
4194  }
4195 
4196  if (!ok) {
4197  goto outer_for;
4198  }
4199 
4200  if (to && !oglobals.continue_on_timeout) {
4201  goto outer_for;
4202  }
4203  }
4204  }
4205  }
4206  outer_for:
4207  switch_safe_free(loop_data);
4208  switch_safe_free(odata);
4209  switch_safe_free(oglobals.file);
4210  switch_safe_free(oglobals.error_file);
4211 
4212  if (bleg && status != SWITCH_STATUS_SUCCESS) {
4213  *bleg = NULL;
4214  }
4215 
4216  if (bleg && !*bleg && status == SWITCH_STATUS_SUCCESS) {
4217  status = SWITCH_STATUS_FALSE;
4218  }
4219 
4220  if (bleg && *bleg) {
4222 
4223  if (session && caller_channel) {
4225 
4226  if (peer_profile) {
4227  if ((cloned_profile = switch_caller_profile_clone(session, peer_profile)) != 0) {
4228  switch_channel_set_originatee_caller_profile(caller_channel, cloned_profile);
4229  }
4230  }
4231 
4233  // Now main SWITCH_SIGNAL_BOND_VARIABLE is populated, don't need this one anymore...
4235  }
4236 
4237 
4240 
4241 
4242  while(switch_channel_state_change_pending(bchan)) {
4243  switch_cond_next();
4244  }
4245 
4247 
4248  if (caller_channel) {
4249  switch_channel_audio_sync(caller_channel);
4250  }
4251  }
4252 
4253  if (oglobals.session) {
4255  }
4256 
4257  if (oglobals.session && status == SWITCH_STATUS_SUCCESS) {
4258  switch_ivr_sleep(oglobals.session, 0, SWITCH_TRUE, NULL);
4259  }
4260 
4261  if (var_event && var_event != ovars) {
4262  switch_event_destroy(&var_event);
4263  }
4264 
4265  switch_safe_free(write_frame.data);
4266  switch_safe_free(fail_on_single_reject_var);
4267 
4268  if (force_reason != SWITCH_CAUSE_NONE) {
4269  *cause = force_reason;
4270  }
4271 
4272  if (caller_channel) {
4273 
4276 
4277  switch_channel_clear_flag(caller_channel, CF_ORIGINATOR);
4278  switch_channel_clear_flag(caller_channel, CF_XFER_ZOMBIE);
4279 
4280  if (hangup_on_single_reject) {
4281  switch_channel_hangup(caller_channel, *cause);
4282  }
4283  }
4284 
4285 
4287 
4288  return status;
4289 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
#define SWITCH_DEFAULT_CLID_NUMBER
Definition: switch_types.h:115
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&#39;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)
static int check_per_channel_timeouts(originate_global_t *oglobals, int max, time_t start, switch_call_cause_t *force_reason)
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
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.
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#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:700
switch_status_t switch_channel_set_timestamps(_In_ switch_channel_t *channel)
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
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:796
#define switch_event_del_header(_e, _h)
Definition: switch_event.h:212
switch_core_session_t * down_session
static char * switch_sanitize_number(char *number)
Definition: switch_utils.h:737
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:157
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_channel_up(_channel)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:590
cJSON *const to
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, switch_dial_handle_list_t *hl)
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:733
#define UNQUOTED_ESC_COMMA
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:683
#define SWITCH_CALL_TIMEOUT_VARIABLE
Definition: switch_types.h:171
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
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:191
#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_bool_t switch_is_number(const char *str)
switch_thread_t * ethread
A representation of an XML tree.
Definition: switch_xml.h:79
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.
uint32_t switch_originate_flag_t
Definition: switch_types.h:335
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_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:913
switch_event_header_t * switch_channel_variable_first(switch_channel_t *channel)
Start iterating over the entries in the channel variable list.
switch_status_t switch_ivr_media(const char *uuid, switch_media_flag_t flags)
Signal a session to request direct media access to it&#39;s remote end.
Definition: switch_ivr.c:1773
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)
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:56
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:179
#define SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE
Definition: switch_types.h:204
#define zstr(x)
Definition: switch_utils.h:314
#define SWITCH_DEFAULT_CLID_NAME
Definition: switch_types.h:114
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:313
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:219
#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:155
originate_status_t originate_status[MAX_PEERS]
int64_t switch_time_t
Definition: switch_apr.h:188
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:70
switch_byte_t switch_byte_t * buf
#define SWITCH_SOFT_HOLDING_UUID_VARIABLE
Definition: switch_types.h:173
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
#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:68
switch_event_t * switch_dial_handle_get_global_vars(switch_dial_handle_t *handle)
#define SWITCH_DEFAULT_TIMEOUT
Definition: switch_types.h:117
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:308
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:190
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:584
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:885
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:293
#define SWITCH_BLANK_STRING
Definition: switch_types.h:48
int switch_dial_handle_get_vars(switch_dial_handle_t *handle, int idx, switch_event_t **array, int max)
#define SWITCH_ENT_ORIGINATE_DELIM
Definition: switch_types.h:47
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1379
#define switch_channel_down_nosig(_channel)
An abstraction of a data frame.
Definition: switch_frame.h:54
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:658
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:386
char * switch_channel_get_uuid(switch_channel_t *channel)
Retrieve the given channel&#39;s unique id.
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
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:993
static int switch_channel_var_true(switch_channel_t *channel, const char *variable)
switch_core_session_t * peer_session
#define SWITCH_CHANNEL_API_ON_POST_ORIGINATE_VARIABLE
Definition: switch_types.h:168
unsigned int switch_core_session_running(_In_ switch_core_session_t *session)
determine if the session&#39;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:3335
switch_status_t
Common return values.
ringback_t * ringback
#define SWITCH_HOLDING_UUID_VARIABLE
Definition: switch_types.h:172
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:287
originate_global_t * oglobals
struct switch_event_header * next
Definition: switch_event.h:76
#define SWITCH_SIGNAL_BOND_VARIABLE
Definition: switch_types.h:203
void switch_channel_variable_last(switch_channel_t *channel)
Stop iterating over channel variables.
void switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
Set the given channel&#39;s originatee caller profile.
#define SWITCH_CHANNEL_EXECUTE_ON_POST_ORIGINATE_VARIABLE
Definition: switch_types.h:156
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&#39;s uuid.
Definition: switch_core.h:932
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:199
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
#define SWITCH_INT64_T_FMT
uint32_t samples
Definition: switch_frame.h:72
#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:167
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:322
const char * caller_id_number
Definition: switch_caller.h:81
#define SWITCH_CHANNEL_API_ON_PRE_ORIGINATE_VARIABLE
Definition: switch_types.h:169
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
int switch_dial_handle_get_peers(switch_dial_handle_t *handle, int idx, char **array, int max)
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:665
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:698
A table of settings and callbacks that define a paticular implementation of a codec.
switch_status_t switch_ivr_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session)
static int switch_false(const char *expr)
Evaluate the falsefullness of a string expression.
Definition: switch_utils.h:551
#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
int switch_dial_handle_get_total(switch_dial_handle_t *handle)
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:2862
#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&#39;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_event_serialize(switch_event_t *event, char **str, switch_bool_t encode)
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.
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)
static uint8_t check_channel_status(originate_global_t *oglobals, uint32_t len, switch_call_cause_t *force_reason, time_t start)
#define SWITCH_READ_ACCEPTABLE(status)
memset(buf, 0, buflen)
#define switch_channel_media_up(_channel)
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.
switch_event_header_t * headers
Definition: switch_event.h:90
#define SWITCH_EXPORT_VARS_VARIABLE
Definition: switch_types.h:195
switch_call_cause_t switch_channel_get_cause(_In_ switch_channel_t *channel)
return the cause code for a given channel
#define switch_xml_toxml(xml, prn_header)
Converts an switch_xml structure back to xml in html format. Returns a string of html data that \ mus...
Definition: switch_xml.h:224
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_ivr_park()

switch_status_t switch_ivr_park ( switch_core_session_t session,
switch_input_args_t args 
)

Definition at line 946 of file switch_ivr.c.

References switch_codec_implementation::actual_samples_per_second, arg_recursion_check_start, arg_recursion_check_stop, switch_input_args_t::buf, switch_frame::buflen, switch_input_args_t::buflen, CF_CONTROLLED, CF_PARK, CF_RECOVERED, CF_SERVICE, CF_UNICAST, switch_frame::codec, CS_RESET, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, switch_input_args_t::dmachine, switch_input_args_t::input_callback, 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, to, and unicast_thread_launch().

Referenced by switch_core_standard_on_park().

947 {
950  switch_frame_t *read_frame = NULL;
951  int stream_id = 0;
952  switch_event_t *event;
953  switch_unicast_conninfo_t *conninfo = NULL;
954  uint32_t rate = 0;
955  uint32_t bpf = 0;
956  const char *to;
957  int timeout = 0;
958  time_t expires = 0;
959  switch_codec_implementation_t read_impl = { 0 };
961  switch_codec_t codec = { 0 };
962  int sval = 0;
963  const char *var;
964  switch_frame_t write_frame = { 0 };
965  unsigned char *abuf = NULL;
966  switch_codec_implementation_t imp = { 0 };
967 
968 
969 
972  }
973 
974  if (switch_channel_test_flag(channel, CF_CONTROLLED)) {
975  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot park channels that are under control already.\n");
976  return SWITCH_STATUS_FALSE;
977  }
978 
979  if (switch_channel_get_state(channel) == CS_RESET) {
980  return SWITCH_STATUS_FALSE;
981  }
982 
984 
985  if ((to = switch_channel_get_variable(channel, "park_timeout"))) {
986  char *cause_str;
987 
988  if ((cause_str = strchr(to, ':'))) {
989  timeout_cause = switch_channel_str2cause(cause_str + 1);
990  }
991 
992  if ((timeout = atoi(to)) >= 0) {
993  expires = switch_epoch_time_now(NULL) + timeout;
994  }
995  switch_channel_set_variable(channel, "park_timeout", NULL);
997  }
998 
1000  switch_channel_set_flag(channel, CF_PARK);
1001 
1003  switch_channel_event_set_data(channel, event);
1004  switch_event_fire(&event);
1005  }
1006 
1008 
1009  if (!rate && switch_channel_media_ready(channel)) {
1010  switch_core_session_get_read_impl(session, &read_impl);
1011  rate = read_impl.actual_samples_per_second;
1012  bpf = read_impl.decoded_bytes_per_packet;
1013 
1014  if (rate && (var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
1015  switch_core_session_get_read_impl(session, &imp);
1016 
1017  if (switch_core_codec_init(&codec,
1018  "L16",
1019  NULL,
1020  NULL,
1022  imp.microseconds_per_packet / 1000,
1023  imp.number_of_channels,
1026  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
1029  }
1030 
1031 
1032  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
1034 
1035  write_frame.codec = &codec;
1037  write_frame.data = abuf;
1038  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
1039  write_frame.datalen = imp.decoded_bytes_per_packet;
1040  write_frame.samples = write_frame.datalen / sizeof(int16_t);
1041  }
1042  }
1043 
1044  if (rate) {
1045  if (switch_channel_test_flag(channel, CF_SERVICE)) {
1046  switch_cond_next();
1047  status = SWITCH_STATUS_SUCCESS;
1048  } else {
1049  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, stream_id);
1050  }
1051  } else {
1052  switch_yield(20000);
1053 
1055  switch_ivr_parse_event(session, event);
1056  switch_event_destroy(&event);
1057  }
1058 
1059  status = SWITCH_STATUS_SUCCESS;
1060  }
1061 
1062  if (!SWITCH_READ_ACCEPTABLE(status)) {
1063  break;
1064  }
1065 
1066  if (rate && write_frame.data && sval) {
1067  switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, read_impl.number_of_channels, sval);
1068  switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
1069  }
1070 
1071  if (expires && switch_epoch_time_now(NULL) >= expires) {
1072  switch_channel_hangup(channel, timeout_cause);
1073  break;
1074  }
1075 
1076  if (switch_channel_test_flag(channel, CF_UNICAST)) {
1077  if (!switch_channel_media_ready(channel)) {
1080  }
1081  }
1082 
1083  if (!conninfo) {
1084  if (!(conninfo = switch_channel_get_private(channel, "unicast"))) {
1086  }
1087 
1088  if (conninfo) {
1089  unicast_thread_launch(conninfo);
1090  }
1091  }
1092 
1093  if (conninfo) {
1094  switch_size_t len = 0;
1095  uint32_t flags = 0;
1097  uint32_t dlen = sizeof(decoded);
1098  switch_status_t tstatus;
1099  switch_byte_t *sendbuf = NULL;
1100  uint32_t sendlen = 0;
1101 
1102  switch_assert(read_frame);
1103 
1104  if (switch_test_flag(read_frame, SFF_CNG)) {
1105  sendlen = bpf;
1107  memset(decoded, 255, sendlen);
1108  sendbuf = decoded;
1109  tstatus = SWITCH_STATUS_SUCCESS;
1110  } else {
1111  if (switch_test_flag(conninfo, SUF_NATIVE)) {
1112  tstatus = SWITCH_STATUS_NOOP;
1113  } else {
1114  switch_codec_t *read_codec = switch_core_session_get_read_codec(session);
1115  tstatus = switch_core_codec_decode(read_codec,
1116  &conninfo->read_codec,
1117  read_frame->data,
1118  read_frame->datalen, read_impl.actual_samples_per_second, decoded, &dlen, &rate, &flags);
1119  }
1120  switch (tstatus) {
1121  case SWITCH_STATUS_NOOP:
1122  case SWITCH_STATUS_BREAK:
1123  sendbuf = read_frame->data;
1124  sendlen = read_frame->datalen;
1125  tstatus = SWITCH_STATUS_SUCCESS;
1126  break;
1127  case SWITCH_STATUS_SUCCESS:
1128  sendbuf = decoded;
1129  sendlen = dlen;
1130  tstatus = SWITCH_STATUS_SUCCESS;
1131  break;
1132  default:
1135  break;
1136  }
1137  }
1138 
1139  if (tstatus == SWITCH_STATUS_SUCCESS) {
1140  len = sendlen;
1141  if (switch_socket_sendto(conninfo->socket, conninfo->remote_addr, 0, (void *) sendbuf, &len) != SWITCH_STATUS_SUCCESS) {
1143  }
1144  }
1145  }
1146  }
1147 
1148  switch_ivr_parse_all_events(session);
1149 
1150 
1151  if (switch_channel_has_dtmf(channel)) {
1152  switch_dtmf_t dtmf = { 0 };
1153 
1154  if (args && !args->input_callback && !args->buf && !args->dmachine) {
1155  status = SWITCH_STATUS_BREAK;
1156  break;
1157  }
1158 
1159  switch_channel_dequeue_dtmf(channel, &dtmf);
1160 
1161  if (args) {
1162  if (args->dmachine) {
1163  char ds[2] = {dtmf.digit, '\0'};
1164  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
1165  break;
1166  }
1167  }
1168 
1169  if (args->input_callback) {
1170  if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
1171  break;
1172  }
1173  }
1174  }
1175  }
1176 
1178  if (args && args->input_callback) {
1179  switch_status_t ostatus;
1180 
1181  if ((ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
1182  status = ostatus;
1183  break;
1184  }
1185  } else {
1186  switch_channel_event_set_data(channel, event);
1187  switch_event_fire(&event);
1188  }
1189  }
1190 
1191  if (args && args->dmachine) {
1192  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1193  break;
1194  }
1195  }
1196 
1197 
1198  }
1199 
1200  end:
1201 
1203 
1204  if (write_frame.codec) {
1205  switch_core_codec_destroy(&codec);
1206  }
1207 
1208  switch_safe_free(abuf);
1209 
1212 
1214  switch_channel_event_set_data(channel, event);
1215  switch_event_fire(&event);
1216  }
1217 
1218  if (switch_channel_test_flag(channel, CF_UNICAST)) {
1220  }
1221 
1222  return status;
1223 }
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:413
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it&#39;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:590
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.
cJSON *const to
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:913
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:56
uint8_t switch_byte_t
Definition: switch_types.h:256
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:131
#define SWITCH_PARK_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:220
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:361
uint32_t buflen
Definition: switch_frame.h:70
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
uint32_t datalen
Definition: switch_frame.h:68
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:796
switch_status_t switch_ivr_parse_event(switch_core_session_t *session, switch_event_t *event)
Definition: switch_ivr.c:503
#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:885
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:54
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:1693
void switch_cond_next(void)
Definition: switch_time.c:658
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:287
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:384
uint32_t samples
Definition: switch_frame.h:72
#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:322
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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:371
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)
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_ivr_parse_all_events()

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 913 of file switch_ivr.c.

References CF_BLOCK_BROADCAST_UNTIL_MEDIA, CF_PROXY_MODE, switch_channel_clear_flag(), switch_channel_media_up, SWITCH_CHANNEL_SESSION_LOG, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_get_name, switch_core_session_stack_count(), switch_ivr_parse_all_messages(), switch_ivr_parse_next_event(), SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_MAX_STACKS, SWITCH_STATUS_FALSE, 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_event(), switch_ivr_session_echo(), switch_ivr_sleep(), switch_ivr_speak_text_handle(), and switch_ivr_wait_for_answer().

914 {
915  switch_channel_t *channel;
916  uint32_t stack_count = 0;
917  if ((stack_count = switch_core_session_stack_count(session, 0)) > SWITCH_MAX_STACKS) {
918  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error %s too many stacked extensions [depth=%d]\n",
919  switch_core_session_get_name(session), stack_count);
920  return SWITCH_STATUS_FALSE;
921  }
922 
924 
926 
927  channel = switch_core_session_get_channel(session);
928 
930  if (switch_channel_media_up(channel)) {
932  } else {
933  goto done;
934  }
935  }
936 
938 
939  done:
940  switch_core_session_stack_count(session, -1);
941 
942  return SWITCH_STATUS_SUCCESS;
943 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define SWITCH_MAX_STACKS
Definition: switch_types.h:583
#define switch_core_session_get_name(_s)
Definition: switch_core.h:265
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:796
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.
#define switch_channel_media_up(_channel)
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:847
uint32_t switch_core_session_stack_count(switch_core_session_t *session, int x)

◆ switch_ivr_parse_all_messages()

switch_status_t switch_ivr_parse_all_messages ( switch_core_session_t session)

Definition at line 847 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(), read_rtp_packet(), 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().

848 {
850  int i = 0;
851 
853 
854  while (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) {
855  i++;
856 
857  if (switch_ivr_process_indications(session, message) == SWITCH_STATUS_SUCCESS) {
859  } else {
860  switch_core_session_receive_message(session, message);
861  message = NULL;
862  }
863  }
864 
866 }
switch_status_t switch_ivr_parse_all_signal_data(switch_core_session_t *session)
Definition: switch_ivr.c:905
switch_status_t switch_ivr_process_indications(switch_core_session_t *session, switch_core_session_message_t *message)
Definition: switch_ivr.c:813
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:179
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
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_ivr_parse_all_signal_data()

switch_status_t switch_ivr_parse_all_signal_data ( switch_core_session_t session)

Definition at line 905 of file switch_ivr.c.

References SWITCH_FALSE, switch_ivr_parse_signal_data(), and SWITCH_TRUE.

Referenced by switch_ivr_parse_all_messages().

905  {
907 }
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:869

◆ switch_ivr_parse_event()

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

◆ switch_ivr_parse_next_event()

switch_status_t switch_ivr_parse_next_event ( switch_core_session_t session)

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

797 {
798  switch_event_t *event;
800 
802  status = switch_ivr_parse_event(session, event);
803  event->event_id = SWITCH_EVENT_PRIVATE_COMMAND;
806  switch_event_fire(&event);
807  }
808 
809  return status;
810 
811 }
#define switch_event_prep_for_delivery(_event)
Definition: switch_event.h:243
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
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:503
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_ivr_parse_next_signal_data()

switch_status_t switch_ivr_parse_next_signal_data ( switch_core_session_t session)

Definition at line 909 of file switch_ivr.c.

References SWITCH_FALSE, and switch_ivr_parse_signal_data().

909  {
911 }
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:869

◆ switch_ivr_parse_signal_data()

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 869 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().

870 {
871  void *data;
872  switch_core_session_message_t msg = { 0 };
873  int i = 0;
875 
876  if (only_session_thread && !switch_core_session_in_thread(session)) {
877  return SWITCH_STATUS_FALSE;
878  }
879 
881  return SWITCH_STATUS_FALSE;
882  }
883 
885 
887  msg.from = __FILE__;
888 
890  i++;
891 
892  msg.pointer_arg = data;
894 
895  data = NULL;
896  if (!all)
897  break;
898  }
899 
901 
903 }
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
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:179
_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:1247
#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_ivr_pause_detect_speech()

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 5245 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 CoreSession::detectSpeech(), switch_ivr_play_and_collect_input(), and switch_ivr_play_and_detect_speech().

5246 {
5249 
5250  if (sth) {
5251  switch_core_asr_pause(sth->ah);
5252  return SWITCH_STATUS_SUCCESS;
5253  }
5254  return SWITCH_STATUS_FALSE;
5255 }
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:233
_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_ivr_play_and_detect_speech()

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 4882 of file switch_ivr_async.c.

References arg_recursion_check_start, arg_recursion_check_stop, switch_input_args_t::buf, switch_input_args_t::buflen, switch_input_args_t::dmachine, play_and_detect_speech_state_t::done, switch_input_args_t::input_callback, play_and_detect_speech_state_t::original_args, PLAY_AND_DETECT_DONE, PLAY_AND_DETECT_DONE_RECOGNIZING, play_and_detect_input_callback(), switch_input_args_t::read_frame_callback, play_and_detect_speech_state_t::result, switch_channel_get_name(), switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_var_true(), 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_input_args_t::user_data.

Referenced by CoreSession::playAndDetectSpeech().

4889 {
4891  int recognizing = 0;
4892  switch_input_args_t myargs = { 0 };
4893  play_and_detect_speech_state_t state = { 0, "", NULL };
4895 
4897 
4898  if (result == NULL) {
4899  goto done;
4900  }
4901 
4902  if (!input_timeout) input_timeout = 5000;
4903 
4904  /* start speech detection */
4905  if ((status = switch_ivr_detect_speech(session, mod_name, grammar, "", NULL, NULL)) != SWITCH_STATUS_SUCCESS) {
4906  /* map SWITCH_STATUS_FALSE to SWITCH_STATUS_GENERR to indicate grammar load failed
4907  SWITCH_STATUS_NOT_INITALIZED will be passed back to indicate ASR resource problem */
4908  if (status == SWITCH_STATUS_FALSE) {
4909  status = SWITCH_STATUS_GENERR;
4910  }
4911  goto done;
4912  }
4913  recognizing = 1;
4914 
4915  /* play the prompt, looking for detection result */
4916 
4917  if (args) {
4918  state.original_args = args;
4919  myargs.dmachine = args->dmachine;
4921  myargs.user_data = args->user_data;
4922  }
4923 
4925  myargs.buf = &state;
4926  myargs.buflen = sizeof(state);
4927 
4928  status = switch_ivr_play_file(session, NULL, file, &myargs);
4929 
4930  if (args && args->dmachine && switch_ivr_dmachine_last_ping(args->dmachine) != SWITCH_STATUS_SUCCESS) {
4931  state.done |= PLAY_AND_DETECT_DONE;
4932  goto done;
4933  }
4934 
4935  if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) {
4936  status = SWITCH_STATUS_FALSE;
4937  goto done;
4938  }
4939 
4940  /* wait for result if not done */
4941  if (!state.done) {
4943  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) WAITING FOR RESULT\n", switch_channel_get_name(channel));
4944  while (!state.done && switch_channel_ready(channel)) {
4945  status = switch_ivr_sleep(session, input_timeout, SWITCH_FALSE, &myargs);
4946 
4947  if (args && args->dmachine && switch_ivr_dmachine_last_ping(args->dmachine) != SWITCH_STATUS_SUCCESS) {
4948  state.done |= PLAY_AND_DETECT_DONE;
4949  goto done;
4950  }
4951 
4952  if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) {
4953  status = SWITCH_STATUS_FALSE;
4954  goto done;
4955  }
4956  }
4957  }
4958 
4959 done:
4960  if (recognizing && !(state.done & PLAY_AND_DETECT_DONE_RECOGNIZING)) {
4962  }
4963  if (recognizing && switch_channel_var_true(channel, "play_and_detect_speech_close_asr")) {
4965  }
4966 
4967  if (state.done) {
4968  status = SWITCH_STATUS_SUCCESS;
4969  }
4970  if (result) {
4971  *result = state.result;
4972  }
4973 
4975 
4976  return status;
4977 }
switch_input_args_t * original_args
#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
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.
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_read_frame_callback_function_t read_frame_callback
static int switch_channel_var_true(switch_channel_t *channel, const char *variable)
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_ivr_play_file()

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 1244 of file switch_ivr_play_say.c.

References switch_codec_implementation::actual_samples_per_second, arg_recursion_check_start, arg_recursion_check_stop, switch_file_handle::audio_buffer, switch_directories::base_dir, switch_input_args_t::buf, switch_frame::buflen, buflen, switch_input_args_t::buflen, CF_BREAK, CF_HOLD, CF_VIDEO, switch_frame::channels, switch_file_handle::channels, switch_frame::codec, cur, switch_file_handle::cur_channels, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, switch_input_args_t::dmachine, switch_codec_implementation::encoded_bytes_per_packet, FILE_BLOCKSIZE, FILE_BUFSIZE, FILE_STARTSAMPLES, switch_codec_implementation::iananame, switch_codec::implementation, switch_input_args_t::input_callback, memset(), switch_codec_implementation::microseconds_per_packet, switch_file_handle::native_rate, switch_codec_implementation::number_of_channels, switch_file_handle::offset_pos, switch_file_handle::params, pool, switch_file_handle::prebuf, switch_file_handle::prefix, switch_frame::rate, switch_input_args_t::read_frame_callback, switch_timer::samplecount, switch_file_handle::samplerate, switch_frame::samples, switch_file_handle::samples, switch_file_handle::samples_in, switch_codec_implementation::samples_per_packet, switch_codec_implementation::samples_per_second, switch_file_handle::sp_audio_buffer, switch_file_handle::speed, 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_change_sln_volume_granular(), 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_OPEN, 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_input_args_t::user_data, switch_file_handle::vol, switch_file_handle::volgranular, 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_collect_input(), switch_ivr_play_and_detect_speech(), switch_ivr_read(), switch_ivr_soft_hold(), and switch_play_and_get_digits().

1245 {
1247  int16_t *abuf = NULL;
1248  switch_dtmf_t dtmf = { 0 };
1249  uint32_t interval = 0, samples = 0, framelen, sample_start = 0, channels = 1;
1250  uint32_t ilen = 0;
1251  switch_size_t olen = 0, llen = 0;
1252  switch_frame_t write_frame = { 0 };
1253  switch_timer_t timer = { 0 };
1254  switch_codec_t codec = { 0 };
1256  char *codec_name;
1259  const char *p;
1260  //char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
1261  char *ext;
1262  char *backup_file = NULL;
1263  const char *backup_ext;
1264  const char *prefix;
1265  const char *timer_name;
1266  const char *prebuf;
1267  const char *alt = NULL;
1268  const char *sleep_val;
1269  const char *play_delimiter_val;
1270  char play_delimiter = 0;
1271  int sleep_val_i = 250;
1272  int eof = 0;
1273  switch_size_t bread = 0;
1274  switch_codec_implementation_t read_impl = { 0 };
1275  char *file_dup;
1276  char *argv[128] = { 0 };
1277  int argc;
1278  int cur;
1279  int done = 0;
1280  int timeout_samples = 0;
1281  switch_bool_t timeout_as_success = SWITCH_FALSE;
1282  const char *var;
1283  int more_data = 0;
1284  switch_event_t *event;
1285  uint32_t test_native = 0, last_native = 0;
1286  uint32_t buflen = 0;
1287  int flags;
1288  int cumulative = 0;
1289  int last_speed = -1;
1290 
1292  return SWITCH_STATUS_FALSE;
1293  }
1294 
1295  switch_core_session_get_read_impl(session, &read_impl);
1296 
1297  if ((var = switch_channel_get_variable(channel, "playback_timeout_sec_cumulative"))) {
1298  int tmp = atoi(var);
1299  if (tmp > 1) {
1300  timeout_samples = read_impl.actual_samples_per_second * tmp;
1301  cumulative = 1;
1302  }
1303 
1304  } else if ((var = switch_channel_get_variable(channel, "playback_timeout_sec"))) {
1305  int tmp = atoi(var);
1306  if (tmp > 1) {
1307  timeout_samples = read_impl.actual_samples_per_second * tmp;
1308  }
1309  }
1310 
1311  if ((var = switch_channel_get_variable(channel, "playback_timeout_as_success"))) {
1312  if (switch_true(var)) {
1313  timeout_as_success = SWITCH_TRUE;
1314  }
1315  }
1316  if ((play_delimiter_val = switch_channel_get_variable(channel, "playback_delimiter"))) {
1317  play_delimiter = *play_delimiter_val;
1318 
1319  if ((sleep_val = switch_channel_get_variable(channel, "playback_sleep_val"))) {
1320  int tmp = atoi(sleep_val);
1321  if (tmp >= 0) {
1322  sleep_val_i = tmp;
1323  }
1324  }
1325  }
1326 
1327  prefix = switch_channel_get_variable(channel, "sound_prefix");
1328  timer_name = switch_channel_get_variable(channel, "timer_name");
1329 
1330  if (zstr(file) || !switch_channel_media_ready(channel)) {
1331  return SWITCH_STATUS_FALSE;
1332  }
1333 
1335 
1336  if (play_delimiter) {
1337  file_dup = switch_core_session_strdup(session, file);
1338  argc = switch_separate_string(file_dup, play_delimiter, argv, (sizeof(argv) / sizeof(argv[0])));
1339  } else {
1340  argc = 1;
1341  argv[0] = (char *) file;
1342  }
1343 
1344  if (!fh) {
1345  fh = &lfh;
1346  memset(fh, 0, sizeof(lfh));
1347  }
1348 
1349  if (fh->samples > 0) {
1350  sample_start = fh->samples;
1351  fh->samples = 0;
1352  }
1353 
1354 
1355 
1356 
1357  for (cur = 0; switch_channel_ready(channel) && !done && cur < argc; cur++) {
1358  file = argv[cur];
1359  eof = 0;
1360 
1361  if (cur) {
1362  fh->samples = sample_start = 0;
1363  if (sleep_val_i) {
1364  status = switch_ivr_sleep(session, sleep_val_i, SWITCH_FALSE, args);
1365  if(status != SWITCH_STATUS_SUCCESS) {
1366  break;
1367  }
1368  }
1369  }
1370 
1371  status = SWITCH_STATUS_SUCCESS;
1372 
1373  if (strchr(file, ':')) {
1374  char *dup;
1375 
1376  if (!strncasecmp(file, "phrase:", 7)) {
1377  char *arg = NULL;
1378  const char *lang = switch_channel_get_variable(channel, "language");
1379  alt = file + 7;
1380  dup = switch_core_session_strdup(session, alt);
1381 
1382  if (dup) {
1383  if ((arg = strchr(dup, ':'))) {
1384  *arg++ = '\0';
1385  }
1386  if ((status = switch_ivr_phrase_macro(session, dup, arg, lang, args)) != SWITCH_STATUS_SUCCESS) {
1387  break;
1388  }
1389  continue;
1390  } else {
1391  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
1392  continue;
1393  }
1394  } else if (!strncasecmp(file, "say:", 4)) {
1395  const char *engine = NULL, *voice = NULL, *text = NULL;
1396 
1397  alt = file + 4;
1398  text = alt;
1399  engine = switch_channel_get_variable(channel, "tts_engine");
1400  voice = switch_channel_get_variable(channel, "tts_voice");
1401 
1402  if (engine && text) {
1403  if ((status = switch_ivr_speak_text(session, engine, voice, (char *)text, args)) != SWITCH_STATUS_SUCCESS) {
1404  break;
1405  }
1406  } else {
1407  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
1408  }
1409 
1410  continue;
1411  }
1412 
1413  }
1414 
1415  if (!prefix) {
1416  prefix = SWITCH_GLOBAL_dirs.base_dir;
1417  }
1418 
1419  if (!strstr(file, SWITCH_URL_SEPARATOR)) {
1420  if (!switch_is_file_path(file)) {
1421  char *tfile = NULL;
1422  char *e;
1423 
1424  if (*file == '{') {
1425  tfile = switch_core_session_strdup(session, file);
1426 
1427  while (*file == '{') {
1428  if ((e = switch_find_end_paren(tfile, '{', '}'))) {
1429  *e = '\0';
1430  file = e + 1;
1431  while(*file == ' ') file++;
1432  } else {
1433  tfile = NULL;
1434  break;
1435  }
1436  }
1437  }
1438 
1439  file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "}" : "", prefix, SWITCH_PATH_SEPARATOR, file);
1440  }
1441  if ((ext = strrchr(file, '.'))) {
1442  ext++;
1443  } else {
1444 
1445  if (!(backup_ext = switch_channel_get_variable(channel, "native_backup_extension"))) {
1446  backup_ext = "wav";
1447  }
1448 
1449  ext = read_impl.iananame;
1450  backup_file = switch_core_session_sprintf(session, "%s.%s", file, backup_ext);
1451  file = switch_core_session_sprintf(session, "%s.%s", file, ext);
1452  }
1453  }
1454 
1455  if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
1456  int maybe = atoi(prebuf);
1457  if (maybe > 0) {
1458  fh->prebuf = maybe;
1459  }
1460  }
1461 
1462 
1463  if (!fh->prefix) {
1464  fh->prefix = prefix;
1465  }
1466 
1468 
1469  if (switch_channel_test_flag(channel, CF_VIDEO)) {
1470  flags |= SWITCH_FILE_FLAG_VIDEO;
1471  //switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
1472  }
1473 
1474 
1475  for(;;) {
1476  if (switch_core_file_open(fh,
1477  file,
1478  read_impl.number_of_channels,
1479  read_impl.actual_samples_per_second, flags, NULL) == SWITCH_STATUS_SUCCESS) {
1480  break;
1481  }
1482 
1483  if (backup_file) {
1484  file = backup_file;
1485  backup_file = NULL;
1486  } else {
1487  break;
1488  }
1489  }
1490 
1491  if (!switch_test_flag(fh, SWITCH_FILE_OPEN)) {
1493  status = SWITCH_STATUS_NOTFOUND;
1494  continue;
1495  }
1496 
1497  switch_channel_audio_sync(channel);
1499  switch_channel_set_private(channel, "__fh", fh);
1501 
1504  }
1505 
1506  if (!abuf) {
1507  write_frame.buflen = FILE_STARTSAMPLES * sizeof(*abuf) * fh->channels;
1508  switch_zmalloc(abuf, write_frame.buflen);
1509  write_frame.data = abuf;
1510  }
1511 
1512  if (sample_start > 0) {
1513  uint32_t pos = 0;
1514  switch_core_file_seek(fh, &pos, 0, SEEK_SET);
1515  switch_core_file_seek(fh, &pos, sample_start, SEEK_CUR);
1517  }
1518 
1520  //title = switch_core_session_strdup(session, p);
1521  switch_channel_set_variable(channel, "RECORD_TITLE", p);
1522  }
1523 
1525  //copyright = switch_core_session_strdup(session, p);
1526  switch_channel_set_variable(channel, "RECORD_COPYRIGHT", p);
1527  }
1528 
1530  //software = switch_core_session_strdup(session, p);
1531  switch_channel_set_variable(channel, "RECORD_SOFTWARE", p);
1532  }
1533 
1535  //artist = switch_core_session_strdup(session, p);
1536  switch_channel_set_variable(channel, "RECORD_ARTIST", p);
1537  }
1538 
1540  //comment = switch_core_session_strdup(session, p);
1541  switch_channel_set_variable(channel, "RECORD_COMMENT", p);
1542  }
1543 
1545  //date = switch_core_session_strdup(session, p);
1546  switch_channel_set_variable(channel, "RECORD_DATE", p);
1547  }
1548 
1549  interval = read_impl.microseconds_per_packet / 1000;
1550 
1551  codec_name = "L16";
1552 
1553  if (!switch_core_codec_ready((&codec))) {
1554  if (switch_core_codec_init(&codec,
1555  codec_name,
1556  NULL,
1557  NULL,
1558  fh->samplerate,
1559  interval, read_impl.number_of_channels,
1562  SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n",
1563  codec_name, fh->samplerate, read_impl.number_of_channels, interval);
1564 
1565 
1566  } else {
1568  "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name,
1569  fh->samplerate, read_impl.number_of_channels, interval);
1571  switch_channel_set_private(channel, "__fh", NULL);
1573 
1575 
1577 
1579  status = SWITCH_STATUS_GENERR;
1580  continue;
1581  }
1582  }
1583 
1584  test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
1585 
1586  if (test_native) {
1587  write_frame.codec = switch_core_session_get_read_codec(session);
1588  samples = read_impl.samples_per_packet;
1589  framelen = read_impl.encoded_bytes_per_packet;
1590  channels = read_impl.number_of_channels;
1591  if (framelen == 0) {
1592  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));
1593 
1595  switch_channel_set_private(channel, "__fh", NULL);
1597 
1600 
1602  status = SWITCH_STATUS_GENERR;
1603  continue;
1604 
1605  }
1606  } else {
1607  write_frame.codec = &codec;
1608  samples = codec.implementation->samples_per_packet;
1609  framelen = codec.implementation->decoded_bytes_per_packet;
1610  channels = codec.implementation->number_of_channels;
1611  }
1612 
1613  last_native = test_native;
1614 
1615  if (timer_name && !timer.samplecount) {
1616  uint32_t len;
1617 
1618  len = samples * 2 * channels;
1619  if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) {
1620  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n");
1621  switch_core_codec_destroy(&codec);
1623  switch_channel_set_private(channel, "__fh", NULL);
1625 
1627 
1630  status = SWITCH_STATUS_GENERR;
1631  continue;
1632  }
1633  switch_core_timer_sync(&timer); // Sync timer
1635  "Setup timer success %u bytes per %d ms! %d ch\n", len, interval, codec.implementation->number_of_channels);
1636  }
1637  write_frame.rate = fh->samplerate;
1638  write_frame.channels = fh->channels;
1639  if (timer_name) {
1640  /* start a thread to absorb incoming audio */
1641  switch_core_service_session(session);
1642  }
1643 
1644  ilen = samples * channels;
1645 
1647  switch_channel_event_set_data(channel, event);
1648  if (!strncasecmp(file, "local_stream:", 13)) {
1649  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "local_stream");
1650  }
1651  if (!strncasecmp(file, "tone_stream:", 12)) {
1652  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "tone_stream");
1653  }
1654  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file);
1655  if (fh->params) {
1656  switch_event_merge(event, fh->params);
1657  }
1658  switch_event_fire(&event);
1659  }
1660 
1661  if (!fh->audio_buffer) {
1664  }
1665 
1666  for (;;) {
1667  int do_speed = 1;
1668  int f;
1669 
1670  if (!switch_channel_ready(channel)) {
1671  status = SWITCH_STATUS_FALSE;
1672  break;
1673  }
1674 
1675  if ((f = switch_channel_test_flag(channel, CF_BREAK))) {
1677  if (f == 2) {
1678  done = 1;
1679  }
1680  status = SWITCH_STATUS_BREAK;
1681  break;
1682  }
1683 
1684  switch_ivr_parse_all_events(session);
1685 
1686  if (args) {
1687  /*
1688  dtmf handler function you can hook up to be executed when a digit is dialed during playback
1689  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
1690  */
1691  if (switch_channel_has_dtmf(channel)) {
1692  switch_channel_dequeue_dtmf(channel, &dtmf);
1693 
1694  if (!args->input_callback && !args->buf && !args->dmachine) {
1695  status = SWITCH_STATUS_BREAK;
1696  done = 1;
1697  break;
1698  }
1699 
1700 
1701  if (args->dmachine) {
1702  char ds[2] = {dtmf.digit, '\0'};
1703  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
1704  break;
1705  }
1706  }
1707 
1708  if (args->input_callback) {
1709  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
1710  } else if (args->buf) {
1711  *((char *) args->buf) = dtmf.digit;
1712  status = SWITCH_STATUS_BREAK;
1713  }
1714  }
1715 
1716  if (args->input_callback) {
1717  switch_event_t *event;
1718 
1720  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
1721  if (ostatus != SWITCH_STATUS_SUCCESS) {
1722  status = ostatus;
1723  }
1724 
1725  switch_event_destroy(&event);
1726  }
1727  }
1728 
1729  if (status != SWITCH_STATUS_SUCCESS) {
1730  done = 1;
1731  break;
1732  }
1733  }
1734 
1735  buflen = FILE_STARTSAMPLES * sizeof(*abuf) * (fh->cur_channels > 0 ? fh->cur_channels : fh->channels);
1736 
1737  if (buflen > write_frame.buflen) {
1738  abuf = realloc(abuf, buflen);
1739  write_frame.data = abuf;
1740  write_frame.buflen = buflen;
1741  }
1742 
1744  if (framelen > FILE_STARTSAMPLES) {
1745  framelen = FILE_STARTSAMPLES;
1746  }
1747  memset(abuf, 255, framelen);
1748  olen = ilen;
1749  do_speed = 0;
1750  } else if (fh->sp_audio_buffer && (eof || (switch_buffer_inuse(fh->sp_audio_buffer) > (switch_size_t) (framelen)))) {
1751  if (!(bread = switch_buffer_read(fh->sp_audio_buffer, abuf, framelen))) {
1752  if (eof) {
1753  break;
1754  } else {
1755  continue;
1756  }
1757  }
1758 
1759  if (bread < framelen) {
1760  memset(abuf + bread, 255, framelen - bread);
1761  }
1762 
1763  olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
1764  do_speed = 0;
1765  } else if (fh->audio_buffer && (eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (framelen)))) {
1766  if (!(bread = switch_buffer_read(fh->audio_buffer, abuf, framelen))) {
1767  if (eof) {
1768  break;
1769  } else {
1770  continue;
1771  }
1772  }
1773 
1774  fh->offset_pos += (uint32_t)(switch_test_flag(fh, SWITCH_FILE_NATIVE) ? bread : bread / 2);
1775 
1776  if (bread < framelen) {
1777  memset(abuf + bread, 255, framelen - bread);
1778  }
1779 
1780  olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
1781  } else {
1782  switch_status_t rstatus;
1783 
1784  if (eof) {
1785  break;
1786  }
1787  olen = FILE_STARTSAMPLES;
1789  olen /= 2;
1790  }
1792 
1793  if ((rstatus = switch_core_file_read(fh, abuf, &olen)) == SWITCH_STATUS_BREAK) {
1794  continue;
1795  }
1796 
1797  if (rstatus != SWITCH_STATUS_SUCCESS) {
1798  eof++;
1799  continue;
1800  }
1801 
1802  test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
1803 
1804  if (test_native != last_native) {
1805  if (test_native) {
1806  write_frame.codec = switch_core_session_get_read_codec(session);
1807  framelen = read_impl.encoded_bytes_per_packet;
1808  if (framelen == 0) {
1809  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));
1810  eof++;
1811  continue;
1812  }
1813  } else {
1814  write_frame.codec = &codec;
1815  framelen = codec.implementation->decoded_bytes_per_packet;
1816  }
1818  }
1819 
1820  last_native = test_native;
1821 
1822  switch_buffer_write(fh->audio_buffer, abuf, switch_test_flag(fh, SWITCH_FILE_NATIVE) ? olen : olen * 2 * fh->channels);
1823  olen = switch_buffer_read(fh->audio_buffer, abuf, framelen);
1824  fh->offset_pos += (uint32_t)(olen / 2);
1825 
1827  olen /= 2;
1828  }
1829 
1830  }
1831 
1832  if (done || olen <= 0) {
1833  break;
1834  }
1835 
1837  if (fh->speed > 2) {
1838  fh->speed = 2;
1839  } else if (fh->speed < -2) {
1840  fh->speed = -2;
1841  }
1842  }
1843 
1844  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
1846  }
1847 
1849  /* file position has changed flush the buffer */
1852  }
1853 
1854 
1855  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->speed && do_speed) {
1856  float factor = 0.25f * abs(fh->speed);
1857  switch_size_t newlen, supplement, step;
1858  short *bp = write_frame.data;
1859  switch_size_t wrote = 0;
1860 
1861  supplement = (int) (factor * olen);
1862  if (!supplement) {
1863  supplement = 1;
1864  }
1865  newlen = (fh->speed > 0) ? olen - supplement : olen + supplement;
1866 
1867  step = (fh->speed > 0) ? (newlen / supplement) : (olen / supplement);
1868 
1869  if (!fh->sp_audio_buffer) {
1870  switch_buffer_create_dynamic(&fh->sp_audio_buffer, 1024, 1024, 0);
1871  }
1872 
1873  while ((wrote + step) < newlen) {
1874  switch_buffer_write(fh->sp_audio_buffer, bp, step * 2);
1875  wrote += step;
1876  bp += step;
1877  if (fh->speed > 0) {
1878  bp++;
1879  } else {
1880  float f;
1881  short s;
1882  f = (float) (*bp + *(bp + 1) + *(bp - 1));
1883  f /= 3;
1884  s = (short) f;
1886  wrote++;
1887  }
1888  }
1889  if (wrote < newlen) {
1890  switch_size_t r = newlen - wrote;
1891  switch_buffer_write(fh->sp_audio_buffer, bp, r * 2);
1892  }
1893  last_speed = fh->speed;
1894  continue;
1895  }
1896 
1897  if (olen < llen) {
1898  uint8_t *dp = (uint8_t *) write_frame.data;
1899  memset(dp + (int) olen, 255, (int) (llen - olen));
1900  olen = llen;
1901  }
1902 
1903  if (!more_data) {
1904  if (timer_name) {
1906  break;
1907  }
1908  } else { /* time off the channel (if you must) */
1909  switch_frame_t *read_frame;
1910  switch_status_t tstatus;
1911 
1912  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
1914  switch_yield(10000);
1915  }
1916 
1917  tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_SINGLE_READ, 0);
1918 
1919 
1920  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
1921  break;
1922  }
1923 
1924  if (args && args->dmachine) {
1925  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
1926  break;
1927  }
1928  }
1929 
1930  if (args && (args->read_frame_callback)) {
1931  int ok = 1;
1933  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
1934  ok = 0;
1935  }
1937  if (!ok) {
1938  break;
1939  }
1940  }
1941  }
1942  }
1943 
1944  more_data = 0;
1945  write_frame.samples = (uint32_t) olen;
1946 
1948  write_frame.datalen = (uint32_t) olen;
1949  } else {
1950  write_frame.datalen = write_frame.samples * 2;
1951  }
1952 
1953  llen = olen;
1954 
1955  if (timer_name) {
1956  write_frame.timestamp = timer.samplecount;
1957  }
1958 #ifndef WIN32
1959 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
1960  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && l16) {
1961  switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);
1962  }
1963 #endif
1964 #endif
1966  if (fh->volgranular) {
1967  switch_change_sln_volume_granular(write_frame.data, write_frame.datalen / 2, fh->volgranular);
1968  } else if (fh->vol) { /* deprecated 2022-Q1 */
1969  switch_change_sln_volume(write_frame.data, write_frame.datalen / 2, fh->vol);
1970  }
1971  }
1972 
1973  /* write silence while dmachine is in reading state */
1974  if (args && args->dmachine && switch_ivr_dmachine_is_parsing(args->dmachine)) {
1975  memset(write_frame.data, 0, write_frame.datalen);
1976  }
1977 
1978  status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
1979 
1980  if (timeout_samples) {
1981  timeout_samples -= write_frame.samples;
1982  if (timeout_samples <= 0) {
1983  timeout_samples = 0;
1984  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "timeout reached playing file\n");
1985  if (timeout_as_success) {
1986  status = SWITCH_STATUS_SUCCESS;
1987  } else {
1988  status = SWITCH_STATUS_TIMEOUT;
1989  }
1990  done = 1;
1991  break;
1992  }
1993  }
1994 
1995 
1996  if (status == SWITCH_STATUS_MORE_DATA) {
1997  status = SWITCH_STATUS_SUCCESS;
1998  more_data = 1;
1999  continue;
2000  } else if (status != SWITCH_STATUS_SUCCESS) {
2001  done = 1;
2002  break;
2003  }
2004 
2005  if (done) {
2006  break;
2007  }
2008  }
2009 
2010  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done playing file %s\n", file);
2011  switch_channel_set_variable_printf(channel, "playback_last_offset_pos", "%d", fh->offset_pos);
2012 
2013  if (read_impl.samples_per_second && fh->native_rate >= 1000) {
2014  switch_channel_set_variable_printf(channel, "playback_seconds", "%d", fh->samples_in / fh->native_rate);
2015  switch_channel_set_variable_printf(channel, "playback_ms", "%d", fh->samples_in / (fh->native_rate / 1000));
2016  }
2017 
2018  switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_in);
2019 
2021  switch_channel_event_set_data(channel, event);
2022  if (!strncasecmp(file, "local_stream:", 13)) {
2023  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "local_stream");
2024  }
2025  if (!strncasecmp(file, "tone_stream:", 12)) {
2026  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Type", "tone_stream");
2027  }
2028  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file);
2029  if (status == SWITCH_STATUS_BREAK) {
2030  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "break");
2031  } else {
2032  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "done");
2033  }
2034  if (fh->params) {
2035  switch_event_merge(event, fh->params);
2036  }
2037  switch_event_fire(&event);
2038  }
2039 
2041  switch_channel_set_private(channel, "__fh", NULL);
2043 
2046 
2047  if (fh->audio_buffer) {
2049  }
2050 
2051  if (fh->sp_audio_buffer) {
2053  }
2054  }
2055 
2056  if (switch_core_codec_ready((&codec))) {
2057  switch_core_codec_destroy(&codec);
2058  }
2059 
2060  if (timer.samplecount) {
2061  /* End the audio absorbing thread */
2063  switch_core_timer_destroy(&timer);
2064  }
2065 
2066  switch_safe_free(abuf);
2067 
2069 
2071 
2072  if (timeout_samples && cumulative) {
2073  switch_channel_set_variable_printf(channel, "playback_timeout_sec_cumulative", "%d", timeout_samples / read_impl.actual_samples_per_second);
2074  }
2075 
2076 
2077  return status;
2078 }
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:413
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 ...
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#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:796
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:1963
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:437
uint32_t timestamp
Definition: switch_frame.h:80
#define SWITCH_URL_SEPARATOR
Definition: switch_types.h:126
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_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:913
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.
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_ivr_speak_text(switch_core_session_t *session, const char *tts_name, const char *voice_name, const char *text, switch_input_args_t *args)
Speak given text with given tts engine.
switch_codec_t * codec
Definition: switch_frame.h:56
#define zstr(x)
Definition: switch_utils.h:314
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:124
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:70
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
#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:68
void switch_event_merge(switch_event_t *event, switch_event_t *tomerge)
uint32_t rate
Definition: switch_frame.h:74
#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:885
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:54
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:707
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:1693
#define switch_core_service_session(_s)
Definition: switch_core.h:1216
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:82
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:993
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:717
#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
void switch_change_sln_volume_granular(int16_t *data, uint32_t samples, int32_t vol)
Change the volume of a signed linear audio frame with more granularity.
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:384
static switch_bool_t switch_is_file_path(const char *file)
uint32_t samples
Definition: switch_frame.h:72
uint32_t channels
Definition: switch_frame.h:76
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
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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:936
struct fspr_pool_t switch_memory_pool_t
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session&#39;s pool.
Definition: switch_core.h:719
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)
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:847

◆ switch_ivr_process_indications()

switch_status_t switch_ivr_process_indications ( switch_core_session_t session,
switch_core_session_message_t message 
)

Definition at line 813 of file switch_ivr.c.

References switch_core_session_message::message_id, 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_core_session_receive_message, SWITCH_MESSAGE_INDICATE_ANSWER, SWITCH_MESSAGE_INDICATE_PROGRESS, SWITCH_MESSAGE_INDICATE_RESPOND, SWITCH_MESSAGE_INDICATE_RINGING, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_core_session_flush_message(), and switch_ivr_parse_all_messages().

814 {
817 
818  switch(message->message_id) {
822  }
823  break;
827  }
828  break;
832  }
833  break;
835  switch_core_session_receive_message(session, message);
836  status = SWITCH_STATUS_SUCCESS;
837  break;
838 
839  default:
840  status = SWITCH_STATUS_FALSE;
841  break;
842  }
843 
844  return status;
845 }
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it&#39;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:183
_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.
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
switch_status_t
Common return values.
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.

◆ switch_ivr_record_file()

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_ivr_record_file_event()

switch_status_t switch_ivr_record_file_event ( _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,
switch_event_t vars 
)

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)
varsvars to add to RECORD_START and RECORD_STOP automatically prefixed with Recording-Variable-
Returns
SWITCH_STATUS_SUCCESS if all is well

◆ switch_ivr_record_session()

switch_status_t switch_ivr_record_session ( switch_core_session_t session,
const 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 3355 of file switch_ivr_async.c.

References switch_ivr_record_session_event().

3356 {
3357  return switch_ivr_record_session_event(session, file, limit, fh, NULL);
3358 }
switch_status_t switch_ivr_record_session_event(switch_core_session_t *session, const char *file, uint32_t limit, switch_file_handle_t *fh, switch_event_t *vars)

◆ switch_ivr_record_session_event()

switch_status_t switch_ivr_record_session_event ( switch_core_session_t session,
const char *  file,
uint32_t  limit,
switch_file_handle_t fh,
switch_event_t variables 
)

Definition at line 2927 of file switch_ivr_async.c.

References switch_codec_implementation::actual_samples_per_second, switch_directories::base_dir, record_helper::bug, CF_VIDEO, switch_file_handle::channels, record_helper::completion_cause, switch_codec_implementation::decoded_bytes_per_packet, record_helper::fh, record_helper::file, record_helper::final_timeout_ms, switch_core_session_message::from, get_recording_var(), record_helper::hangup_on_error, record_helper::helper_pool, 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::params, path, switch_file_handle::pre_buffer_datalen, record_helper::read_impl, record_callback(), record_helper_create(), record_helper_destroy(), recording_var_true(), switch_file_handle::samplerate, set_completion_cause(), 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_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), switch_channel_set_variable, switch_channel_set_variable_printf(), switch_channel_test_flag(), switch_core_alloc, switch_core_file_close(), switch_core_file_handle_dup(), 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_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_sprintf(), switch_core_strdup, SWITCH_DEFAULT_DIR_PERMS, SWITCH_DEFAULT_FILE_BUFFER_LEN, switch_dir_make_recursive(), switch_epoch_time_now(), switch_event_dup(), switch_event_get_header, 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_goto_status, 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(), SWITCH_URL_SEPARATOR, to, record_helper::variables, and zstr.

Referenced by switch_ivr_record_session().

2928 {
2930  const char *p;
2931  const char *vval;
2933  switch_status_t status;
2934  time_t to = 0;
2936  uint8_t channels;
2937  switch_codec_implementation_t read_impl = { 0 };
2938  struct record_helper *rh = NULL;
2941  char *file_path = NULL;
2942  char *ext;
2943  char *in_file = NULL, *out_file = NULL;
2945 
2946  if ((p = get_recording_var(channel, vars, "RECORD_HANGUP_ON_ERROR"))) {
2947  hangup_on_error = switch_true(p);
2948  }
2949 
2951  return SWITCH_STATUS_FALSE;
2952  }
2953 
2954  if (!switch_channel_media_up(channel) || !switch_core_session_get_read_codec(session)) {
2955  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can not record session. Media not enabled on channel\n");
2956  return SWITCH_STATUS_FALSE;
2957  }
2958 
2959  switch_core_session_get_read_impl(session, &read_impl);
2960  channels = read_impl.number_of_channels;
2961 
2962  if ((bug = switch_channel_get_private(channel, file))) {
2963  if (recording_var_true(channel, vars, "RECORD_TOGGLE_ON_REPEAT")) {
2964  return switch_ivr_stop_record_session(session, file);
2965  }
2966 
2967  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Already recording [%s]\n", file);
2968  return SWITCH_STATUS_SUCCESS;
2969  }
2970 
2971 
2972  if (recording_var_true(channel, vars, "RECORD_CHECK_BRIDGE")) {
2973  switch_core_session_t *other_session;
2974  int exist = 0;
2976 
2977  if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
2978  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
2979  if ((bug = switch_channel_get_private(other_channel, file))) {
2980  if (switch_true(switch_channel_get_variable(other_channel, "RECORD_TOGGLE_ON_REPEAT"))) {
2981  rstatus = switch_ivr_stop_record_session(other_session, file);
2982  } else {
2983  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(other_session), SWITCH_LOG_WARNING, "Already recording [%s]\n", file);
2984  }
2985  exist = 1;
2986  }
2987  switch_core_session_rwunlock(other_session);
2988  }
2989 
2990  if (exist) {
2991  return rstatus;
2992  }
2993  }
2994 
2995  if ((status = record_helper_create(&rh, session)) != SWITCH_STATUS_SUCCESS) {
2996  return status;
2997  }
2998 
2999  if (fh) {
3000  switch_file_handle_t *newfh;
3001 
3002  if ((status = switch_core_file_handle_dup(fh, &newfh, rh->helper_pool)) != SWITCH_STATUS_SUCCESS) {
3003  switch_goto_status(status, err);
3004  }
3005 
3006  fh = newfh;
3007  } else {
3008  if (!(fh = switch_core_alloc(rh->helper_pool, sizeof(*fh)))) {
3010  }
3011  }
3012 
3013  if (recording_var_true(channel, vars, "RECORD_WRITE_ONLY")) {
3014  flags &= ~SMBF_READ_STREAM;
3015  flags |= SMBF_WRITE_STREAM;
3016  }
3017 
3018  if (recording_var_true(channel, vars, "RECORD_READ_ONLY")) {
3019  flags &= ~SMBF_WRITE_STREAM;
3020  flags |= SMBF_READ_STREAM;
3021  }
3022 
3023  if (channels == 1) { /* if leg is already stereo this feature is not available */
3024  if (recording_var_true(channel, vars, "RECORD_STEREO")) {
3025  flags |= SMBF_STEREO;
3026  flags &= ~SMBF_STEREO_SWAP;
3027  channels = 2;
3028  }
3029 
3030  if (recording_var_true(channel, vars, "RECORD_STEREO_SWAP")) {
3031  flags |= SMBF_STEREO;
3032  flags |= SMBF_STEREO_SWAP;
3033  channels = 2;
3034  }
3035  }
3036 
3037  if (recording_var_true(channel, vars, "RECORD_ANSWER_REQ")) {
3038  flags |= SMBF_ANSWER_REQ;
3039  }
3040 
3041  if (recording_var_true(channel, vars, "RECORD_BRIDGE_REQ")) {
3042  flags |= SMBF_BRIDGE_REQ;
3043  }
3044 
3045  if (recording_var_true(channel, vars, "RECORD_APPEND")) {
3046  file_flags |= SWITCH_FILE_WRITE_APPEND;
3047  }
3048 
3049  fh->samplerate = 0;
3050  if ((vval = get_recording_var(channel, vars, "record_sample_rate"))) {
3051  int tmp = 0;
3052 
3053  tmp = atoi(vval);
3054 
3055  if (switch_is_valid_rate(tmp)) {
3056  fh->samplerate = tmp;
3057  }
3058  }
3059 
3060  if (!fh->samplerate) {
3061  fh->samplerate = read_impl.actual_samples_per_second;
3062  }
3063 
3064  fh->channels = channels;
3065 
3066  if ((vval = get_recording_var(channel, vars, "enable_file_write_buffering"))) {
3067  int tmp = atoi(vval);
3068 
3069  if (tmp > 0) {
3070  fh->pre_buffer_datalen = tmp;
3071  } else if (switch_true(vval)) {
3073  }
3074 
3075  } else {
3077  }
3078 
3079  if (!switch_is_file_path(file)) {
3080  char *tfile = NULL;
3081  char *e;
3082  const char *prefix;
3083 
3084  prefix = get_recording_var(channel, vars, "sound_prefix");
3085 
3086  if (!prefix) {
3087  prefix = SWITCH_GLOBAL_dirs.base_dir;
3088  }
3089 
3090  if (*file == '[') {
3091  tfile = switch_core_strdup(rh->helper_pool, file);
3092  if ((e = switch_find_end_paren(tfile, '[', ']'))) {
3093  *e = '\0';
3094  file = e + 1;
3095  } else {
3096  tfile = NULL;
3097  }
3098  } else {
3099  file_path = switch_core_sprintf(rh->helper_pool, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, file);
3100  }
3101 
3102  file = switch_core_sprintf(rh->helper_pool, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
3103  } else {
3104  file_path = switch_core_strdup(rh->helper_pool, file);
3105  }
3106 
3107  if (file_path && !strstr(file_path, SWITCH_URL_SEPARATOR)) {
3108  char *p;
3109  char *path = switch_core_strdup(rh->helper_pool, file_path);
3110 
3111  if ((p = strrchr(path, *SWITCH_PATH_SEPARATOR))) {
3112  *p = '\0';
3113 
3114  if (*path == '{') {
3115  path = switch_find_end_paren(path, '{', '}') + 1;
3116  }
3117  if ((vval = get_recording_var(channel, vars, "RECORD_DIR_PERMS"))) {
3118  fileperms = strtol(vval, 0, 16);
3119  }
3120 
3121 
3123  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error creating %s\n", path);
3124  set_completion_cause(rh, "uri-failure");
3126  }
3127 
3128  } else {
3129  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error finding the folder path section in '%s'\n", path);
3130  path = NULL;
3131  }
3132  }
3133 
3134  if ((ext = strrchr(file, '.'))) {
3135  ext++;
3136 
3137  if (switch_channel_test_flag(channel, CF_VIDEO)) {
3138  file_flags |= SWITCH_FILE_FLAG_VIDEO;
3139  }
3140 
3141  if (switch_core_file_open(fh, file, channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
3142  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", file);
3143  if (hangup_on_error) {
3146  }
3147  set_completion_cause(rh, "uri-failure");
3149  }
3150 
3151  if (fh->params) {
3152  if ((p = switch_event_get_header(fh->params,"record_write_only")) && switch_true(p)) {
3153  flags &= ~SMBF_READ_STREAM;
3154  flags |= SMBF_WRITE_STREAM;
3155  }
3156 
3157 
3158  if ((p = switch_event_get_header(fh->params, "record_read_only")) && switch_true(p)) {
3159  flags &= ~SMBF_WRITE_STREAM;
3160  flags |= SMBF_READ_STREAM;
3161  }
3162  }
3163 
3165  //switch_core_media_set_video_file(session, fh, SWITCH_RW_READ);
3166  //switch_channel_set_flag_recursive(session->channel, CF_VIDEO_DECODED_READ);
3167 
3168  if (recording_var_true(channel, vars, "record_concat_video")) {
3169  flags |= SMBF_READ_VIDEO_STREAM;
3170  flags |= SMBF_WRITE_VIDEO_STREAM;
3171  } else if (recording_var_true(channel, vars, "record_bleg_video")) {
3172  flags |= SMBF_WRITE_VIDEO_STREAM;
3173  } else {
3174  flags |= SMBF_READ_VIDEO_STREAM;
3175  }
3176  } else {
3177  flags &= ~SMBF_READ_VIDEO_PING;
3178  flags &= ~SMBF_READ_VIDEO_STREAM;
3179  flags &= ~SMBF_WRITE_VIDEO_STREAM;
3180  }
3181 
3182  } else {
3183  int tflags = 0;
3184 
3185  ext = read_impl.iananame;
3186 
3187  in_file = switch_core_sprintf(rh->helper_pool, "%s-in.%s", file, ext);
3188  out_file = switch_core_sprintf(rh->helper_pool, "%s-out.%s", file, ext);
3190  channels = 1;
3193 
3194  if (switch_core_file_open(&rh->in_fh, in_file, channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
3195  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", in_file);
3196  if (hangup_on_error) {
3199  }
3200  set_completion_cause(rh, "uri-failure");
3202  }
3203 
3204  if (switch_core_file_open(&rh->out_fh, out_file, channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
3205  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", out_file);
3207  if (hangup_on_error) {
3210  }
3211  set_completion_cause(rh, "uri-failure");
3213  }
3214 
3215  rh->native = 1;
3216  fh = NULL;
3217 
3218  if ((flags & SMBF_WRITE_STREAM)) {
3219  tflags |= SMBF_TAP_NATIVE_WRITE;
3220  }
3221 
3222  if ((flags & SMBF_READ_STREAM)) {
3223  tflags |= SMBF_TAP_NATIVE_READ;
3224  }
3225 
3226  flags = tflags;
3227  }
3228 
3229  if ((p = get_recording_var(channel, vars, "RECORD_TITLE"))) {
3230  vval = (const char *) switch_core_strdup(rh->helper_pool, p);
3232  switch_channel_set_variable(channel, "RECORD_TITLE", NULL);
3233  }
3234 
3235  if ((p = get_recording_var(channel, vars, "RECORD_COPYRIGHT"))) {
3236  vval = (const char *) switch_core_strdup(rh->helper_pool, p);
3238  switch_channel_set_variable(channel, "RECORD_COPYRIGHT", NULL);
3239  }
3240 
3241  if ((p = get_recording_var(channel, vars, "RECORD_SOFTWARE"))) {
3242  vval = (const char *) switch_core_strdup(rh->helper_pool, p);
3244  switch_channel_set_variable(channel, "RECORD_SOFTWARE", NULL);
3245  }
3246 
3247  if ((p = get_recording_var(channel, vars, "RECORD_ARTIST"))) {
3248  vval = (const char *) switch_core_strdup(rh->helper_pool, p);
3250  switch_channel_set_variable(channel, "RECORD_ARTIST", NULL);
3251  }
3252 
3253  if ((p = get_recording_var(channel, vars, "RECORD_COMMENT"))) {
3254  vval = (const char *) switch_core_strdup(rh->helper_pool, p);
3256  switch_channel_set_variable(channel, "RECORD_COMMENT", NULL);
3257  }
3258 
3259  if ((p = get_recording_var(channel, vars, "RECORD_DATE"))) {
3260  vval = (const char *) switch_core_strdup(rh->helper_pool, p);
3262  switch_channel_set_variable(channel, "RECORD_DATE", NULL);
3263  }
3264 
3265  if (limit) {
3266  to = switch_epoch_time_now(NULL) + limit;
3267  }
3268 
3269  rh->fh = fh;
3271  rh->packet_len = read_impl.decoded_bytes_per_packet;
3272 
3273  if (file_flags & SWITCH_FILE_WRITE_APPEND) {
3274  rh->min_sec = 3;
3275  }
3276 
3277  if ((p = get_recording_var(channel, vars, "RECORD_MIN_SEC"))) {
3278  int tmp = atoi(p);
3279  if (tmp >= 0) {
3280  rh->min_sec = tmp;
3281  }
3282  }
3283 
3284  if ((p = get_recording_var(channel, vars, "RECORD_INITIAL_TIMEOUT_MS"))) {
3285  int tmp = atoi(p);
3286  if (tmp >= 0) {
3287  rh->initial_timeout_ms = tmp;
3288  rh->silence_threshold = 200;
3289  }
3290  }
3291 
3292  if ((p = get_recording_var(channel, vars, "RECORD_FINAL_TIMEOUT_MS"))) {
3293  int tmp = atoi(p);
3294  if (tmp >= 0) {
3295  rh->final_timeout_ms = tmp;
3296  rh->silence_threshold = 200;
3297  }
3298  }
3299 
3300  if ((p = get_recording_var(channel, vars, "RECORD_SILENCE_THRESHOLD"))) {
3301  int tmp = atoi(p);
3302  if (tmp >= 0) {
3303  rh->silence_threshold = tmp;
3304  }
3305  }
3306 
3307  if (vars) {
3308  switch_event_dup(&rh->variables, vars);
3309  }
3310 
3312 
3313  if ((status = switch_core_media_bug_add(session, "session_record", file,
3314  record_callback, rh, to, flags, &bug)) != SWITCH_STATUS_SUCCESS) {
3315  if (switch_channel_ready(channel)) {
3316  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error adding media bug for file %s\n", file);
3317  } else {
3318  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Error adding media bug for file %s\n", file);
3319  }
3320  switch_goto_status(status, err);
3321  }
3322 
3323  if ((p = get_recording_var(channel, vars, "RECORD_PRE_BUFFER_FRAMES"))) {
3324  int tmp = atoi(p);
3325 
3326  if (tmp > 0) {
3328  }
3329  } else {
3331  }
3332 
3333  switch_channel_set_private(channel, file, bug);
3334 
3335  if (switch_channel_test_flag(channel, CF_VIDEO)) {
3336  switch_core_session_message_t msg = { 0 };
3337 
3338  msg.from = __FILE__;
3340 
3341  switch_core_session_receive_message(session, &msg);
3342  }
3343 
3344  return SWITCH_STATUS_SUCCESS;
3345 
3346 err:
3347  if (!zstr(rh->completion_cause)) {
3348  switch_channel_set_variable_printf(channel, "record_completion_cause", "%s", rh->completion_cause);
3349  }
3350  record_helper_destroy(&rh, session);
3351 
3352  return status;
3353 }
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it&#39;s state machine to end.
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
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:796
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:1963
static void set_completion_cause(struct record_helper *rh, const char *completion_cause)
switch_status_t switch_ivr_stop_record_session(switch_core_session_t *session, const char *file)
Stop Recording a session.
switch_memory_pool_t * helper_pool
cJSON *const to
switch_bool_t
Definition: switch_types.h:437
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
#define SWITCH_URL_SEPARATOR
Definition: switch_types.h:126
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.
static switch_status_t record_helper_destroy(struct record_helper **rh, switch_core_session_t *session)
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.
#define switch_channel_ready(_channel)
switch_status_t switch_event_dup(switch_event_t **event, switch_event_t *todup)
Duplicate an event.
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.
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_file_handle_dup(switch_file_handle_t *oldfh, switch_file_handle_t **newfh, switch_memory_pool_t *pool)
Duplicates a file handle using another pool.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:179
#define zstr(x)
Definition: switch_utils.h:314
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:124
static switch_status_t record_helper_create(struct record_helper **rh, switch_core_session_t *session)
const char * completion_cause
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
#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:1028
int32_t switch_fileperms_t
Definition: switch_apr.h:687
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
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:82
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
#define SWITCH_DEFAULT_DIR_PERMS
Definition: switch_types.h:120
static int recording_var_true(switch_channel_t *channel, switch_event_t *vars, const char *name)
switch_status_t
Common return values.
static const char * get_recording_var(switch_channel_t *channel, switch_event_t *vars, const char *name)
const char *const const char *const path
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:287
switch_event_t * variables
switch_status_t switch_dir_make_recursive(const char *path, switch_fileperms_t perm, switch_memory_pool_t *pool)
Definition: switch_apr.c:551
static switch_bool_t switch_is_file_path(const char *file)
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
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:322
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:378
uint32_t switch_media_bug_flag_t
switch_file_handle_t out_fh
switch_file_handle_t * fh
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)
#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:236
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_ivr_resume_detect_speech()

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 5257 of file switch_ivr_async.c.

References speech_thread_handle::ah, switch_channel_audio_sync, 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 CoreSession::detectSpeech(), speech_thread(), and switch_ivr_detect_speech().

5258 {
5261 
5262  if (sth) {
5263  switch_channel_audio_sync(channel);
5264  switch_core_asr_resume(sth->ah);
5265  return SWITCH_STATUS_SUCCESS;
5266  }
5267  return SWITCH_STATUS_FALSE;
5268 }
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:233
_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_audio_sync(_c)
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.

◆ switch_ivr_schedule_broadcast()

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 5635 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.

5636 {
5637  struct broadcast_helper *helper;
5638  size_t len = sizeof(*helper) + strlen(path) + 1;
5639  char *cur = NULL;
5640 
5641  switch_zmalloc(cur, len);
5642  helper = (struct broadcast_helper *) cur;
5643 
5644  cur += sizeof(*helper);
5645  switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
5646  helper->flags = flags;
5647 
5648  switch_copy_string(cur, path, len - sizeof(*helper));
5649  helper->path = cur;
5650 
5651  return switch_scheduler_add_task(runtime, sch_broadcast_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
5652 }
#define __SWITCH_FUNC__
switch_media_flag_t flags
pack cur
struct switch_runtime runtime
Definition: switch_core.c:86
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)
const char *const const char *const path

◆ switch_ivr_schedule_hangup()

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 5538 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.

5539 {
5540  struct hangup_helper *helper;
5541  size_t len = sizeof(*helper);
5542 
5543  switch_zmalloc(helper, len);
5544 
5545  switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
5546  helper->cause = cause;
5547  helper->bleg = bleg;
5548 
5549  return switch_scheduler_add_task(runtime, sch_hangup_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
5550 }
#define __SWITCH_FUNC__
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1]
switch_bool_t bleg
struct switch_runtime runtime
Definition: switch_core.c:86
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)

◆ switch_ivr_schedule_transfer()

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 5575 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.

5576 {
5577  struct transfer_helper *helper;
5578  size_t len = sizeof(*helper);
5579  char *cur = NULL;
5580 
5581  if (extension) {
5582  len += strlen(extension) + 1;
5583  }
5584 
5585  if (dialplan) {
5586  len += strlen(dialplan) + 1;
5587  }
5588 
5589  if (context) {
5590  len += strlen(context) + 1;
5591  }
5592 
5593  switch_zmalloc(cur, len);
5594  helper = (struct transfer_helper *) cur;
5595 
5596  switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
5597 
5598  cur += sizeof(*helper);
5599 
5600  if (extension) {
5601  switch_copy_string(cur, extension, strlen(extension) + 1);
5602  helper->extension = cur;
5603  cur += strlen(helper->extension) + 1;
5604  }
5605 
5606  if (dialplan) {
5607  switch_copy_string(cur, dialplan, strlen(dialplan) + 1);
5608  helper->dialplan = cur;
5609  cur += strlen(helper->dialplan) + 1;
5610  }
5611 
5612  if (context) {
5613  switch_copy_string(cur, context, strlen(context) + 1);
5614  helper->context = cur;
5615  }
5616 
5617  return switch_scheduler_add_task(runtime, sch_transfer_callback, (char *) __SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
5618 }
#define __SWITCH_FUNC__
pack cur
struct switch_runtime runtime
Definition: switch_core.c:86
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_ivr_session_audio()

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

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

3728 {
3730  switch_media_bug_t *bug;
3731  switch_status_t status;
3733  switch_codec_implementation_t read_impl = { 0 };
3734  int existing = 0, c_read = 0, c_write = 0, flags = SMBF_NO_PAUSE;
3735 
3737  return SWITCH_STATUS_FALSE;
3738  }
3739 
3740  switch_core_session_get_read_impl(session, &read_impl);
3741 
3742 
3743  if ((bug = switch_channel_get_private(channel, "__audio"))) {
3745  existing = 1;
3746  } else {
3747  if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
3748  return SWITCH_STATUS_MEMERR;
3749  }
3750 
3751  pvt->session = session;
3752  }
3753 
3754 
3755  if (!strcasecmp(direction, "write")) {
3756  flags = SMBF_WRITE_REPLACE;
3757  c_write = 1;
3758  } else if (!strcasecmp(direction, "read")) {
3759  flags = SMBF_READ_REPLACE;
3760  c_read = 1;
3761  } else if (!strcasecmp(direction, "both")) {
3763  c_read = c_write = 1;
3764  }
3765 
3766 
3767  if (!strcasecmp(cmd, "mute")) {
3768  if (c_read) {
3769  pvt->read_mute = level;
3770  pvt->read_level = 0;
3771  }
3772  if (c_write) {
3773  pvt->write_mute = level;
3774  pvt->write_level = 0;
3775  }
3776  } else if (!strcasecmp(cmd, "level")) {
3777  if (level < 5 && level > -5) {
3778  if (c_read) {
3779  pvt->read_level = level;
3780  }
3781  if (c_write) {
3782  pvt->write_level = level;
3783  }
3784  }
3785  }
3786 
3787  if (existing) {
3788  switch_core_media_bug_set_flag(bug, flags);
3789  } else {
3790  if ((status = switch_core_media_bug_add(session, "audio", cmd,
3791  session_audio_callback, pvt, 0, flags, &bug)) != SWITCH_STATUS_SUCCESS) {
3792  return status;
3793  }
3794 
3795  switch_channel_set_private(channel, "__audio", bug);
3796  }
3797 
3798 
3799  return SWITCH_STATUS_SUCCESS;
3800 }
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&#39;s pool.
Definition: switch_core.h:696
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_ivr_session_echo()

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 703 of file switch_ivr_async.c.

References arg_recursion_check_start, switch_input_args_t::buf, switch_input_args_t::buflen, CF_BREAK, CF_TEXT_ECHO, CF_VIDEO_DECODED_READ, CF_VIDEO_ECHO, switch_dtmf_t::digit, switch_input_args_t::input_callback, switch_channel_clear_flag(), switch_channel_clear_flag_recursive(), switch_channel_dequeue_dtmf(), switch_channel_has_dtmf(), switch_channel_pre_answer, switch_channel_ready, switch_channel_set_flag, switch_channel_set_flag_recursive(), switch_channel_test_flag(), switch_channel_var_true(), 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, and SWITCH_TRUE.

704 {
705  switch_status_t status;
706  switch_frame_t *read_frame;
708 
710  return SWITCH_STATUS_FALSE;
711  }
712 
714 
715  if (switch_channel_var_true(channel, "echo_decode_video")) {
717  }
718 
719  if (switch_channel_var_true(channel, "echo_decode_audio")) {
721  }
722 
725 
726  while (switch_channel_ready(channel)) {
727  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
728  if (!SWITCH_READ_ACCEPTABLE(status)) {
729  break;
730  }
731 
733 
734  if (args && (args->input_callback || args->buf || args->buflen)) {
735  switch_dtmf_t dtmf = {0};
736 
737  /*
738  dtmf handler function you can hook up to be executed when a digit is dialed during playback
739  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
740  */
741  if (switch_channel_has_dtmf(channel)) {
742  if (!args->input_callback && !args->buf) {
743  break;
744  }
745  switch_channel_dequeue_dtmf(channel, &dtmf);
746  if (args->input_callback) {
747  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
748  } else {
749  *((char *) args->buf) = dtmf.digit;
750  status = SWITCH_STATUS_BREAK;
751  }
752  }
753 
754  if (args->input_callback) {
755  switch_event_t *event = NULL;
756 
758  status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
759  switch_event_destroy(&event);
760  }
761  }
762 
763  if (status != SWITCH_STATUS_SUCCESS) {
764  break;
765  }
766  }
767 
768  switch_core_session_write_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
769 
770  if (switch_channel_test_flag(channel, CF_BREAK)) {
772  break;
773  }
774  }
775 
776  if (switch_channel_var_true(channel, "echo_decode_video")) {
778  }
779 
783 
784  return SWITCH_STATUS_SUCCESS;
785 }
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
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:913
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.
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:54
#define arg_recursion_check_start(_args)
void switch_core_session_video_reset(switch_core_session_t *session)
static int switch_channel_var_true(switch_channel_t *channel, const char *variable)
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_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
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)

◆ switch_ivr_session_transfer()

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_ivr_set_param_detect_speech()

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

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

Referenced by CoreSession::detectSpeech().

5287 {
5290 
5291  if (sth && sth->ah && name && val) {
5292  switch_core_asr_text_param(sth->ah, (char *) name, val);
5293  status = SWITCH_STATUS_SUCCESS;
5294  }
5295 
5296  return status;
5297 }
switch_asr_handle_t * ah
#define SWITCH_SPEECH_KEY
Definition: switch_types.h:233
_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.
const char *const name
Definition: switch_cJSON.h:250
void switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val)
Set a text parameter on an asr handle.

◆ switch_ivr_set_xml_chan_vars()

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

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

2839 {
2840 
2842 
2843  if (!hi)
2844  return off;
2845 
2846  for (; hi; hi = hi->next) {
2847  if (hi->idx) {
2848  int i;
2849 
2850  for (i = 0; i < hi->idx; i++) {
2851  off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->array[i], off);
2852  }
2853  } else {
2854  off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->value, off);
2855  }
2856  }
2858 
2859  return off;
2860 }
static int switch_ivr_set_xml_chan_var(switch_xml_t xml, const char *var, const char *val, int off)
Definition: switch_ivr.c:2814
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.

◆ switch_ivr_set_xml_profile_data()

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

Definition at line 2599 of file switch_ivr.c.

References switch_caller_profile::ani, switch_caller_profile::aniii, switch_caller_profile::callee_id_name, switch_caller_profile::callee_id_number, switch_caller_profile::caller_id_name, switch_caller_profile::caller_id_number, switch_caller_profile::chan_name, switch_caller_profile::context, switch_caller_profile::destination_number, switch_caller_profile::dialplan, switch_caller_profile::network_addr, profile_node_s::next, switch_caller_profile::rdnis, switch_caller_profile::soft, switch_caller_profile::source, switch_xml_add_child_d(), switch_xml_set_txt_d(), switch_caller_profile::transfer_source, switch_caller_profile::username, switch_caller_profile::uuid, profile_node_s::val, and profile_node_s::var.

Referenced by switch_ivr_generate_xml_cdr().

2600 {
2601  switch_xml_t param;
2602 
2603  if (!(param = switch_xml_add_child_d(xml, "username", off++))) {
2604  return -1;
2605  }
2606  switch_xml_set_txt_d(param, caller_profile->username);
2607 
2608  if (!(param = switch_xml_add_child_d(xml, "dialplan", off++))) {
2609  return -1;
2610  }
2611  switch_xml_set_txt_d(param, caller_profile->dialplan);
2612 
2613  if (!(param = switch_xml_add_child_d(xml, "caller_id_name", off++))) {
2614  return -1;
2615  }
2616  switch_xml_set_txt_d(param, caller_profile->caller_id_name);
2617 
2618  if (!(param = switch_xml_add_child_d(xml, "caller_id_number", off++))) {
2619  return -1;
2620  }
2621  switch_xml_set_txt_d(param, caller_profile->caller_id_number);
2622 
2623  if (!(param = switch_xml_add_child_d(xml, "callee_id_name", off++))) {
2624  return -1;
2625  }
2626  switch_xml_set_txt_d(param, caller_profile->callee_id_name);
2627 
2628  if (!(param = switch_xml_add_child_d(xml, "callee_id_number", off++))) {
2629  return -1;
2630  }
2631  switch_xml_set_txt_d(param, caller_profile->callee_id_number);
2632 
2633  if (!(param = switch_xml_add_child_d(xml, "ani", off++))) {
2634  return -1;
2635  }
2636  switch_xml_set_txt_d(param, caller_profile->ani);
2637 
2638  if (!(param = switch_xml_add_child_d(xml, "aniii", off++))) {
2639  return -1;
2640  }
2641  switch_xml_set_txt_d(param, caller_profile->aniii);
2642 
2643 
2644  if (!(param = switch_xml_add_child_d(xml, "network_addr", off++))) {
2645  return -1;
2646  }
2647  switch_xml_set_txt_d(param, caller_profile->network_addr);
2648 
2649  if (!(param = switch_xml_add_child_d(xml, "rdnis", off++))) {
2650  return -1;
2651  }
2652  switch_xml_set_txt_d(param, caller_profile->rdnis);
2653 
2654  if (!(param = switch_xml_add_child_d(xml, "destination_number", off++))) {
2655  return -1;
2656  }
2657  switch_xml_set_txt_d(param, caller_profile->destination_number);
2658 
2659  if (!(param = switch_xml_add_child_d(xml, "uuid", off++))) {
2660  return -1;
2661  }
2662  switch_xml_set_txt_d(param, caller_profile->uuid);
2663 
2664  if (!(param = switch_xml_add_child_d(xml, "source", off++))) {
2665  return -1;
2666  }
2667  switch_xml_set_txt_d(param, caller_profile->source);
2668 
2669  if (caller_profile->transfer_source) {
2670  if (!(param = switch_xml_add_child_d(xml, "transfer_source", off++))) {
2671  return -1;
2672  }
2673  switch_xml_set_txt_d(param, caller_profile->transfer_source);
2674  }
2675 
2676  if (!(param = switch_xml_add_child_d(xml, "context", off++))) {
2677  return -1;
2678  }
2679  switch_xml_set_txt_d(param, caller_profile->context);
2680 
2681  if (!(param = switch_xml_add_child_d(xml, "chan_name", off++))) {
2682  return -1;
2683  }
2684  switch_xml_set_txt_d(param, caller_profile->chan_name);
2685 
2686 
2687  if (caller_profile->soft) {
2688  profile_node_t *pn;
2689 
2690  for (pn = caller_profile->soft; pn; pn = pn->next) {
2691 
2692  if (!(param = switch_xml_add_child_d(xml, pn->var, off++))) {
2693  return -1;
2694  }
2695  switch_xml_set_txt_d(param, pn->val);
2696  }
2697 
2698  }
2699 
2700 
2701  return off;
2702 }
switch_xml_t switch_xml_add_child_d(_In_ switch_xml_t xml, _In_z_ const char *name, _In_ switch_size_t off)
wrapper for switch_xml_add_child() that strdup()s name
const char * network_addr
Definition: switch_caller.h:93
A representation of an XML tree.
Definition: switch_xml.h:79
const char * dialplan
Definition: switch_caller.h:77
switch_xml_t switch_xml_set_txt_d(switch_xml_t xml, const char *txt)
wrapper for switch_xml_set_txt() that strdup()s txt \ sets the character content for the given tag an...
Definition: switch_xml.c:3005
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
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_ivr_signal_bridge()

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 1532 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_enterprise_orig_and_bridge(), switch_ivr_multi_threaded_bridge(), switch_ivr_nomedia(), and switch_ivr_orig_and_bridge().

1533 {
1534  switch_channel_t *caller_channel = switch_core_session_get_channel(session);
1535  switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
1536  switch_event_t *event;
1537 
1538  if (switch_channel_down_nosig(peer_channel)) {
1539  switch_channel_hangup(caller_channel, switch_channel_get_cause(peer_channel));
1540  return SWITCH_STATUS_FALSE;
1541  }
1542 
1543  if (!switch_channel_up_nosig(caller_channel)) {
1545  return SWITCH_STATUS_FALSE;
1546  }
1547 
1548  check_bridge_export(caller_channel, peer_channel);
1549 
1552 
1555  switch_channel_set_variable(peer_channel, "call_uuid", switch_core_session_get_uuid(session));
1556 
1559 
1560  switch_channel_clear_state_handler(caller_channel, NULL);
1561  switch_channel_clear_state_handler(peer_channel, NULL);
1562 
1565 
1566  switch_channel_set_variable(caller_channel, "signal_bridge", "true");
1567  switch_channel_set_variable(peer_channel, "signal_bridge", "true");
1568 
1569  /* fire events that will change the data table from "show channels" */
1571  switch_channel_event_set_data(caller_channel, event);
1572  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", "signal_bridge");
1573  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(peer_session));
1574  switch_event_fire(&event);
1575  }
1576 
1578  switch_channel_event_set_data(peer_channel, event);
1579  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", "signal_bridge");
1581  switch_event_fire(&event);
1582  }
1583 
1584  switch_channel_set_state_flag(caller_channel, CF_RESET);
1585  switch_channel_set_state_flag(peer_channel, CF_RESET);
1586 
1587  switch_channel_set_state(caller_channel, CS_HIBERNATE);
1588  switch_channel_set_state(peer_channel, CS_HIBERNATE);
1589 
1590 #if 0
1591  if (switch_channel_test_flag(caller_channel, CF_BRIDGED)) {
1592  switch_channel_set_flag(caller_channel, CF_TRANSFER);
1593  switch_channel_set_flag(peer_channel, CF_TRANSFER);
1594  }
1595 #endif
1596 
1597  switch_ivr_bridge_display(session, peer_session);
1598 
1599  return SWITCH_STATUS_SUCCESS;
1600 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:202
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it&#39;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:384
#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_ivr_sleep()

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_input_args_t::buf, switch_frame::buflen, switch_input_args_t::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_input_args_t::dmachine, switch_input_args_t::input_callback, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, switch_input_args_t::read_frame_callback, 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, switch_zmalloc, and switch_input_args_t::user_data.

Referenced by audio_bridge_thread(), 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_collect_input(), 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 (read_frame && args && (args->read_frame_callback)) {
307  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
308  break;
309  }
310  }
311 
312  if (sval && write_frame.datalen) {
313  switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, imp.number_of_channels, sval);
314  switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
315  } else {
316  switch_core_session_write_frame(session, &cng_frame, SWITCH_IO_FLAG_NONE, 0);
317  }
318  }
319 
320 
321  end:
322 
324 
326 
327  if (write_frame.codec) {
329  }
330 
331  switch_safe_free(abuf);
332 
333  return status;
334 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
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:590
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:913
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:56
#define SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE
Definition: switch_types.h:131
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:70
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
#define switch_channel_audio_sync(_c)
uint32_t datalen
Definition: switch_frame.h:68
#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:885
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:54
#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:1693
switch_read_frame_callback_function_t read_frame_callback
switch_status_t
Common return values.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:287
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:72
#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)
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_ivr_speak_text()

switch_status_t switch_ivr_speak_text ( switch_core_session_t session,
const char *  tts_name,
const char *  voice_name,
const 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 3026 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().

3028 {
3030  uint32_t rate = 0;
3031  int interval = 0;
3032  uint32_t channels;
3033  switch_frame_t write_frame = { 0 };
3034  switch_timer_t ltimer, *timer;
3035  switch_codec_t lcodec, *codec;
3037  char *codec_name;
3039  switch_speech_handle_t lsh, *sh;
3041  const char *timer_name, *var;
3042  cached_speech_handle_t *cache_obj = NULL;
3043  int need_create = 1, need_alloc = 1;
3044  switch_codec_implementation_t read_impl = { 0 };
3045  switch_core_session_get_read_impl(session, &read_impl);
3046 
3048  return SWITCH_STATUS_FALSE;
3049  }
3050 
3052 
3053  sh = &lsh;
3054  codec = &lcodec;
3055  timer = &ltimer;
3056 
3059  need_create = 0;
3060  if (!strcasecmp(cache_obj->tts_name, tts_name)) {
3061  need_alloc = 0;
3062  } else {
3064  }
3065  }
3066 
3067  if (!cache_obj) {
3068  cache_obj = (cached_speech_handle_t *) switch_core_session_alloc(session, sizeof(*cache_obj));
3069  }
3070  if (need_alloc) {
3071  switch_copy_string(cache_obj->tts_name, tts_name, sizeof(cache_obj->tts_name));
3072  switch_copy_string(cache_obj->voice_name, voice_name, sizeof(cache_obj->voice_name));
3074  }
3075  sh = &cache_obj->sh;
3076  codec = &cache_obj->codec;
3077  timer = &cache_obj->timer;
3078  }
3079 
3080  timer_name = switch_channel_get_variable(channel, "timer_name");
3081 
3083 
3084  rate = read_impl.actual_samples_per_second;
3085  interval = read_impl.microseconds_per_packet / 1000;
3086  channels = read_impl.number_of_channels;
3087 
3088  if (need_create) {
3089  memset(sh, 0, sizeof(*sh));
3090  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) {
3091  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid TTS module %s[%s]!\n", tts_name, voice_name);
3095  return status;
3096  }
3097  } else if (cache_obj && strcasecmp(cache_obj->voice_name, voice_name)) {
3098  switch_copy_string(cache_obj->voice_name, voice_name, sizeof(cache_obj->voice_name));
3099  switch_core_speech_text_param_tts(sh, "voice", voice_name);
3100  }
3101 
3103  flags = 0;
3104  switch_core_speech_close(sh, &flags);
3106  return SWITCH_STATUS_FALSE;
3107  }
3108  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
3109 
3110  codec_name = "L16";
3111 
3112  if (need_create) {
3113  if (switch_core_codec_init(codec,
3114  codec_name,
3115  NULL,
3116  NULL, (int) rate, interval, channels, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
3117  pool) == SWITCH_STATUS_SUCCESS) {
3118  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
3119  } else {
3120  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed %s@%uhz 1 channel %dms\n", codec_name,
3121  rate, interval);
3122  flags = 0;
3123  switch_core_speech_close(sh, &flags);
3127  return SWITCH_STATUS_GENERR;
3128  }
3129  }
3130 
3131  write_frame.codec = codec;
3132 
3133  if (timer_name) {
3134  if (need_create) {
3135  if (switch_core_timer_init(timer, timer_name, interval, (int) sh->samples, pool) != SWITCH_STATUS_SUCCESS) {
3136  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n");
3137  switch_core_codec_destroy(write_frame.codec);
3138  flags = 0;
3139  switch_core_speech_close(sh, &flags);
3143  return SWITCH_STATUS_GENERR;
3144  }
3145  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", sh->samples * 2,
3146  interval);
3147  }
3148  switch_core_timer_sync(timer); // Sync timer
3149 
3150  /* start a thread to absorb incoming audio */
3151  switch_core_service_session(session);
3152 
3153  }
3154 
3155  status = switch_ivr_speak_text_handle(session, sh, write_frame.codec, timer_name ? timer : NULL, text, args);
3156  flags = 0;
3157 
3158  if (!cache_obj) {
3159  switch_core_speech_close(sh, &flags);
3161  }
3162 
3163  if (timer_name) {
3164  /* End the audio absorbing thread */
3166  if (!cache_obj) {
3168  }
3169  }
3170 
3173 
3174  return status;
3175 }
void switch_core_thread_session_end(_In_ switch_core_session_t *session)
Signal a thread using a thread session to terminate.
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
#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_codec_t * codec
Definition: switch_frame.h:56
#define SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME
Definition: switch_types.h:189
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:188
#define switch_channel_get_variable(_c, _v)
An abstraction of a data frame.
Definition: switch_frame.h:54
#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:1693
switch_speech_handle_t sh
#define switch_core_service_session(_s)
Definition: switch_core.h:1216
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&#39;s pool.
Definition: switch_core.h:696
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, const char *text, switch_input_args_t *args)
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.
struct fspr_pool_t switch_memory_pool_t
#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_ivr_speak_text_handle()

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,
const char *  text,
switch_input_args_t args 
)

Definition at line 2744 of file switch_ivr_play_say.c.

References arg_recursion_check_start, arg_recursion_check_stop, switch_input_args_t::buf, switch_frame::buflen, switch_input_args_t::buflen, CF_BREAK, CF_HOLD, switch_speech_handle::channels, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_dtmf_t::digit, switch_input_args_t::dmachine, switch_codec::implementation, switch_input_args_t::input_callback, memset(), switch_frame::rate, switch_speech_handle::rate, switch_input_args_t::read_frame_callback, switch_timer::samplecount, switch_frame::samples, switch_speech_handle::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_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_events(), switch_ivr_parse_all_messages(), 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_input_args_t::user_data.

Referenced by switch_ivr_speak_text().

2747 {
2749  short abuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
2750  switch_dtmf_t dtmf = { 0 };
2751  uint32_t len = 0;
2752  switch_size_t ilen = 0;
2753  switch_frame_t write_frame = { 0 };
2756  switch_size_t extra = 0;
2757  char *tmp = NULL;
2758  const char *star, *pound, *p;
2759  switch_size_t starlen, poundlen;
2760 
2761  if (!sh) {
2762  return SWITCH_STATUS_FALSE;
2763  }
2764 
2766  return SWITCH_STATUS_FALSE;
2767  }
2768 
2769  if (!switch_core_codec_ready(codec)) {
2770  return SWITCH_STATUS_FALSE;
2771  }
2772 
2774 
2775  write_frame.data = abuf;
2776  write_frame.buflen = sizeof(abuf);
2777 
2778  len = sh->samples * 2 * sh->channels;
2779 
2780  flags = 0;
2781 
2782  if (!(star = switch_channel_get_variable(channel, "star_replace"))) {
2783  star = "star";
2784  }
2785  if (!(pound = switch_channel_get_variable(channel, "pound_replace"))) {
2786  pound = "pound";
2787  }
2788  starlen = strlen(star);
2789  poundlen = strlen(pound);
2790 
2791 
2792  for (p = text; p && *p; p++) {
2793  if (*p == '*') {
2794  extra += starlen;
2795  } else if (*p == '#') {
2796  extra += poundlen;
2797  }
2798  }
2799 
2800  if (extra) {
2801  char *tp;
2802  switch_size_t mylen = strlen(text) + extra + 1;
2803  tmp = malloc(mylen);
2804  if (!tmp) {
2806  return SWITCH_STATUS_MEMERR;
2807  }
2808  memset(tmp, 0, mylen);
2809  tp = tmp;
2810  for (p = text; p && *p; p++) {
2811  if (*p == '*' ) {
2812  snprintf(tp + strlen(tp), sizeof(tp) - strlen(tp), "%s", star);
2813  tp += starlen;
2814  } else if (*p == '#') {
2815  snprintf(tp + strlen(tp), sizeof(tp) - strlen(tp), "%s", pound);
2816  tp += poundlen;
2817  } else {
2818  *tp++ = *p;
2819  }
2820  }
2821 
2822  text = tmp;
2823  }
2824 
2825  switch_core_speech_feed_tts(sh, text, &flags);
2826  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Speaking text: %s\n", text);
2827  switch_safe_free(tmp);
2828  text = NULL;
2829 
2830  write_frame.rate = sh->rate;
2831  memset(write_frame.data, 0, len);
2832  write_frame.datalen = len;
2833  write_frame.samples = len / 2;
2834  write_frame.codec = codec;
2835 
2836  switch_assert(codec->implementation != NULL);
2837 
2838  switch_channel_audio_sync(channel);
2839 
2840 
2841  for (;;) {
2842  switch_event_t *event;
2843 
2844  ilen = len;
2845 
2846  if (!switch_channel_ready(channel)) {
2847  status = SWITCH_STATUS_FALSE;
2848  break;
2849  }
2850 
2851  if (switch_channel_test_flag(channel, CF_BREAK)) {
2853  status = SWITCH_STATUS_BREAK;
2854  break;
2855  }
2856 
2857  switch_ivr_parse_all_events(session);
2858 
2859  if (args) {
2860  /* dtmf handler function you can hook up to be executed when a digit is dialed during playback
2861  * if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
2862  */
2863  if (switch_channel_has_dtmf(channel)) {
2864  if (!args->input_callback && !args->buf && !args->dmachine) {
2865  status = SWITCH_STATUS_BREAK;
2866  break;
2867  }
2868  if (args->buf && !strcasecmp(args->buf, "_break_")) {
2869  status = SWITCH_STATUS_BREAK;
2870  } else {
2871  switch_channel_dequeue_dtmf(channel, &dtmf);
2872 
2873  if (args->dmachine) {
2874  char ds[2] = {dtmf.digit, '\0'};
2875  if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) {
2876  break;
2877  }
2878  }
2879 
2880  if (args->input_callback) {
2881  status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
2882  } else if (args->buf) {
2883  *((char *) args->buf) = dtmf.digit;
2884  status = SWITCH_STATUS_BREAK;
2885  }
2886  }
2887  }
2888 
2889  if (args->input_callback) {
2891  switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
2892  if (ostatus != SWITCH_STATUS_SUCCESS) {
2893  status = ostatus;
2894  }
2895  switch_event_destroy(&event);
2896  }
2897  }
2898 
2899  if (status != SWITCH_STATUS_SUCCESS) {
2900  break;
2901  }
2902  }
2903 
2905  if (timer) {
2907  break;
2908  }
2909  } else {
2910  switch_frame_t *read_frame;
2911  switch_status_t tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2912 
2913  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
2915  switch_yield(10000);
2916  }
2917 
2918  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
2919  break;
2920  }
2921 
2922  if (args && args->dmachine) {
2923  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
2924  goto done;
2925  }
2926  }
2927 
2928  if (args && (args->read_frame_callback)) {
2929  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
2930  goto done;
2931  }
2932  }
2933  }
2934  continue;
2935  }
2936 
2937 
2939  status = switch_core_speech_read_tts(sh, abuf, &ilen, &flags);
2940 
2941  if (status != SWITCH_STATUS_SUCCESS) {
2942  if (status == SWITCH_STATUS_BREAK) {
2943  status = SWITCH_STATUS_SUCCESS;
2944  }
2945  break;
2946  }
2947 
2948  write_frame.datalen = (uint32_t) ilen;
2949  write_frame.samples = (uint32_t) (ilen / 2 / sh->channels);
2950  if (timer) {
2951  write_frame.timestamp = timer->samplecount;
2952  }
2954  break;
2955  }
2956 
2957  if (timer) {
2959  break;
2960  }
2961  } else { /* time off the channel (if you must) */
2962  switch_frame_t *read_frame;
2963  switch_status_t tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2964 
2965  while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
2967  switch_yield(10000);
2968  }
2969 
2970  if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
2971  break;
2972  }
2973 
2974  if (args && args->dmachine) {
2975  if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) {
2976  goto done;
2977  }
2978  }
2979 
2980  if (args && (args->read_frame_callback)) {
2981  if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) {
2982  goto done;
2983  }
2984  }
2985  }
2986  }
2987 
2988  done:
2989 
2990  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done speaking text\n");
2991  flags = 0;
2993 
2995  return status;
2996 }
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.
switch_status_t switch_core_speech_feed_tts(switch_speech_handle_t *sh, const char *text, switch_speech_flag_t *flags)
Feed text to 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:590
uint32_t timestamp
Definition: switch_frame.h:80
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:913
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:56
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:70
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
#define switch_channel_audio_sync(_c)
uint32_t datalen
Definition: switch_frame.h:68
uint32_t rate
Definition: switch_frame.h:74
#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:885
switch_input_callback_function_t input_callback
An abstraction of a data frame.
Definition: switch_frame.h:54
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:72
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:693
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)
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:847

◆ switch_ivr_stop_detect_speech()

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 5229 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 CoreSession::detectSpeech(), 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().

5230 {
5232  struct speech_thread_handle *sth;
5233 
5234  switch_assert(channel != NULL);
5235  if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
5237  switch_core_event_hook_remove_recv_dtmf(session, speech_on_dtmf);
5238  switch_core_media_bug_remove(session, &sth->bug);
5239  return SWITCH_STATUS_SUCCESS;
5240  }
5241 
5242  return SWITCH_STATUS_FALSE;
5243 }
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:233
_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_ivr_stop_displace_session()

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 987 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.

988 {
991 
992  if ((bug = switch_channel_get_private(channel, file))) {
993  switch_channel_set_private(channel, file, NULL);
994  switch_core_media_bug_remove(session, &bug);
995  return SWITCH_STATUS_SUCCESS;
996  }
997 
998  return SWITCH_STATUS_FALSE;
999 }
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_ivr_stop_inband_dtmf_generate_session()

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 4075 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.

4076 {
4078  switch_media_bug_t *bug = switch_channel_get_private(channel, "dtmf_generate");
4079 
4080  if (bug) {
4081  switch_channel_set_private(channel, "dtmf_generate", NULL);
4082  switch_core_media_bug_remove(session, &bug);
4083  return SWITCH_STATUS_SUCCESS;
4084  }
4085 
4086  return SWITCH_STATUS_FALSE;
4087 
4088 }
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_ivr_stop_inband_dtmf_session()

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 3841 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.

3842 {
3845 
3846  if ((bug = switch_channel_get_private(channel, "dtmf"))) {
3847  switch_channel_set_private(channel, "dtmf", NULL);
3848  switch_core_media_bug_remove(session, &bug);
3849  return SWITCH_STATUS_SUCCESS;
3850  }
3851  return SWITCH_STATUS_FALSE;
3852 }
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_ivr_stop_record_session()

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 1920 of file switch_ivr_async.c.

References record_helper::bug, 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_ivr_record_session_event().

1921 {
1924 
1925  if (!strcasecmp(file, "all")) {
1927  } else if ((bug = switch_channel_get_private(channel, file))) {
1928  switch_core_media_bug_remove(session, &bug);
1929  return SWITCH_STATUS_SUCCESS;
1930  }
1931  return SWITCH_STATUS_FALSE;
1932 }
_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_ivr_stop_session_audio()

switch_status_t switch_ivr_stop_session_audio ( switch_core_session_t session)

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

3715 {
3718 
3719  if ((bug = switch_channel_get_private(channel, "__audio"))) {
3720  switch_channel_set_private(channel, "__audio", NULL);
3721  switch_core_media_bug_remove(session, &bug);
3722  return SWITCH_STATUS_SUCCESS;
3723  }
3724  return SWITCH_STATUS_FALSE;
3725 }
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_ivr_stop_tone_detect_session()

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 4307 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().

4308 {
4310  switch_tone_container_t *cont = switch_channel_get_private(channel, "_tone_detect_");
4311  int i = 0;
4312 
4313  if (cont) {
4314  switch_channel_set_private(channel, "_tone_detect_", NULL);
4315  for (i = 0; i < cont->index; i++) {
4316  cont->list[i].up = 0;
4317  }
4318  switch_core_media_bug_remove(session, &cont->bug);
4319  if (cont->detect_fax) {
4320  cont->detect_fax = 0;
4321  }
4322  return SWITCH_STATUS_SUCCESS;
4323  }
4324  return SWITCH_STATUS_FALSE;
4325 }
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_ivr_tone_detect_session()

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 4327 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_ivr_dmachine_binding::callback, 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_ivr_dmachine_binding::next, 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().

4331 {
4333  switch_status_t status;
4334  switch_tone_container_t *cont = switch_channel_get_private(channel, "_tone_detect_");
4335  char *p, *next;
4336  int i = 0, ok = 0, detect_fax = 0;
4337  switch_media_bug_flag_t bflags = 0;
4338  const char *var;
4339  switch_codec_implementation_t read_impl = { 0 };
4340  switch_core_session_get_read_impl(session, &read_impl);
4341 
4342 
4343  if (zstr(key)) {
4344  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Key Specified!\n");
4345  return SWITCH_STATUS_FALSE;
4346  }
4347 
4348  if (cont) {
4349  if (cont->index >= MAX_TONES) {
4350  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Max Tones Reached!\n");
4351  return SWITCH_STATUS_FALSE;
4352  }
4353 
4354  for (i = 0; i < cont->index; i++) {
4355  if (!zstr(cont->list[i].key) && !strcasecmp(key, cont->list[i].key)) {
4356  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Re-enabling %s\n", key);
4357  cont->list[i].up = 1;
4358  cont->list[i].hits = 0;
4359  cont->list[i].sleep = 0;
4360  cont->list[i].expires = 0;
4361  return SWITCH_STATUS_SUCCESS;
4362  }
4363  }
4364  }
4365 
4366  if (zstr(tone_spec)) {
4367  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Spec Specified!\n");
4368  return SWITCH_STATUS_FALSE;
4369  }
4370 
4371  if (!cont && !(cont = switch_core_session_alloc(session, sizeof(*cont)))) {
4372  return SWITCH_STATUS_MEMERR;
4373  }
4374 
4375  if ((var = switch_channel_get_variable(channel, "tone_detect_hits"))) {
4376  int tmp = atoi(var);
4377  if (tmp > 0) {
4378  hits = tmp;
4379  }
4380  }
4381 
4382  if (!hits) hits = 1;
4383 
4384  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);
4385 
4386  i = 0;
4387  p = (char *) tone_spec;
4388 
4389  do {
4390  teletone_process_t this;
4391  next = strchr(p, ',');
4392  while (*p == ' ')
4393  p++;
4394  if ((this = (teletone_process_t) atof(p))) {
4395  ok++;
4396  cont->list[cont->index].map.freqs[i++] = this;
4397  }
4398  if (!strncasecmp(p, "1100", 4)) {
4399  detect_fax = cont->index;
4400  }
4401 
4402  if (next) {
4403  p = next + 1;
4404  }
4405  } while (next);
4406  cont->list[cont->index].map.freqs[i++] = 0;
4407 
4408  if (!ok) {
4409  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid tone spec!\n");
4410  return SWITCH_STATUS_FALSE;
4411  }
4412 
4413  cont->detect_fax = detect_fax;
4414 
4415  cont->list[cont->index].key = switch_core_session_strdup(session, key);
4416 
4417  if (app) {
4418  cont->list[cont->index].app = switch_core_session_strdup(session, app);
4419  }
4420 
4421  if (data) {
4422  cont->list[cont->index].data = switch_core_session_strdup(session, data);
4423  }
4424 
4425  cont->list[cont->index].callback = callback;
4426  cont->list[cont->index].hits = 0;
4427  cont->list[cont->index].total_hits = hits;
4428  cont->list[cont->index].start_time = switch_micro_time_now();
4429 
4430  cont->list[cont->index].up = 1;
4431  memset(&cont->list[cont->index].mt, 0, sizeof(cont->list[cont->index].mt));
4432  cont->list[cont->index].mt.sample_rate = read_impl.actual_samples_per_second;
4433  teletone_multi_tone_init(&cont->list[cont->index].mt, &cont->list[cont->index].map);
4434  cont->session = session;
4435 
4437  return SWITCH_STATUS_FALSE;
4438  }
4439 
4440  cont->list[cont->index].default_sleep = 25;
4441  cont->list[cont->index].default_expires = 250;
4442 
4443  if ((var = switch_channel_get_variable(channel, "tone_detect_sleep"))) {
4444  int tmp = atoi(var);
4445  if (tmp > 0) {
4446  cont->list[cont->index].default_sleep = tmp;
4447  }
4448  }
4449 
4450  if ((var = switch_channel_get_variable(channel, "tone_detect_expires"))) {
4451  int tmp = atoi(var);
4452  if (tmp > 0) {
4453  cont->list[cont->index].default_expires = tmp;
4454  }
4455  }
4456 
4457 
4458  if (zstr(flags)) {
4459  bflags = SMBF_READ_REPLACE;
4460  } else {
4461  if (strchr(flags, 'o')) {
4462  cont->list[cont->index].once = 1;
4463  }
4464 
4465  if (strchr(flags, 'r')) {
4466  bflags |= SMBF_READ_REPLACE;
4467  } else if (strchr(flags, 'w')) {
4468  bflags |= SMBF_WRITE_REPLACE;
4469  }
4470  }
4471 
4472  bflags |= SMBF_NO_PAUSE;
4473 
4474  if (cont->bug_running) {
4475  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s bug already running\n", switch_channel_get_name(channel));
4476  } else {
4477  cont->bug_running = 1;
4478  if (cont->detect_fax) {
4479  switch_core_event_hook_add_send_dtmf(session, tone_on_dtmf);
4480  switch_core_event_hook_add_recv_dtmf(session, tone_on_dtmf);
4481  }
4482 
4483  if ((status = switch_core_media_bug_add(session, "tone_detect", key,
4484  tone_detect_callback, cont, timeout, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
4485  cont->bug_running = 0;
4486  return status;
4487  }
4488  switch_channel_set_private(channel, "_tone_detect_", cont);
4489  }
4490 
4491  cont->index++;
4492 
4493  return SWITCH_STATUS_SUCCESS;
4494 }
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
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:314
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.
char * key
Definition: switch_msrp.c:64
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session&#39;s pool.
Definition: switch_core.h:696
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&#39;s pool.
Definition: switch_core.h:719
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_ivr_transfer_recordings()

switch_status_t switch_ivr_transfer_recordings ( switch_core_session_t orig_session,
switch_core_session_t new_session 
)

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

Referenced by switch_channel_mark_hold(), and switch_ivr_originate().

1952 {
1953  const char *var = NULL;
1954  switch_channel_t *orig_channel = switch_core_session_get_channel(orig_session);
1955  switch_channel_t *new_channel = switch_core_session_get_channel(new_session);
1956 
1959  }
1961 
1963 }
#define SWITCH_RECORD_POST_PROCESS_EXEC_APP_VARIABLE
Definition: switch_types.h:147
_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:148
#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_ivr_transfer_variable()

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 2318 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.

2319 {
2322  switch_event_t *var_event;
2323 
2324  const char *val = NULL;
2325  uint8_t prefix = 0;
2326 
2327  if (var && *var == '~') {
2328  var++;
2329  prefix = 1;
2330  }
2331 
2332  if (var && !prefix) {
2333  if ((val = switch_channel_get_variable(chana, var))) {
2334  switch_channel_set_variable(chanb, var, val);
2335  }
2336  } else {
2338 
2339  switch_channel_get_variables(chana, &var_event);
2340 
2341  for (hi = var_event->headers; hi; hi = hi->next) {
2342  char *vvar = hi->name;
2343  char *vval = hi->value;
2344  if (vvar && vval && (!prefix || (var && !strncmp((char *) vvar, var, strlen(var))))) {
2345  switch_channel_set_variable(chanb, (char *) vvar, (char *) vval);
2346  }
2347  }
2348 
2349  switch_event_destroy(&var_event);
2350  }
2351 
2352  return SWITCH_STATUS_SUCCESS;
2353 }
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_ivr_unhold()

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 1603 of file switch_ivr.c.

References CCS_HELD, 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_callstate(), switch_channel_get_partner_uuid(), SWITCH_CHANNEL_SESSION_LOG, 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_log_printf(), SWITCH_LOG_WARNING, SWITCH_MESSAGE_INDICATE_UNHOLD, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

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

1604 {
1605  switch_core_session_message_t msg = { 0 };
1607  const char *other_uuid;
1608  switch_core_session_t *b_session;
1609  switch_event_t *event;
1610 
1611  if (channel) {
1612  switch_channel_callstate_t callstate;
1613 
1614  callstate = switch_channel_get_callstate(channel);
1615  if (callstate != CCS_HELD) {
1616  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Call is not on hold. No need to unhold.\n");
1617  return SWITCH_STATUS_FALSE;
1618  }
1619  }
1620 
1622  msg.from = __FILE__;
1623 
1626 
1627  switch_core_session_receive_message(session, &msg);
1628 
1629 
1630  if ((other_uuid = switch_channel_get_partner_uuid(channel)) && (b_session = switch_core_session_locate(other_uuid))) {
1631  switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
1632  switch_channel_stop_broadcast(b_channel);
1633  switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
1634  switch_core_session_rwunlock(b_session);
1635  }
1636 
1637 
1639  switch_channel_event_set_data(channel, event);
1640  switch_event_fire(&event);
1641  }
1642 
1643  return SWITCH_STATUS_SUCCESS;
1644 }
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_core_session_message_types_t message_id
Definition: switch_core.h:183
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:179
_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_channel_callstate_t
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
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&#39;s uuid.
Definition: switch_core.h:932
#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:384
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_channel_callstate_t switch_channel_get_callstate(switch_channel_t *channel)
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_ivr_unhold_uuid()

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 1646 of file switch_ivr.c.

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

1647 {
1650 
1651  if ((session = switch_core_session_locate(uuid))) {
1652  status = switch_ivr_unhold(session);
1654  }
1655 
1656  return status;
1657 }
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
Common return values.
switch_status_t switch_ivr_unhold(switch_core_session_t *session)
Signal the session with a protocol specific unhold message.
Definition: switch_ivr.c:1603
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932

◆ switch_ivr_uuid_bridge()

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 2005 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_ivr_check_hold(), 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().

2006 {
2007  switch_core_session_t *originator_session, *originatee_session, *swap_session;
2008  switch_channel_t *originator_channel, *originatee_channel, *swap_channel;
2010  switch_caller_profile_t *originator_cp, *originatee_cp;
2012 
2013  if ((originator_session = switch_core_session_locate(originator_uuid))) {
2014  if ((originatee_session = switch_core_session_locate(originatee_uuid))) {
2015  originator_channel = switch_core_session_get_channel(originator_session);
2016  originatee_channel = switch_core_session_get_channel(originatee_session);
2017 
2018  switch_ivr_check_hold(originator_session);
2019  switch_ivr_check_hold(originatee_session);
2020 
2021 
2022  if (switch_channel_test_flag(originator_channel, CF_LEG_HOLDING)) {
2023  switch_channel_set_flag(originator_channel, CF_HOLD_ON_BRIDGE);
2024  }
2025 
2026  if (switch_channel_test_flag(originatee_channel, CF_LEG_HOLDING)) {
2027  switch_channel_set_flag(originatee_channel, CF_HOLD_ON_BRIDGE);
2028  }
2029 
2030 
2031  if (switch_channel_direction(originator_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(originator_channel, CF_DIALPLAN)) {
2032  if (!switch_channel_test_flag(originator_channel, CF_RECOVERING_BRIDGE)) {
2033  switch_channel_flip_cid(originator_channel);
2034  }
2035  switch_channel_set_flag(originator_channel, CF_DIALPLAN);
2036  }
2037 
2038  if (switch_channel_down_nosig(originator_channel)) {
2039  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));
2040  switch_core_session_rwunlock(originator_session);
2041  switch_core_session_rwunlock(originatee_session);
2042  return SWITCH_STATUS_FALSE;
2043  }
2044 
2045  if (!switch_channel_media_up(originator_channel)) {
2046  if (switch_channel_media_up(originatee_channel)) {
2047  swap_session = originator_session;
2048  originator_session = originatee_session;
2049  originatee_session = swap_session;
2050 
2051  swap_channel = originator_channel;
2052  originator_channel = originatee_channel;
2053  originatee_channel = swap_channel;
2054  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originatee_session), SWITCH_LOG_WARNING, "reversing order of channels so this will work!\n");
2055  } else {
2056  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_CRIT, "Neither channel is answered, cannot bridge them.\n");
2057  switch_core_session_rwunlock(originator_session);
2058  switch_core_session_rwunlock(originatee_session);
2059  return SWITCH_STATUS_FALSE;
2060  }
2061  }
2062 
2063  if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(originatee_channel, CF_DIALPLAN)) {
2064  switch_channel_clear_flag(originatee_channel, CF_DIALPLAN);
2065  }
2066 
2067  cleanup_proxy_mode_a(originator_session);
2068  cleanup_proxy_mode_a(originatee_session);
2069 
2070  /* override transmit state for originator_channel to bridge to originatee_channel
2071  * install pointer to originatee_session into originator_channel
2072  * set CF_TRANSFER on both channels and change state to CS_SOFT_EXECUTE to
2073  * interrupt anything they are already doing.
2074  * originatee_session will fall asleep and originator_session will bridge to it
2075  */
2076 
2077  switch_channel_set_flag(originator_channel, CF_REDIRECT);
2078  switch_channel_set_flag(originatee_channel, CF_REDIRECT);
2079 
2080 
2081  switch_channel_set_variable(originator_channel, SWITCH_UUID_BRIDGE, switch_core_session_get_uuid(originatee_session));
2088 
2089 
2090  originator_cp = switch_channel_get_caller_profile(originator_channel);
2091  originatee_cp = switch_channel_get_caller_profile(originatee_channel);
2092 
2093 
2094 
2095  if (switch_channel_outbound_display(originator_channel)) {
2096  switch_channel_invert_cid(originator_channel);
2097 
2098  if (switch_channel_direction(originator_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2099  switch_channel_clear_flag(originatee_channel, CF_BLEG);
2100  }
2101  }
2102 
2103  if (switch_channel_inbound_display(originatee_channel)) {
2104  switch_channel_invert_cid(originatee_channel);
2105 
2106  if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2107  switch_channel_set_flag(originatee_channel, CF_BLEG);
2108  }
2109 
2110  }
2111 
2112 
2113  switch_channel_set_variable(originatee_channel, "original_destination_number", originatee_cp->destination_number);
2114  switch_channel_set_variable(originatee_channel, "original_caller_id_name", originatee_cp->caller_id_name);
2115  switch_channel_set_variable(originatee_channel, "original_caller_id_number", originatee_cp->caller_id_number);
2116 
2117  switch_channel_set_variable(originator_channel, "original_destination_number", originator_cp->destination_number);
2118  switch_channel_set_variable(originator_channel, "original_caller_id_name", originator_cp->caller_id_name);
2119  switch_channel_set_variable(originator_channel, "original_caller_id_number", originator_cp->caller_id_number);
2120 
2121  switch_channel_step_caller_profile(originatee_channel);
2122  switch_channel_step_caller_profile(originator_channel);
2123 
2124  originator_cp = switch_channel_get_caller_profile(originator_channel);
2125  originatee_cp = switch_channel_get_caller_profile(originatee_channel);
2126 
2127 
2128 #ifdef DEEP_DEBUG_CID
2129  {
2130  switch_event_t *event;
2131 
2133  //switch_channel_event_set_basic_data(originator_channel, event);
2134  switch_caller_profile_event_set_data(originator_cp, "ORIGINATOR", event);
2135  switch_caller_profile_event_set_data(originatee_cp, "ORIGINATEE", event);
2136  DUMP_EVENT(event);
2137  switch_event_destroy(&event);
2138  }
2139  }
2140 #endif
2141 
2142  switch_channel_set_originator_caller_profile(originatee_channel, switch_caller_profile_clone(originatee_session, originator_cp));
2143  switch_channel_set_originatee_caller_profile(originator_channel, switch_caller_profile_clone(originator_session, originatee_cp));
2144 
2145  originator_cp->callee_id_name = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_name);
2146  originator_cp->callee_id_number = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_number);
2147 
2148  originatee_cp->caller_id_name = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_name);
2149  originatee_cp->caller_id_number = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_number);
2150 
2151 #ifdef DEEP_DEBUG_CID
2152  {
2153  switch_event_t *event;
2154 
2156  //switch_channel_event_set_basic_data(originator_channel, event);
2157  switch_caller_profile_event_set_data(originator_cp, "POST-ORIGINATOR", event);
2158  switch_caller_profile_event_set_data(originatee_cp, "POST-ORIGINATEE", event);
2159  DUMP_EVENT(event);
2160  switch_event_destroy(&event);
2161  }
2162  }
2163 #endif
2164 
2165  switch_channel_stop_broadcast(originator_channel);
2166  switch_channel_stop_broadcast(originatee_channel);
2167 
2168  switch_channel_set_flag(originator_channel, CF_TRANSFER);
2169  switch_channel_set_flag(originatee_channel, CF_TRANSFER);
2170 
2171 
2172  switch_channel_clear_flag(originator_channel, CF_ORIGINATING);
2173  switch_channel_clear_flag(originatee_channel, CF_ORIGINATING);
2174 
2175 
2176  originator_cp->transfer_source = switch_core_sprintf(originator_cp->pool,
2177  "%ld:%s:uuid_br:%s", (long)switch_epoch_time_now(NULL), originator_cp->uuid_str,
2178  switch_core_session_get_uuid(originatee_session));
2182 
2183 
2184  originatee_cp->transfer_source = switch_core_sprintf(originatee_cp->pool,
2185  "%ld:%s:uuid_br:%s", (long)switch_epoch_time_now(NULL), originatee_cp->uuid_str,
2186  switch_core_session_get_uuid(originator_session));
2190 
2191  /* change the states and let the chips fall where they may */
2192 
2193  //switch_channel_set_variable(originator_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
2194  //switch_channel_set_variable(originatee_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
2195  switch_channel_clear_state_handler(originator_channel, NULL);
2196  switch_channel_clear_state_handler(originatee_channel, NULL);
2197 
2198 
2199 
2202 
2206 
2209 
2210  state = switch_channel_get_state(originator_channel);
2211  switch_channel_set_state(originator_channel, state == CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE);
2212  state = switch_channel_get_state(originatee_channel);
2213  switch_channel_set_state(originatee_channel, state == CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE);
2214 
2215  status = SWITCH_STATUS_SUCCESS;
2216 
2217  //switch_ivr_bridge_display(originator_session, originatee_session);
2218 
2219  /* release the read locks we have on the channels */
2220  switch_core_session_rwunlock(originator_session);
2221  switch_core_session_rwunlock(originatee_session);
2222 
2223  } else {
2224  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_DEBUG, "originatee uuid %s is not present\n", originatee_uuid);
2225  switch_core_session_rwunlock(originator_session);
2226  }
2227  } else {
2228  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(originator_session), SWITCH_LOG_DEBUG, "originator uuid %s is not present\n", originator_uuid);
2229  }
2230 
2231  return status;
2232 }
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:145
#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:733
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:184
#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&#39;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:386
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:203
void switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
Set the given channel&#39;s originatee caller profile.
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932
#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:144
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:322
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_ivr_check_hold(switch_core_session_t *session)
Definition: switch_ivr.c:2143
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&#39;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:182
#define SWITCH_UUID_BRIDGE
Definition: switch_types.h:234
switch_memory_pool_t * pool

◆ switch_ivr_wait_for_silence()

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 2080 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, count, switch_frame::data, switch_frame::datalen, if(), 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_frame::seq, 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_DEBUG, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, SWITCH_STATUS_FALSE, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, and switch_zmalloc.

2082 {
2083  uint32_t score, count = 0, j = 0;
2084  double energy = 0;
2086  int divisor = 0;
2087  uint32_t org_silence_hits = silence_hits;
2088  uint32_t channels;
2089  switch_frame_t *read_frame;
2091  int16_t *data;
2092  uint32_t listening = 0;
2093  int countdown = 0;
2094  switch_codec_t raw_codec = { 0 };
2095  int16_t *abuf = NULL;
2096  switch_frame_t write_frame = { 0 };
2097  switch_file_handle_t fh = { 0 };
2098  int32_t sample_count = 0;
2099  switch_codec_implementation_t read_impl = { 0 };
2100  switch_core_session_get_read_impl(session, &read_impl);
2101 
2102 
2103  if (timeout_ms) {
2104  sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
2105  }
2106 
2107  if (file) {
2108  if (switch_core_file_open(&fh,
2109  file,
2110  read_impl.number_of_channels,
2112  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failure opening playback file %s.\n", file);
2114  return SWITCH_STATUS_NOTFOUND;
2115  }
2117  write_frame.data = abuf;
2118  write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
2119  }
2120 
2121 
2122  if (switch_core_codec_init(&raw_codec,
2123  "L16",
2124  NULL,
2125  NULL,
2126  read_impl.actual_samples_per_second,
2127  read_impl.microseconds_per_packet / 1000,
2130 
2131  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to initialize L16 codec.\n");
2132  status = SWITCH_STATUS_FALSE;
2133  goto end;
2134  }
2135 
2136  write_frame.codec = &raw_codec;
2137 
2138  divisor = read_impl.actual_samples_per_second / 8000;
2139  channels = read_impl.number_of_channels;
2140 
2141  switch_core_session_set_read_codec(session, &raw_codec);
2142 
2143  while (switch_channel_ready(channel)) {
2144 
2145  /* reinitialize energy value per loop */
2146  energy = 0;
2147 
2148  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
2149 
2150  if (!SWITCH_READ_ACCEPTABLE(status)) {
2151  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read frame.\n");
2152  break;
2153  }
2154 
2155  if (sample_count) {
2156  sample_count -= raw_codec.implementation->samples_per_packet;
2157  if (sample_count <= 0) {
2158  switch_channel_set_variable(channel, "wait_for_silence_timeout", "true");
2159  switch_channel_set_variable_printf(channel, "wait_for_silence_listenhits", "%d", listening);
2160  switch_channel_set_variable_printf(channel, "wait_for_silence_silence_hits", "%d", silence_hits);
2162  "switch_ivr_wait_for_silence: TIMEOUT after %d ms at %d listen hits, %d silence hits, %d countdown\n",
2163  timeout_ms, listening, (org_silence_hits - silence_hits), countdown);
2164  break;
2165  }
2166  }
2167 
2168  if (abuf) {
2170 
2171  if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
2172  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to read file %s.\n", file);
2173  break;
2174  }
2175 
2176  write_frame.samples = (uint32_t) olen;
2177  write_frame.datalen = (uint32_t) (olen * sizeof(int16_t) * fh.channels);
2178  if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
2179  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to write frame from file %s.\n", file);
2180  break;
2181  }
2182  }
2183 
2184  if (countdown) {
2185  if (!--countdown) {
2186  switch_channel_set_variable(channel, "wait_for_silence_timeout", "false");
2187  switch_channel_set_variable_printf(channel, "wait_for_silence_listenhits", "%d", listening);
2188  switch_channel_set_variable_printf(channel, "wait_for_silence_silence_hits", "%d", silence_hits);
2189  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_wait_for_silence: SILENCE DETECTED\n");
2190  break;
2191  } else {
2192  continue;
2193  }
2194  }
2195 
2196  data = (int16_t *) read_frame->data;
2197 
2198  /* Need to check if the read_frame is valid before attempting to get "energy" value from it */
2199  if (read_frame->seq) {
2200  for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
2201  energy += abs(data[j++]);
2202  j += channels;
2203  }
2204  }
2205 
2206  score = (uint32_t) (energy / (read_frame->samples / divisor));
2207 
2208  if (score >= thresh) {
2209  listening++;
2210  }
2211 
2212  if (((listen_hits == 0) || (listening > listen_hits)) && (score < thresh)) {
2213  if (!--silence_hits) {
2214  countdown = 25;
2215  }
2216  } else {
2217  silence_hits = org_silence_hits;
2218  }
2219  }
2220 
2222  switch_core_codec_destroy(&raw_codec);
2223 
2224  end:
2225 
2226  if (abuf) {
2227 
2229  free(abuf);
2230  }
2231 
2232  return status;
2233 }
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:1963
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:590
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:56
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.
uint16_t seq
Definition: switch_frame.h:81
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:70
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
uint32_t datalen
Definition: switch_frame.h:68
#define switch_zmalloc(ptr, len)
An abstraction of a data frame.
Definition: switch_frame.h:54
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:1693
switch_status_t
Common return values.
uint32_t samples
Definition: switch_frame.h:72
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.
int count
Definition: switch_cJSON.h:204
#define switch_channel_set_variable(_channel, _var, _val)
#define SWITCH_READ_ACCEPTABLE(status)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.

◆ switch_play_and_get_digits()

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 2627 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, target, and zstr.

Referenced by CoreSession::playAndGetDigits(), and switch_ivr_menu_execute().

2641 {
2643  char *var_name_invalid = NULL;
2644 
2645  if (!zstr(digits_regex) && !zstr(var_name)) {
2646  var_name_invalid = switch_mprintf("%s_invalid", var_name);
2647  switch_channel_set_variable(channel, var_name_invalid, NULL);
2648  switch_safe_free(var_name_invalid);
2649  }
2650 
2651  while (switch_channel_ready(channel) && max_tries) {
2652  switch_status_t status;
2653 
2654  memset(digit_buffer, 0, digit_buffer_length);
2655 
2656  status = switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name,
2657  digit_buffer, digit_buffer_length, timeout, valid_terminators, digit_timeout);
2658 
2659  if (status == SWITCH_STATUS_RESTART) {
2660  return status;
2661  }
2662 
2663  if (status == SWITCH_STATUS_TIMEOUT && strlen(digit_buffer) >= min_digits) {
2664  status = SWITCH_STATUS_SUCCESS;
2665  }
2666 
2667  if ((min_digits == 0) && (strlen(digit_buffer) == 0) && switch_channel_get_variable(channel, SWITCH_READ_TERMINATOR_USED_VARIABLE) != 0)
2668  {
2669  return SWITCH_STATUS_SUCCESS;
2670  }
2671 
2672  if (!(status == SWITCH_STATUS_TOO_SMALL && strlen(digit_buffer) == 0)) {
2673  if (status == SWITCH_STATUS_SUCCESS) {
2674  if (!zstr(digit_buffer)) {
2675  if (zstr(digits_regex)) {
2676  return SWITCH_STATUS_SUCCESS;
2677  }
2678  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "Test Regex [%s][%s]\n", digit_buffer, digits_regex);
2679 
2680  if (switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) {
2681  return SWITCH_STATUS_SUCCESS;
2682  } else {
2683  switch_channel_set_variable(channel, var_name, NULL);
2684  if (!zstr(var_name)) {
2685  var_name_invalid = switch_mprintf("%s_invalid", var_name);
2686  switch_channel_set_variable(channel, var_name_invalid, digit_buffer);
2687  switch_safe_free(var_name_invalid);
2688  }
2689  }
2690  }
2691  }
2692  }
2693 
2694  if (!switch_channel_ready(channel)) {
2695  break;
2696  }
2697 
2698  switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL);
2699  max_tries--;
2700  }
2701 
2702  memset(digit_buffer, 0, digit_buffer_length);
2703 
2704  /* If we get here then check for transfer-on-failure ext/dp/context */
2705  /* split this arg on spaces to get ext, dp, and context */
2706 
2707  if (!zstr(transfer_on_failure)) {
2708  const char *failure_ext = NULL;
2709  const char *failure_dialplan = NULL;
2710  const char *failure_context = NULL;
2711  char *target[4];
2712  char *mydata = switch_core_session_strdup(session, transfer_on_failure);
2713  int argc;
2714 
2715  argc = switch_separate_string(mydata, ' ', target, (sizeof(target) / sizeof(target[0])));
2716 
2717  if ( argc < 1 ) {
2718  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,"Bad target for PAGD failure: [%s]\n", transfer_on_failure);
2719  return SWITCH_STATUS_FALSE;
2720  }
2721 
2722  if ( argc > 0 ) {
2723  failure_ext = target[0];
2724  }
2725 
2726  if ( argc > 1 ) {
2727  failure_dialplan = target[1];
2728  }
2729 
2730  if ( argc > 2 ) {
2731  failure_context = target[2];
2732  }
2733 
2735  "PAGD failure! Transfer to: %s / %s / %s\n", failure_ext, failure_dialplan, failure_context);
2736 
2737  switch_ivr_session_transfer(session,failure_ext, failure_dialplan, failure_context);
2738  return SWITCH_STATUS_FALSE;
2739  }
2740 
2741  return SWITCH_STATUS_FALSE;
2742 }
#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:314
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:885
#define SWITCH_READ_TERMINATOR_USED_VARIABLE
Definition: switch_types.h:130
switch_status_t
Common return values.
const cJSON *const target
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&#39;s pool.
Definition: switch_core.h:719
#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:300