SWITCH_DECLARE(const char *) switch_channel_get_hold_music_partner(switch_channel_t *channel);
SWITCH_DECLARE(uint32_t) switch_channel_del_variable_prefix(switch_channel_t *channel, const char *prefix);
+SWITCH_DECLARE(switch_status_t) switch_channel_transfer_variable_prefix(switch_channel_t *orig_channel, switch_channel_t *new_channel, const char *prefix);
#define switch_channel_set_variable_safe(_channel, _var, _val) switch_channel_set_variable_var_check(_channel, _var, _val, SWITCH_FALSE)
#define switch_channel_set_variable(_channel, _var, _val) switch_channel_set_variable_var_check(_channel, _var, _val, SWITCH_TRUE)
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream);
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session);
+SWITCH_DECLARE(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 *));
+
+
/*!
\brief Read a frame from the bug
\param bug the bug to read from
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t *session, char *file, uint32_t limit, switch_file_handle_t *fh);
+SWITCH_DECLARE(switch_status_t) switch_ivr_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session);
SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_pop_eavesdropper(switch_core_session_t *session, switch_core_session_t **sessionp);
#define SWITCH_TRANSFER_HISTORY_VARIABLE "transfer_history"
#define SWITCH_TRANSFER_SOURCE_VARIABLE "transfer_source"
#define SWITCH_SENSITIVE_DTMF_VARIABLE "sensitive_dtmf"
+#define SWITCH_RECORD_POST_PROCESS_EXEC_APP_VARIABLE "record_post_process_exec_app"
+#define SWITCH_RECORD_POST_PROCESS_EXEC_API_VARIABLE "record_post_process_exec_api"
#define SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE "execute_on_answer"
#define SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE "execute_on_pre_answer"
{
switch_core_session_t *peer_session = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
- switch_channel_t *channel, *peer_channel = NULL;
+ switch_channel_t *channel = switch_core_session_get_channel(session), *peer_channel = NULL;
const char *bond = NULL;
switch_core_session_t *b_session = NULL;
+ switch_bool_t follow_recording = switch_true(switch_channel_get_variable(channel, "recording_follow_attxfer"));
- channel = switch_core_session_get_channel(session);
-
bond = switch_channel_get_partner_uuid(channel);
switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, bond);
switch_core_event_hook_add_state_change(session, tmp_hanguphook);
+ if (follow_recording && (b_session = switch_core_session_locate(bond))) {
+ switch_ivr_transfer_recordings(b_session, session);
+ switch_core_session_rwunlock(b_session);
+ }
if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL)
!= SWITCH_STATUS_SUCCESS || !peer_session) {
}
if (bond) {
- char buf[128] = "";
int br = 0;
switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
if (!switch_channel_down(peer_channel)) {
if (!switch_channel_ready(channel)) {
- switch_status_t status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(peer_session), bond);
+ switch_status_t status;
+
+ if (follow_recording) {
+ switch_ivr_transfer_recordings(session, peer_session);
+ }
+ status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(peer_session), bond);
att_xfer_set_result(peer_channel, status);
br++;
} else if ((b_session = switch_core_session_locate(bond))) {
switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
- switch_snprintf(buf, sizeof(buf), "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
- switch_channel_set_variable(b_channel, "xfer_uuids", buf);
-
- switch_snprintf(buf, sizeof(buf), "%s %s", switch_core_session_get_uuid(peer_session), bond);
- switch_channel_set_variable(channel, "xfer_uuids", buf);
+ switch_channel_set_variable_printf(b_channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
+ switch_channel_set_variable_printf(channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), bond);
switch_core_event_hook_add_state_change(session, hanguphook);
switch_core_event_hook_add_state_change(b_session, hanguphook);
return r;
}
+SWITCH_DECLARE(switch_status_t) switch_channel_transfer_variable_prefix(switch_channel_t *orig_channel, switch_channel_t *new_channel, const char *prefix)
+{
+ switch_event_header_t *hi = NULL;
+ int x = 0;
+
+ if ((hi = switch_channel_variable_first(orig_channel))) {
+ for (; hi; hi = hi->next) {
+ char *var = hi->name;
+ char *val = hi->value;
+
+ if (zstr(prefix) || !strncasecmp(var, prefix, strlen(prefix))) {
+ x++;
+ switch_channel_set_variable(new_channel, var, val);
+ }
+ }
+ switch_channel_variable_last(orig_channel);
+ }
+
+ return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+}
SWITCH_DECLARE(void) switch_channel_set_presence_data_vals(switch_channel_t *channel, const char *presence_data_cols)
{
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
+
+SWITCH_DECLARE(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 *))
+{
+ switch_media_bug_t *new_bug = NULL, *cur = NULL, *bp = NULL, *last = NULL;
+ int total = 0;
+
+ switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
+ bp = orig_session->bugs;
+ while (bp) {
+ cur = bp;
+ bp = bp->next;
+
+ if (cur->callback == callback) {
+ if (last) {
+ last->next = cur->next;
+ } else {
+ orig_session->bugs = cur->next;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_DEBUG, "Transfering %s from %s to %s\n", cur->target,
+ switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session));
+
+ switch_core_media_bug_add(new_session, cur->function, cur->target, cur->callback,
+ user_data_dup_func(new_session, cur->user_data),
+ cur->stop_time, cur->flags, &new_bug);
+ switch_core_media_bug_destroy(cur);
+ total++;
+ } else {
+ last = cur;
+ }
+ }
+
+ if (!orig_session->bugs && switch_core_codec_ready(&orig_session->bug_codec)) {
+ switch_core_codec_destroy(&orig_session->bug_codec);
+ }
+
+ switch_thread_rwlock_unlock(orig_session->bug_rwlock);
+
+
+ return total ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+}
+
+
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_pop(switch_core_session_t *orig_session, const char *function, switch_media_bug_t **pop)
{
switch_media_bug_t *bp;
switch_event_fire(&event);
}
- switch_channel_execute_on(channel, "record_post_process_exec_app");
+ switch_channel_execute_on(channel, SWITCH_RECORD_POST_PROCESS_EXEC_APP_VARIABLE);
- if ((var = switch_channel_get_variable(channel, "record_post_process_exec_api"))) {
+ if ((var = switch_channel_get_variable(channel, SWITCH_RECORD_POST_PROCESS_EXEC_API_VARIABLE))) {
char *cmd = switch_core_session_strdup(session, var);
char *data, *expanded = NULL;
switch_stream_handle_t stream = { 0 };
return SWITCH_STATUS_FALSE;
}
+static void* switch_ivr_record_user_data_dup(switch_core_session_t *session, void *user_data)
+{
+ struct record_helper *rh = (struct record_helper *) user_data, *dup = NULL;
+
+ dup = switch_core_session_alloc(session, sizeof(*dup));
+ memcpy(dup, rh, sizeof(*rh));
+ dup->file = switch_core_session_strdup(session, rh->file);
+
+ return dup;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session)
+{
+ const char *var = NULL;
+ switch_channel_t *orig_channel = switch_core_session_get_channel(orig_session);
+ switch_channel_t *new_channel = switch_core_session_get_channel(new_session);
+
+ if ((var = switch_channel_get_variable(orig_channel, SWITCH_RECORD_POST_PROCESS_EXEC_API_VARIABLE))) {
+ switch_channel_set_variable(new_channel, SWITCH_RECORD_POST_PROCESS_EXEC_API_VARIABLE, var);
+ }
+ switch_channel_transfer_variable_prefix(orig_channel, new_channel, SWITCH_RECORD_POST_PROCESS_EXEC_APP_VARIABLE);
+
+ return switch_core_media_bug_transfer_callback(orig_session, new_session, record_callback, switch_ivr_record_user_data_dup);
+}
+
struct eavesdrop_pvt {
switch_buffer_t *buffer;
switch_mutex_t *mutex;