uint32_t soft_lock;
switch_ivr_dmachine_t *dmachine[2];
plc_state_t *plc;
+ uint8_t recur_buffer[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ switch_size_t recur_buffer_len;
};
struct switch_media_bug {
uint32_t record_pre_buffer_count;
uint32_t record_pre_buffer_max;
switch_frame_t *ping_frame;
+ switch_frame_t *read_demux_frame;
struct switch_media_bug *next;
};
#define switch_core_session_get_name(_s) switch_channel_get_name(switch_core_session_get_channel(_s))
+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_DECLARE(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);
+
/*!
\brief Add a media bug to the session
\param session the session to add the bug to
\param bug the bug to get the data from
*/
SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_read_replace_frame(_In_ switch_media_bug_t *bug);
-
+SWITCH_DECLARE(void) switch_core_media_bug_set_read_demux_frame(_In_ switch_media_bug_t *bug, _In_ switch_frame_t *frame);
/*!
\brief Obtain the session from a media bug
\param bug the bug to get the data from
\param bug bug to remove
\return SWITCH_STATUS_SUCCESS if the operation was a success
*/
+
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug);
SWITCH_DECLARE(uint32_t) switch_core_media_bug_prune(switch_core_session_t *session);
\param session the session to remove the bugs from
\return SWITCH_STATUS_SUCCESS if the operation was a success
*/
-SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(_In_ switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all_function(_In_ switch_core_session_t *session, const char *function);
+
+#define switch_core_media_bug_remove_all(_s) switch_core_media_bug_remove_all_function(_s, NULL)
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_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_eavesdrop_pop_eavesdropper(switch_core_session_t *session, switch_core_session_t **sessionp);
+SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_exec_all(switch_core_session_t *session, const char *app, const char *arg);
+SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_update_display(switch_core_session_t *session, const char *name, const char *number);
+
/*!
\brief Eavesdrop on a another session
\param session our session
///\}
SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples);
-
+SWITCH_DECLARE(uint32_t) switch_unmerge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples);
SWITCH_DECLARE(void) switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t channels);
SWITCH_END_EXTERN_C
ED_NONE = 0,
ED_MUX_READ = (1 << 0),
ED_MUX_WRITE = (1 << 1),
- ED_DTMF = (1 << 2)
+ ED_DTMF = (1 << 2),
+ ED_COPY_DISPLAY = (1 << 3)
} switch_eavesdrop_flag_enum_t;
typedef uint32_t switch_eavesdrop_flag_t;
SMBF_THREAD_LOCK = (1 << 7),
SMBF_PRUNE = (1 << 8),
SMBF_NO_PAUSE = (1 << 9),
- SMBF_STEREO_SWAP = (1 << 10)
+ SMBF_STEREO_SWAP = (1 << 10),
+ SMBF_LOCK = (1 << 11)
} switch_media_bug_flag_enum_t;
typedef uint32_t switch_media_bug_flag_t;
};
typedef struct switch_console_callback_match switch_console_callback_match_t;
+typedef void (*switch_media_bug_exec_cb_t)(switch_media_bug_t *bug, void *user_data);
+
typedef void (*switch_cap_callback_t) (const char *var, const char *val, void *user_data);
typedef switch_status_t (*switch_console_complete_callback_t) (const char *, const char *, switch_console_callback_match_t **matches);
typedef switch_bool_t (*switch_media_bug_callback_t) (switch_media_bug_t *, void *, switch_abc_type_t);
number = tech_pvt->caller_profile->destination_number;
}
+ switch_ivr_eavesdrop_update_display(session, name, number);
+
if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY) && switch_channel_test_flag(channel, CF_ANSWERED)) {
if (zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) ||
zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) {
}
+SWITCH_STANDARD_APP(sofia_sla_function)
+{
+ private_object_t *tech_pvt;
+ switch_core_session_t *bargee_session;
+
+ if (zstr(data)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: <uuid>\n");
+ return;
+ }
+
+ if ((bargee_session = switch_core_session_locate((char *)data))) {
+ if (bargee_session == session) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "BARGE: %s (cannot barge on myself)\n", (char *) data);
+ } else {
+ if (switch_core_session_check_interface(bargee_session, sofia_endpoint_interface)) {
+ tech_pvt = switch_core_session_get_private(bargee_session);
+ sofia_set_flag(tech_pvt, TFLAG_SLA_BARGE);
+ switch_ivr_transfer_variable(bargee_session, session, SWITCH_SIGNAL_BOND_VARIABLE);
+ }
+ }
+
+ switch_core_session_rwunlock(bargee_session);
+ }
+
+ switch_ivr_eavesdrop_session(session, data, NULL, ED_MUX_READ | ED_MUX_WRITE | ED_COPY_DISPLAY);
+}
+
+
SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
{
switch_chat_interface_t *chat_interface;
switch_api_interface_t *api_interface;
switch_management_interface_t *management_interface;
+ switch_application_interface_t *app_interface;
struct in_addr in;
memset(&mod_sofia_globals, 0, sizeof(mod_sofia_globals));
management_interface->relative_oid = "1001";
management_interface->management_function = sofia_manage;
+ SWITCH_ADD_APP(app_interface, "sofia_sla", "private sofia sla function",
+ "private sofia sla function", sofia_sla_function, "<uuid>", SAF_NONE);
+
SWITCH_ADD_API(api_interface, "sofia", "Sofia Controls", sofia_function, "<cmd> <args>");
SWITCH_ADD_API(api_interface, "sofia_gateway_data", "Get data from a sofia gateway", sofia_gateway_data_function,
"<gateway_name> [ivar|ovar|var] <name>");
TFLAG_GOT_ACK,
TFLAG_CAPTURE,
TFLAG_REINVITED,
+ TFLAG_SLA_BARGE,
/* No new flags below this line */
TFLAG_MAX
} TFLAGS;
status = 200;
phrase = "OK";
+ if (sofia_test_flag(tech_pvt, TFLAG_SLA_BARGE)) {
+ switch_core_session_t *new_session, *other_session;
+ const char *other_uuid = switch_channel_get_variable(tech_pvt->channel, SWITCH_SIGNAL_BOND_VARIABLE);
+ char *cmd = NULL;
+
+ if (!zstr(other_uuid) && (other_session = switch_core_session_locate(other_uuid))) {
+ switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
+
+ switch_mutex_lock(profile->ireg_mutex);
+ if (switch_ivr_eavesdrop_pop_eavesdropper(session, &new_session) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_t *new_channel = switch_core_session_get_channel(new_session);
+ const char *new_uuid = switch_core_session_get_uuid(new_session);
+
+
+ switch_channel_set_variable(new_channel, SWITCH_SIGNAL_BOND_VARIABLE, NULL);
+
+ switch_channel_set_flag(other_channel, CF_REDIRECT);
+
+ switch_channel_set_state(new_channel, CS_RESET);
+
+ switch_ivr_uuid_bridge(new_uuid, other_uuid);
+ cmd = switch_core_session_sprintf(session, "sleep:500,sofia_sla:%s inline", new_uuid);
+
+ switch_channel_clear_flag(other_channel, CF_REDIRECT);
+
+ switch_core_session_rwunlock(new_session);
+ }
+ switch_mutex_unlock(profile->ireg_mutex);
+
+ switch_core_session_rwunlock(other_session);
+ }
+
+ if (!zstr(cmd)) {
+ switch_ivr_eavesdrop_exec_all(session, "transfer", cmd);
+ }
+ }
+
sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if ((b_session = switch_core_session_locate(b_private->uuid))) {
switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
const char *uuid;
- int one_leg = 1;
- private_object_t *b_tech_pvt = NULL;
const char *app = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_VARIABLE);
const char *data = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE);
switch_caller_profile_t *orig_cp;
tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,conference:%s+flags{dist-dtmf}", data);
tech_pvt->caller_profile->dialplan = "inline";
} else {
- if (switch_core_session_check_interface(b_session, sofia_endpoint_interface)) {
- b_tech_pvt = switch_core_session_get_private(b_session);
- }
-
- if ((uuid = switch_channel_get_variable(b_channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
- one_leg = 0;
- } else {
+ if (!(uuid = switch_channel_get_variable(b_channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
uuid = switch_core_session_get_uuid(b_session);
}
if (uuid) {
- switch_core_session_t *c_session = NULL;
- int do_conf = 0;
- const char *c_app = NULL;
- const char *c_data = NULL;
-
uuid = switch_core_session_strdup(b_session, uuid);
+ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
+ "answer,sofia_sla:%s", b_private->uuid);
- if (call_info && (c_session = switch_core_session_locate(uuid))) {
- switch_channel_t *c_channel = switch_core_session_get_channel(c_session);
- private_object_t *c_tech_pvt = NULL;
-
- c_app = switch_channel_get_variable(c_channel, SWITCH_CURRENT_APPLICATION_VARIABLE);
- c_data = switch_channel_get_variable(c_channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE);
-
- if (switch_core_session_check_interface(c_session, sofia_endpoint_interface)) {
- c_tech_pvt = switch_core_session_get_private(c_session);
- }
-
-
- if (!one_leg &&
- (!b_tech_pvt || !sofia_test_flag(b_tech_pvt, TFLAG_SIP_HOLD)) &&
- (!c_tech_pvt || !sofia_test_flag(c_tech_pvt, TFLAG_SIP_HOLD))) {
- char *ext = switch_core_session_sprintf(session, "answer,conference:%s@sla+flags{mintwo|dist-dtmf}", uuid);
-
- switch_channel_set_flag(c_channel, CF_REDIRECT);
- switch_ivr_session_transfer(b_session, ext, "inline", NULL);
- switch_ivr_session_transfer(c_session, ext, "inline", NULL);
- switch_channel_clear_flag(c_channel, CF_REDIRECT);
- do_conf = 1;
- }
- switch_core_session_rwunlock(c_session);
- }
-
- if (do_conf) {
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
- "answer,conference:%s@sla+flags{mintwo|dist-dtmf}", uuid);
- } else {
- if (one_leg && c_app) {
- if (c_data) {
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
- "answer,%s:%s", c_app, c_data);
- } else {
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
- "answer,%s", c_app);
- }
- } else {
- switch_channel_mark_hold(b_channel, SWITCH_FALSE);
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
- "answer,intercept:%s", uuid);
- }
- }
tech_pvt->caller_profile->dialplan = "inline";
}
}
}
#endif
+
if (hup && dh.hits > 0) {
goto done;
continue;
}
- if (bp->ready && switch_test_flag(bp, SMBF_READ_STREAM)) {
- switch_mutex_lock(bp->read_mutex);
- switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
-
- if (bp->callback) {
- ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ);
- }
- switch_mutex_unlock(bp->read_mutex);
- }
-
if (ok && switch_test_flag(bp, SMBF_READ_REPLACE)) {
do_bugs = 0;
if (bp->callback) {
bp->read_replace_frame_in = read_frame;
bp->read_replace_frame_out = read_frame;
+ bp->read_demux_frame = NULL;
if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) {
read_frame = bp->read_replace_frame_out;
}
}
}
+ if (session->bugs) {
+ switch_media_bug_t *bp;
+ switch_bool_t ok = SWITCH_TRUE;
+ int prune = 0;
+ switch_thread_rwlock_rdlock(session->bug_rwlock);
+
+ for (bp = session->bugs; bp; bp = bp->next) {
+ if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
+ continue;
+ }
+
+ if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
+ continue;
+ }
+ if (switch_test_flag(bp, SMBF_PRUNE)) {
+ prune++;
+ continue;
+ }
+
+ if (ok && bp->ready && switch_test_flag(bp, SMBF_READ_STREAM)) {
+ switch_mutex_lock(bp->read_mutex);
+ if (bp->read_demux_frame) {
+ uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ int bytes = read_frame->datalen / 2;
+
+ memcpy(data, read_frame->data, read_frame->datalen);
+ switch_unmerge_sln((int16_t *)data, bytes, bp->read_demux_frame->data, bytes);
+ switch_buffer_write(bp->raw_read_buffer, data, read_frame->datalen);
+ } else {
+ switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
+ }
+
+ if (bp->callback) {
+ ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ);
+ }
+ switch_mutex_unlock(bp->read_mutex);
+ }
+
+ if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
+ switch_set_flag(bp, SMBF_PRUNE);
+ prune++;
+ }
+ }
+ switch_thread_rwlock_unlock(session->bug_rwlock);
+ if (prune) {
+ switch_core_media_bug_prune(session);
+ }
+ }
+
if (do_bugs) {
goto done;
}
SWITCH_DECLARE(uint32_t) switch_core_media_bug_set_flag(switch_media_bug_t *bug, uint32_t flag)
{
+ if ((flag & SMBF_PRUNE)) {
+ switch_clear_flag(bug, SMBF_LOCK);
+ }
return switch_set_flag(bug, flag);
}
bug->read_replace_frame_out = frame;
}
+SWITCH_DECLARE(void) switch_core_media_bug_set_read_demux_frame(switch_media_bug_t *bug, switch_frame_t *frame)
+{
+ bug->read_demux_frame = frame;
+}
+
SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug)
{
return bug->user_data;
bytes = read_impl.decoded_bytes_per_packet;
+ if (0 && bug->session->recur_buffer_len) {
+ frame->datalen = bug->session->recur_buffer_len;
+ frame->samples = bug->session->recur_buffer_len / sizeof(int16_t);
+ frame->rate = read_impl.actual_samples_per_second;
+ frame->codec = NULL;
+ memcpy(frame->data, bug->session->recur_buffer, bug->session->recur_buffer_len);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+
if (frame->buflen < bytes) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "%s frame buffer too small!\n",
switch_channel_get_name(bug->session->channel));
return SWITCH_STATUS_BREAK;
}
+ memcpy(bug->session->recur_buffer, frame->data, frame->datalen);
+ bug->session->recur_buffer_len = frame->datalen;
+
return SWITCH_STATUS_SUCCESS;
}
return x ? 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;
+
+ if (orig_session->bugs) {
+ switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
+ for (bp = orig_session->bugs; bp; bp = bp->next) {
+ if (!strcmp(bp->function, function)) {
+ switch_set_flag(bp, SMBF_LOCK);
+ break;
+ }
+ }
+ switch_thread_rwlock_unlock(orig_session->bug_rwlock);
+
+ if (bp) {
+ *pop = bp;
+ return SWITCH_STATUS_SUCCESS;
+ } else {
+ *pop = NULL;
+ }
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_DECLARE(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_media_bug_t *bp;
+ int x = 0;
+
+ switch_assert(cb);
+
+ if (orig_session->bugs) {
+ switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
+ for (bp = orig_session->bugs; bp; bp = bp->next) {
+ if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, function)) {
+ cb(bp, user_data);
+ x++;
+ }
+ }
+ switch_thread_rwlock_unlock(orig_session->bug_rwlock);
+ }
+
+ return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+}
+
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream)
{
switch_media_bug_t *bp;
return SWITCH_STATUS_SUCCESS;
}
-SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(switch_core_session_t *session)
+SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all_function(switch_core_session_t *session, const char *function)
{
switch_media_bug_t *bp;
switch_status_t status = SWITCH_STATUS_FALSE;
if (session->bugs) {
switch_thread_rwlock_wrlock(session->bug_rwlock);
for (bp = session->bugs; bp; bp = bp->next) {
- if (bp->thread_id && bp->thread_id != switch_thread_self()) {
+ if ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
continue;
}
+
+ if (!zstr(function) && strcmp(bp->function, function)) {
+ continue;
+ }
+
if (bp->callback) {
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
{
switch_media_bug_t *bp = *bug;
if (bp) {
- if (bp->thread_id && bp->thread_id != switch_thread_self()) {
+ if ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(*bug)), SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
return SWITCH_STATUS_FALSE;
}
{
switch_media_bug_t *bp = NULL, *last = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (switch_core_media_bug_test_flag(*bug, SMBF_LOCK)) {
+ return status;
+ }
switch_thread_rwlock_wrlock(session->bug_rwlock);
if (session->bugs) {
switch_mutex_t *r_mutex;
switch_buffer_t *w_buffer;
switch_mutex_t *w_mutex;
+ switch_core_session_t *eavesdropper;
uint32_t flags;
+ switch_frame_t demux_frame;
+ uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
};
+
+
static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
struct eavesdrop_pvt *ep = (struct eavesdrop_pvt *) user_data;
if (switch_buffer_inuse(ep->r_buffer) >= rframe->datalen) {
uint32_t bytes;
switch_buffer_lock(ep->r_buffer);
- bytes = (uint32_t) switch_buffer_read(ep->r_buffer, data, rframe->datalen);
+ bytes = (uint32_t) switch_buffer_read(ep->r_buffer, ep->data, rframe->datalen);
- rframe->datalen = switch_merge_sln(rframe->data, rframe->samples, (int16_t *) data, bytes / 2) * 2;
+ rframe->datalen = switch_merge_sln(rframe->data, rframe->samples, (int16_t *) ep->data, bytes / 2) * 2;
rframe->samples = rframe->datalen / 2;
+ ep->demux_frame.data = ep->data;
+ ep->demux_frame.datalen = bytes;
+ ep->demux_frame.samples = bytes / 2;
+
switch_buffer_unlock(ep->r_buffer);
switch_core_media_bug_set_read_replace_frame(bug, rframe);
+ switch_core_media_bug_set_read_demux_frame(bug, &ep->demux_frame);
}
}
}
return SWITCH_TRUE;
}
+SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_pop_eavesdropper(switch_core_session_t *session, switch_core_session_t **sessionp)
+{
+ switch_media_bug_t *bug;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (switch_core_media_bug_pop(session, "eavesdrop", &bug) == SWITCH_STATUS_SUCCESS) {
+ struct eavesdrop_pvt *ep = (struct eavesdrop_pvt *) switch_core_media_bug_get_user_data(bug);
+
+ if (ep && ep->eavesdropper && ep->eavesdropper != session) {
+ switch_core_session_read_lock(ep->eavesdropper);
+ *sessionp = ep->eavesdropper;
+ switch_core_media_bug_set_flag(bug, SMBF_PRUNE);
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ }
+
+
+ return status;
+}
+
+struct exec_cb_data {
+ switch_core_session_t *caller;
+ char *var;
+ char *val;
+};
+
+static void exec_cb(switch_media_bug_t *bug, void *user_data)
+{
+ struct exec_cb_data *data = (struct exec_cb_data *) user_data;
+ struct eavesdrop_pvt *ep = (struct eavesdrop_pvt *) switch_core_media_bug_get_user_data(bug);
+
+ if (ep && ep->eavesdropper && ep->eavesdropper != data->caller) {
+ switch_channel_t *a = switch_core_session_get_channel(ep->eavesdropper);
+ switch_channel_t *b = switch_core_session_get_channel(data->caller);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s telling %s to exec %s:%s\n",
+ switch_channel_get_name(b), switch_channel_get_name(a), data->var, data->val);
+
+ switch_core_session_execute_application(ep->eavesdropper, data->var, data->val);
+ }
+}
+
+static void display_exec_cb(switch_media_bug_t *bug, void *user_data)
+{
+ struct exec_cb_data *data = (struct exec_cb_data *) user_data;
+ struct eavesdrop_pvt *ep = (struct eavesdrop_pvt *) switch_core_media_bug_get_user_data(bug);
+
+ if (ep && ep->eavesdropper && ep->eavesdropper != data->caller) {
+ switch_core_session_message_t msg = { 0 };
+
+ msg.from = __FILE__;
+ msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
+ msg.string_array_arg[0] = data->var;
+ msg.string_array_arg[1] = data->val;
+
+ switch_core_session_receive_message(ep->eavesdropper, &msg);
+ }
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_exec_all(switch_core_session_t *session, const char *app, const char *arg)
+{
+ struct exec_cb_data *data = NULL;
+
+ data = switch_core_session_alloc(session, sizeof(*data));
+ data->var = switch_core_session_strdup(session, app);
+ data->val = switch_core_session_strdup(session, arg);
+ data->caller = session;
+
+ return switch_core_media_bug_exec_all(session, "eavesdrop", exec_cb, data);
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_update_display(switch_core_session_t *session, const char *name, const char *number)
+{
+ struct exec_cb_data *data = NULL;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ data = switch_core_session_alloc(session, sizeof(*data));
+ data->var = switch_core_session_strdup(session, name);
+ data->val = switch_core_session_strdup(session, number);
+ data->caller = session;
+
+ if (!switch_channel_test_app_flag_key("EAVESDROP", channel, 1)) {
+ switch_channel_set_app_flag_key("EAVESDROP", channel, 1);
+ status = switch_core_media_bug_exec_all(session, "eavesdrop", display_exec_cb, data);
+ switch_channel_clear_app_flag_key("EAVESDROP", channel, 1);
+ }
+
+ return status;
+}
+
+
SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session_t *session,
const char *uuid, const char *require_group, switch_eavesdrop_flag_t flags)
{
switch_status_t status = SWITCH_STATUS_FALSE;
switch_channel_t *channel = switch_core_session_get_channel(session);
int codec_initialized = 0;
+ const char *name, *num;
if ((tsession = switch_core_session_locate(uuid))) {
struct eavesdrop_pvt *ep = NULL;
write_frame.buflen = sizeof(buf);
write_frame.rate = codec.implementation->actual_samples_per_second;
+ ep->eavesdropper = session;
ep->flags = flags;
switch_mutex_init(&ep->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
switch_buffer_create_dynamic(&ep->buffer, 2048, 2048, 8192);
/* Tell the channel we are going to be in a bridge */
msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
switch_core_session_receive_message(session, &msg);
-
cp = switch_channel_get_caller_profile(tchannel);
- switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", cp->caller_id_number, cp->caller_id_name);
+ name = cp->caller_id_name;
+ num = cp->caller_id_number;
+
+ if (flags & ED_COPY_DISPLAY) {
+ const char *tmp_name = NULL, *tmp_num = NULL;
+ name = cp->callee_id_name;
+ num = cp->callee_id_number;
+
+ if (!((tmp_name = switch_channel_get_variable(tchannel, "last_sent_callee_id_name"))
+ && (tmp_num = switch_channel_get_variable(tchannel, "last_sent_callee_id_number")))) {
+
+ tmp_name = switch_channel_get_variable(tchannel, "callee_id_name");
+ tmp_num = switch_channel_get_variable(tchannel, "callee_id_number");
+ }
+
+ if (tmp_name) name = tmp_name;
+ if (tmp_num) num = tmp_num;
+
+ }
+
+ switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", name, num);
msg.string_arg = cid_buf;
msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
switch_core_session_receive_message(session, &msg);
return x;
}
+
+SWITCH_DECLARE(uint32_t) switch_unmerge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples)
+{
+ int i;
+ int32_t x;
+
+ if (samples > other_samples) {
+ x = other_samples;
+ } else {
+ x = samples;
+ }
+
+ for (i = 0; i < x; i++) {
+ data[i] -= other_data[i];
+ }
+
+ return x;
+}
+
SWITCH_DECLARE(void) switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t channels)
{
int16_t *buf;