forked from Mirrors/freeswitch
support crazy transfer crap
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@7083 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
cb03f74e20
commit
69120105ee
@ -32,7 +32,7 @@
|
||||
<!--<param name="dtmf-type" value="info"/>-->
|
||||
<param name="record-template" value="$${base_dir}/recordings/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
|
||||
<!--enable to use presense and mwi -->
|
||||
<param name="manage-presence" value="true"/>
|
||||
<param name="manage-presence" value="false"/>
|
||||
<!-- This setting is for AAL2 bitpacking on G726 -->
|
||||
<!-- <param name="bitpacking" value="aal2"/> -->
|
||||
<!--max number of open dialogs in proceeding -->
|
||||
|
@ -727,6 +727,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro(switch_core_session_t *s
|
||||
SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint32_t delay_ms);
|
||||
SWITCH_DECLARE(void) switch_ivr_intercept_session(switch_core_session_t *session, const char *uuid);
|
||||
SWITCH_DECLARE(void) switch_ivr_park_session(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t *session, switch_core_session_t *peer_session);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -628,6 +628,7 @@ CF_UNICAST = (1 << 21) - Channel has a unicast connection
|
||||
CF_VIDEO = (1 << 22) - Channel has video
|
||||
CF_EVENT_LOCK = (1 << 23) - Don't parse events
|
||||
CF_RESET = (1 << 24) - Tell extension parser to reset
|
||||
CF_ORIGINATING = (1 << 25) - Channel is originating
|
||||
</pre>
|
||||
*/
|
||||
|
||||
@ -656,7 +657,8 @@ typedef enum {
|
||||
CF_UNICAST = (1 << 21),
|
||||
CF_VIDEO = (1 << 22),
|
||||
CF_EVENT_LOCK = (1 << 23),
|
||||
CF_RESET = (1 << 24)
|
||||
CF_RESET = (1 << 24),
|
||||
CF_ORIGINATING = (1 << 25)
|
||||
} switch_channel_flag_t;
|
||||
|
||||
|
||||
|
@ -1685,6 +1685,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
|
||||
switch_channel_set_variable(nchannel, "sip_destination_url", tech_pvt->dest);
|
||||
|
||||
caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
|
||||
caller_profile->destination_number = switch_core_strdup(caller_profile->pool, dest);
|
||||
switch_channel_set_caller_profile(nchannel, caller_profile);
|
||||
switch_channel_set_flag(nchannel, CF_OUTBOUND);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
|
||||
|
@ -132,7 +132,7 @@ static void switch_core_standard_on_execute(switch_core_session_t *session)
|
||||
char *expanded = NULL;
|
||||
int nomedia = 0;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Execute %s(%s)\n",
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Execute %s(%s)\n", switch_channel_get_name(session->channel),
|
||||
extension->current_application->application_name, switch_str_nil(extension->current_application->application_data));
|
||||
if ((application_interface = switch_loadable_module_get_application_interface(extension->current_application->application_name)) == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", extension->current_application->application_name);
|
||||
@ -156,8 +156,9 @@ static void switch_core_standard_on_execute(switch_core_session_t *session)
|
||||
if ((expanded =
|
||||
switch_channel_expand_variables(session->channel,
|
||||
extension->current_application->application_data)) != extension->current_application->application_data) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Expanded String %s(%s)\n", extension->current_application->application_name,
|
||||
expanded);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Expanded String %s(%s)\n", switch_channel_get_name(session->channel),
|
||||
extension->current_application->application_name, expanded);
|
||||
|
||||
}
|
||||
|
||||
if (switch_channel_get_variable(session->channel, "presence_id")) {
|
||||
|
@ -852,6 +852,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_
|
||||
channel = switch_core_session_get_channel(session);
|
||||
switch_assert(channel != NULL);
|
||||
|
||||
switch_channel_clear_flag(channel, CF_ORIGINATING);
|
||||
|
||||
/* clear all state handlers */
|
||||
switch_channel_clear_state_handler(channel, NULL);
|
||||
|
||||
|
@ -596,7 +596,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
|
||||
switch_channel_answer(caller_channel);
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
|
||||
if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) ||
|
||||
switch_channel_test_flag(peer_channel, CF_RING_READY)) {
|
||||
switch_event_t *event;
|
||||
switch_core_session_message_t msg = { 0 };
|
||||
const switch_application_interface_t *application_interface;
|
||||
@ -627,7 +628,29 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!(switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) {
|
||||
if ((status = switch_ivr_wait_for_answer(session, peer_session)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_state_t w_state = switch_channel_get_state(caller_channel);
|
||||
switch_channel_hangup(peer_channel, SWITCH_CAUSE_ALLOTTED_TIMEOUT);
|
||||
if (w_state < CS_HANGUP && w_state != CS_RING && w_state != CS_PARK && !switch_channel_test_flag(caller_channel, CF_TRANSFER) &&
|
||||
w_state != CS_EXECUTE) {
|
||||
const char *ext = switch_channel_get_variable(peer_channel, "original_destination_number");
|
||||
if (!ext) {
|
||||
ext = switch_channel_get_variable(peer_channel, "destination_number");
|
||||
}
|
||||
|
||||
if (ext) {
|
||||
switch_ivr_session_transfer(session, ext, NULL, NULL);
|
||||
} else {
|
||||
switch_channel_hangup(caller_channel, SWITCH_CAUSE_ALLOTTED_TIMEOUT);
|
||||
}
|
||||
}
|
||||
switch_core_session_rwunlock(peer_session);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
|
||||
msg.from = __FILE__;
|
||||
msg.string_arg = switch_core_session_strdup(peer_session, switch_core_session_get_uuid(session));
|
||||
@ -707,8 +730,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uuid, const char *originatee_uuid)
|
||||
{
|
||||
switch_core_session_t *originator_session, *originatee_session;
|
||||
switch_channel_t *originator_channel, *originatee_channel;
|
||||
switch_core_session_t *originator_session, *originatee_session, *swap_session;
|
||||
switch_channel_t *originator_channel, *originatee_channel, *swap_channel;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_caller_profile_t *cp, *originator_cp, *originatee_cp;
|
||||
|
||||
@ -717,6 +740,23 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
|
||||
originator_channel = switch_core_session_get_channel(originator_session);
|
||||
originatee_channel = switch_core_session_get_channel(originatee_session);
|
||||
|
||||
if (!switch_channel_test_flag(originator_channel, CF_ANSWERED)) {
|
||||
if (switch_channel_test_flag(originatee_channel, CF_ANSWERED)) {
|
||||
swap_session = originator_session;
|
||||
originator_session = originatee_session;
|
||||
originatee_session = swap_session;
|
||||
|
||||
swap_channel = originator_channel;
|
||||
originator_channel = originatee_channel;
|
||||
originatee_channel = swap_channel;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "reversing order of channels so this will work!\n");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Neither channel is answered, cannot bridge them.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* override transmit state for originator_channel to bridge to originatee_channel
|
||||
* install pointer to originatee_session into originator_channel
|
||||
* set CF_TRANSFER on both channels and change state to CS_TRANSMIT to
|
||||
@ -726,12 +766,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
|
||||
|
||||
switch_channel_clear_state_handler(originator_channel, NULL);
|
||||
switch_channel_clear_state_handler(originatee_channel, NULL);
|
||||
switch_channel_set_flag(originator_channel, CF_ORIGINATOR);
|
||||
switch_channel_set_state_flag(originator_channel, CF_ORIGINATOR);
|
||||
switch_channel_clear_flag(originatee_channel, CF_ORIGINATOR);
|
||||
switch_channel_add_state_handler(originator_channel, &uuid_bridge_state_handlers);
|
||||
switch_channel_add_state_handler(originatee_channel, &uuid_bridge_state_handlers);
|
||||
switch_channel_set_variable(originator_channel, SWITCH_UUID_BRIDGE, switch_core_session_get_uuid(originatee_session));
|
||||
|
||||
|
||||
|
||||
switch_channel_set_variable(originator_channel, SWITCH_BRIDGE_CHANNEL_VARIABLE, switch_channel_get_name(originatee_channel));
|
||||
switch_channel_set_variable(originator_channel, SWITCH_BRIDGE_UUID_VARIABLE, switch_core_session_get_uuid(originatee_session));
|
||||
@ -743,6 +784,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
|
||||
|
||||
originator_cp = switch_channel_get_caller_profile(originator_channel);
|
||||
originatee_cp = switch_channel_get_caller_profile(originatee_channel);
|
||||
|
||||
|
||||
switch_channel_set_variable(originatee_channel, "original_destination_number", originatee_cp->destination_number);
|
||||
switch_channel_set_variable(originatee_channel, "original_caller_id_name", originatee_cp->caller_id_name);
|
||||
switch_channel_set_variable(originatee_channel, "original_caller_id_number", originatee_cp->caller_id_number);
|
||||
|
||||
switch_channel_set_variable(originator_channel, "original_destination_number", originator_cp->destination_number);
|
||||
switch_channel_set_variable(originator_channel, "original_caller_id_name", originator_cp->caller_id_name);
|
||||
switch_channel_set_variable(originator_channel, "original_caller_id_number", originator_cp->caller_id_number);
|
||||
|
||||
|
||||
cp = switch_caller_profile_clone(originatee_session, originatee_cp);
|
||||
cp->destination_number = switch_core_strdup(cp->pool, originator_cp->caller_id_number);
|
||||
@ -750,7 +801,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
|
||||
cp->caller_id_name = switch_core_strdup(cp->pool, originator_cp->caller_id_name);
|
||||
switch_channel_set_caller_profile(originatee_channel, cp);
|
||||
switch_channel_set_originator_caller_profile(originatee_channel, switch_caller_profile_clone(originatee_session, originator_cp));
|
||||
|
||||
|
||||
cp = switch_caller_profile_clone(originator_session, originator_cp);
|
||||
cp->destination_number = switch_core_strdup(cp->pool, originatee_cp->caller_id_number);
|
||||
cp->caller_id_number = switch_core_strdup(cp->pool, originatee_cp->caller_id_number);
|
||||
@ -763,6 +814,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
|
||||
|
||||
switch_channel_set_flag(originator_channel, CF_TRANSFER);
|
||||
switch_channel_set_flag(originatee_channel, CF_TRANSFER);
|
||||
|
||||
switch_channel_clear_flag(originator_channel, CF_ORIGINATING);
|
||||
switch_channel_clear_flag(originatee_channel, CF_ORIGINATING);
|
||||
|
||||
/* change the states and let the chips fall where they may */
|
||||
switch_channel_set_state(originator_channel, CS_RESET);
|
||||
|
@ -165,13 +165,19 @@ static uint8_t check_channel_status(switch_channel_t **peer_channels,
|
||||
*idx = IDX_NADA;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
switch_channel_state_t state;
|
||||
if (!peer_channels[i]) {
|
||||
continue;
|
||||
}
|
||||
if (!*ring_ready && switch_channel_test_flag(peer_channels[i], CF_RING_READY)) {
|
||||
*ring_ready = 1;
|
||||
}
|
||||
if (switch_channel_get_state(peer_channels[i]) >= CS_HANGUP) {
|
||||
|
||||
state = switch_channel_get_state(peer_channels[i]);
|
||||
if (state >= CS_HANGUP || state == CS_RESET || switch_channel_test_flag(peer_channels[i], CF_TRANSFER) ||
|
||||
switch_channel_test_flag(peer_channels[i], CF_BRIDGED) ||
|
||||
!switch_channel_test_flag(peer_channels[i], CF_ORIGINATING)
|
||||
) {
|
||||
(*hups)++;
|
||||
} else if ((switch_channel_test_flag(peer_channels[i], CF_ANSWERED) ||
|
||||
(early_ok && len == 1 && switch_channel_test_flag(peer_channels[i], CF_EARLY_MEDIA))) &&
|
||||
@ -233,6 +239,284 @@ static int teletone_handler(teletone_generation_session_t * ts, teletone_tone_ma
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t *session, switch_core_session_t *peer_session)
|
||||
{
|
||||
switch_channel_t *caller_channel;
|
||||
switch_channel_t *peer_channel;
|
||||
const char *ringback_data = NULL;
|
||||
switch_frame_t write_frame = { 0 };
|
||||
switch_codec_t write_codec = { 0 };
|
||||
switch_codec_t *read_codec = NULL;
|
||||
uint8_t pass = 0;
|
||||
ringback_t ringback = { 0 };
|
||||
switch_core_session_message_t *message = NULL;
|
||||
switch_frame_t *read_frame = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
uint8_t abuf[1024];
|
||||
int timelimit = 60;
|
||||
const char *var;
|
||||
switch_time_t start = 0;
|
||||
|
||||
caller_channel = switch_core_session_get_channel(session);
|
||||
peer_channel = switch_core_session_get_channel(peer_session);
|
||||
|
||||
switch_assert(caller_channel && peer_channel);
|
||||
|
||||
if ((var = switch_channel_get_variable(caller_channel, "call_timeout"))) {
|
||||
timelimit = atoi(var);
|
||||
if (timelimit < 0) {
|
||||
timelimit = 60;
|
||||
}
|
||||
}
|
||||
|
||||
timelimit *= 1000000;
|
||||
start = switch_timestamp_now();
|
||||
|
||||
if ((switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
read_codec = switch_core_session_get_read_codec(session);
|
||||
|
||||
if (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
|
||||
ringback_data = switch_channel_get_variable(caller_channel, "transfer_ringback");
|
||||
}
|
||||
|
||||
if (!ringback_data) {
|
||||
ringback_data = switch_channel_get_variable(caller_channel, "ringback");
|
||||
}
|
||||
|
||||
switch_channel_set_variable(caller_channel, "originate_disposition", "failure");
|
||||
|
||||
|
||||
if (ringback_data) {
|
||||
char *tmp_data = NULL;
|
||||
ringback_t ringback = { 0 };
|
||||
|
||||
switch_buffer_create_dynamic(&ringback.audio_buffer, 512, 1024, 0);
|
||||
switch_buffer_set_loops(ringback.audio_buffer, -1);
|
||||
|
||||
if (switch_is_file_path(ringback_data)) {
|
||||
char *ext;
|
||||
|
||||
if (strrchr(ringback_data, '.') || strstr(ringback_data, SWITCH_URL_SEPARATOR)) {
|
||||
switch_core_session_set_read_codec(session, &write_codec);
|
||||
} else {
|
||||
ringback.asis++;
|
||||
write_frame.codec = read_codec;
|
||||
ext = read_codec->implementation->iananame;
|
||||
tmp_data = switch_mprintf("%s.%s", ringback_data, ext);
|
||||
ringback_data = tmp_data;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback File [%s]\n", ringback_data);
|
||||
|
||||
ringback.fhb.channels = read_codec->implementation->number_of_channels;
|
||||
ringback.fhb.samplerate = read_codec->implementation->actual_samples_per_second;
|
||||
if (switch_core_file_open(&ringback.fhb,
|
||||
ringback_data,
|
||||
read_codec->implementation->number_of_channels,
|
||||
read_codec->implementation->actual_samples_per_second,
|
||||
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
|
||||
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing File\n");
|
||||
switch_safe_free(tmp_data);
|
||||
goto done;
|
||||
}
|
||||
ringback.fh = &ringback.fhb;
|
||||
|
||||
|
||||
} else {
|
||||
teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback);
|
||||
ringback.ts.rate = read_codec->implementation->actual_samples_per_second;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback Tone [%s]\n", ringback_data);
|
||||
//ringback.ts.debug = 1;
|
||||
//ringback.ts.debug_stream = switch_core_get_console();
|
||||
if (teletone_run(&ringback.ts, ringback_data)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing Tone\n");
|
||||
teletone_destroy_session(&ringback.ts);
|
||||
switch_buffer_destroy(&ringback.audio_buffer);
|
||||
ringback_data = NULL;
|
||||
}
|
||||
}
|
||||
switch_safe_free(tmp_data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (ringback_data && !switch_channel_test_flag(caller_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
|
||||
switch_channel_pre_answer(caller_channel);
|
||||
}
|
||||
|
||||
if ((read_codec = switch_core_session_get_read_codec(session)) && (ringback_data || !switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA))) {
|
||||
if (!(pass = (uint8_t) switch_test_flag(read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH))) {
|
||||
if (switch_core_codec_init(&write_codec,
|
||||
"L16",
|
||||
NULL,
|
||||
read_codec->implementation->actual_samples_per_second,
|
||||
read_codec->implementation->microseconds_per_frame / 1000,
|
||||
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
|
||||
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
|
||||
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"Raw Codec Activation Success L16@%uhz 1 channel %dms\n",
|
||||
read_codec->implementation->actual_samples_per_second, read_codec->implementation->microseconds_per_frame / 1000);
|
||||
write_frame.data = abuf;
|
||||
write_frame.buflen = sizeof(abuf);
|
||||
|
||||
write_frame.codec = &write_codec;
|
||||
write_frame.datalen = read_codec->implementation->bytes_per_frame;
|
||||
write_frame.samples = write_frame.datalen / 2;
|
||||
memset(write_frame.data, 255, write_frame.datalen);
|
||||
|
||||
if (ringback_data) {
|
||||
char *tmp_data = NULL;
|
||||
|
||||
switch_buffer_create_dynamic(&ringback.audio_buffer, 512, 1024, 0);
|
||||
switch_buffer_set_loops(ringback.audio_buffer, -1);
|
||||
|
||||
if (switch_is_file_path(ringback_data)) {
|
||||
char *ext;
|
||||
|
||||
if (strrchr(ringback_data, '.') || strstr(ringback_data, SWITCH_URL_SEPARATOR)) {
|
||||
switch_core_session_set_read_codec(session, &write_codec);
|
||||
} else {
|
||||
ringback.asis++;
|
||||
write_frame.codec = read_codec;
|
||||
ext = read_codec->implementation->iananame;
|
||||
tmp_data = switch_mprintf("%s.%s", ringback_data, ext);
|
||||
ringback_data = tmp_data;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback File [%s]\n", ringback_data);
|
||||
|
||||
ringback.fhb.channels = read_codec->implementation->number_of_channels;
|
||||
ringback.fhb.samplerate = read_codec->implementation->actual_samples_per_second;
|
||||
if (switch_core_file_open(&ringback.fhb,
|
||||
ringback_data,
|
||||
read_codec->implementation->number_of_channels,
|
||||
read_codec->implementation->actual_samples_per_second,
|
||||
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
|
||||
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing File\n");
|
||||
switch_safe_free(tmp_data);
|
||||
goto done;
|
||||
}
|
||||
ringback.fh = &ringback.fhb;
|
||||
|
||||
|
||||
} else {
|
||||
teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback);
|
||||
ringback.ts.rate = read_codec->implementation->actual_samples_per_second;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback Tone [%s]\n", ringback_data);
|
||||
//ringback.ts.debug = 1;
|
||||
//ringback.ts.debug_stream = switch_core_get_console();
|
||||
if (teletone_run(&ringback.ts, ringback_data)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing Tone\n");
|
||||
teletone_destroy_session(&ringback.ts);
|
||||
switch_buffer_destroy(&ringback.audio_buffer);
|
||||
ringback_data = NULL;
|
||||
}
|
||||
}
|
||||
switch_safe_free(tmp_data);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec Error!\n");
|
||||
switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
|
||||
read_codec = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!(switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) {
|
||||
int diff = (int)(switch_timestamp_now() - start);
|
||||
|
||||
if (diff > timelimit) {
|
||||
status = SWITCH_STATUS_TIMEOUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (switch_core_session_dequeue_message(peer_session, &message) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_core_session_receive_message(session, message);
|
||||
|
||||
if (switch_test_flag(message, SCSMF_DYNAMIC)) {
|
||||
switch_safe_free(message);
|
||||
} else {
|
||||
message = NULL;
|
||||
}
|
||||
}
|
||||
status = switch_core_session_read_frame(session, &read_frame, 1000, 0);
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (read_frame && !pass) {
|
||||
if (ringback.fh) {
|
||||
uint8_t abuf[1024];
|
||||
switch_size_t mlen, olen;
|
||||
unsigned int pos = 0;
|
||||
|
||||
if (ringback.asis) {
|
||||
mlen = write_frame.codec->implementation->encoded_bytes_per_frame;
|
||||
} else {
|
||||
mlen = write_frame.codec->implementation->samples_per_frame;
|
||||
}
|
||||
|
||||
olen = mlen;
|
||||
switch_core_file_read(ringback.fh, abuf, &olen);
|
||||
|
||||
if (olen == 0) {
|
||||
olen = mlen;
|
||||
ringback.fh->speed = 0;
|
||||
switch_core_file_seek(ringback.fh, &pos, 0, SEEK_SET);
|
||||
switch_core_file_read(ringback.fh, abuf, &olen);
|
||||
if (olen == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
write_frame.data = abuf;
|
||||
write_frame.datalen = (uint32_t) (ringback.asis ? olen : olen * 2);
|
||||
} else if (ringback.audio_buffer) {
|
||||
if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(ringback.audio_buffer,
|
||||
write_frame.data,
|
||||
write_frame.codec->implementation->bytes_per_frame)) <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_core_session_write_frame(session, &write_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch_yield(1000);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (ringback.fh) {
|
||||
switch_core_file_close(ringback.fh);
|
||||
ringback.fh = NULL;
|
||||
} else if (ringback.audio_buffer) {
|
||||
teletone_destroy_session(&ringback.ts);
|
||||
switch_buffer_destroy(&ringback.audio_buffer);
|
||||
}
|
||||
|
||||
if (!pass && write_codec.implementation) {
|
||||
if (read_codec && !ringback.asis) {
|
||||
switch_core_session_set_read_codec(session, read_codec);
|
||||
switch_core_session_reset(session);
|
||||
}
|
||||
switch_core_codec_destroy(&write_codec);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
#define MAX_PEERS 128
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *session,
|
||||
switch_core_session_t **bleg,
|
||||
@ -608,8 +892,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
peer_sessions[i] = new_session;
|
||||
peer_channels[i] = switch_core_session_get_channel(new_session);
|
||||
switch_assert(peer_channels[i] != NULL);
|
||||
|
||||
|
||||
switch_channel_set_flag(peer_channels[i], CF_ORIGINATING);
|
||||
|
||||
if (var_event) {
|
||||
switch_event_t *event;
|
||||
switch_event_header_t *header;
|
||||
@ -888,6 +1172,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
if (!peer_channels[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(peer_channels[i], CF_TRANSFER) || switch_channel_test_flag(peer_channels[i], CF_BRIDGED) ||
|
||||
switch_channel_get_state(peer_channels[i]) == CS_RESET ||
|
||||
!switch_channel_test_flag(peer_channels[i], CF_ORIGINATING)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i != idx) {
|
||||
if (idx == IDX_CANCEL) {
|
||||
if (to) {
|
||||
@ -916,6 +1208,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
peer_channel = peer_channels[idx];
|
||||
} else {
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
peer_channel = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -968,6 +1261,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
}
|
||||
}
|
||||
|
||||
if (*cause == SWITCH_CAUSE_SUCCESS || *cause == SWITCH_CAUSE_UNALLOCATED) {
|
||||
*cause = SWITCH_CAUSE_ORIGINATOR_CANCEL;
|
||||
}
|
||||
|
||||
if (idx == IDX_CANCEL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"Originate Cancelled by originator termination Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
|
||||
@ -982,26 +1279,28 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
switch_channel_set_variable(caller_channel, "originate_disposition", switch_channel_cause2str(*cause));
|
||||
}
|
||||
|
||||
if (!pass && write_codec.implementation) {
|
||||
switch_core_codec_destroy(&write_codec);
|
||||
}
|
||||
|
||||
if (ringback.fh) {
|
||||
switch_core_file_close(ringback.fh);
|
||||
ringback.fh = NULL;
|
||||
if (read_codec && !ringback.asis) {
|
||||
switch_core_session_set_read_codec(session, read_codec);
|
||||
switch_core_session_reset(session);
|
||||
}
|
||||
} else if (ringback.audio_buffer) {
|
||||
teletone_destroy_session(&ringback.ts);
|
||||
switch_buffer_destroy(&ringback.audio_buffer);
|
||||
}
|
||||
|
||||
if (!pass && write_codec.implementation) {
|
||||
if (read_codec && !ringback.asis) {
|
||||
switch_core_session_set_read_codec(session, read_codec);
|
||||
switch_core_session_reset(session);
|
||||
}
|
||||
switch_core_codec_destroy(&write_codec);
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < and_argc; i++) {
|
||||
if (!peer_channels[i]) {
|
||||
continue;
|
||||
}
|
||||
switch_channel_clear_flag(peer_channels[i], CF_ORIGINATING);
|
||||
if (status == SWITCH_STATUS_SUCCESS && bleg && *bleg && *bleg == peer_sessions[i]) {
|
||||
continue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user