add some goodies

This commit is contained in:
Anthony Minessale 2010-10-07 18:30:07 -05:00
parent 82f268cce6
commit 9537197b4d
10 changed files with 200 additions and 15 deletions

View File

@ -167,6 +167,7 @@ struct switch_core_session {
uint32_t track_id;
switch_log_level_t loglevel;
uint32_t soft_lock;
switch_ivr_dmachine_t *dmachine;
};
struct switch_media_bug {

View File

@ -704,7 +704,8 @@ SWITCH_DECLARE(switch_log_level_t) switch_core_session_get_loglevel(switch_core_
SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec);
SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine);
SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session);
/*!
\brief Retrieve the unique identifier from the core

View File

@ -557,6 +557,7 @@ SWITCH_DECLARE(uint32_t) switch_ivr_schedule_broadcast(time_t runtime, const cha
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const char *path, switch_media_flag_t flags);
SWITCH_DECLARE(void) switch_ivr_broadcast_in_thread(switch_core_session_t *session, const char *app, int flags);
/*!
\brief Transfer variables from one session to another

View File

@ -1057,6 +1057,7 @@ typedef enum {
CF_MEDIA_SET,
CF_CONSUME_ON_ORIGINATE,
CF_PASSTHRU_PTIME_MISMATCH,
CF_BRIDGE_NOWRITE,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CF_FLAG_MAX
} switch_channel_flag_t;

View File

@ -95,6 +95,120 @@ SWITCH_STANDARD_DIALPLAN(inline_dialplan_hunt)
return extension;
}
struct action_binding {
char *input;
char *string;
char *value;
switch_core_session_t *session;
};
static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match)
{
struct action_binding *act = (struct action_binding *) match->user_data;
switch_event_t *event;
switch_status_t status;
int exec = 0;
char *string = act->string;
switch_channel_t *channel = switch_core_session_get_channel(act->session);
if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s]\n",
switch_channel_get_name(channel), act->string, act->value);
if (!strncasecmp(string, "exec:", 5)) {
string += 5;
exec = 1;
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, string, act->value);
if (exec) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute", exec == 2 ? "non-blocking" : "blocking");
}
if ((status = switch_core_session_queue_event(act->session, &event)) != SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&event);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_WARNING, "%s event queue faiure.\n",
switch_core_session_get_name(act->session));
}
}
if (exec) {
char *cmd = switch_core_session_sprintf(act->session, "%s::%s", string, act->value);
switch_ivr_broadcast_in_thread(act->session, cmd, SMF_ECHO_ALEG|SMF_HOLD_BLEG);
}
return SWITCH_STATUS_SUCCESS;
}
#define CLEAR_DIGIT_ACTION_USAGE ""
SWITCH_STANDARD_APP(clear_digit_action_function)
{
//switch_channel_t *channel = switch_core_session_get_channel(session);
switch_ivr_dmachine_t *dmachine;
if ((dmachine = switch_core_session_get_dmachine(session))) {
switch_core_session_set_dmachine(session, NULL);
switch_ivr_dmachine_destroy(&dmachine);
}
}
#define BIND_DIGIT_ACTION_USAGE "<digits|~regex>,<string>,<value>"
SWITCH_STANDARD_APP(bind_digit_action_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_ivr_dmachine_t *dmachine;
char *mydata;
int argc = 0;
char *argv[3] = { 0 };
struct action_binding *act;
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE);
return;
}
if (!(dmachine = switch_core_session_get_dmachine(session))) {
uint32_t digit_timeout = 1500;
uint32_t input_timeout = 0;
const char *var;
uint32_t tmp;
if ((var = switch_channel_get_variable(channel, "bind_digit_digit_timeout"))) {
tmp = (uint32_t) atol(var);
if (tmp < 0) tmp = 0;
digit_timeout = tmp;
}
if ((var = switch_channel_get_variable(channel, "bind_digit_input_timeout"))) {
tmp = (uint32_t) atol(var);
if (tmp < 0) tmp = 0;
input_timeout = tmp;
}
switch_ivr_dmachine_create(&dmachine, NULL, digit_timeout, input_timeout);
switch_core_session_set_dmachine(session, dmachine);
}
mydata = switch_core_session_strdup(session, data);
argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 3 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2])) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE);
return;
}
act = switch_core_session_alloc(session, sizeof(*act));
act->input = argv[0];
act->string = argv[1];
act->value = argv[2];
act->session = session;
switch_ivr_dmachine_bind(dmachine, act->input, 0, digit_action_callback, act);
}
#define DETECT_SPEECH_SYNTAX "<mod_name> <gram_name> <gram_path> [<addr>] OR grammar <gram_name> [<path>] OR pause OR resume"
SWITCH_STANDARD_APP(detect_speech_function)
{
@ -3277,6 +3391,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_API(api_interface, "chat", "chat", chat_api_function, "<proto>|<from>|<to>|<message>|[<content-type>]");
SWITCH_ADD_API(api_interface, "strftime", "strftime", strftime_api_function, "<format_string>");
SWITCH_ADD_API(api_interface, "presence", "presence", presence_api_function, PRESENCE_USAGE);
SWITCH_ADD_APP(app_interface, "bind_digit_action", "bind a key sequence or regex to an action",
"bind a key sequence or regex to an action", bind_digit_action_function, BIND_DIGIT_ACTION_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "clear_digit_action", "clear all digit bindings", "",
clear_digit_action_function, CLEAR_DIGIT_ACTION_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "privacy", "Set privacy on calls", "Set caller privacy on calls.", privacy_function, "off|on|name|full|number",
SAF_SUPPORT_NOMEDIA);

View File

@ -5077,7 +5077,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
if (channel) {
if (sofia_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) {
if (sofia_test_flag(tech_pvt, TFLAG_EARLY_MEDIA) && !sofia_test_flag(tech_pvt, TFLAG_ANS)) {
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
sofia_set_flag(tech_pvt, TFLAG_SDP);
switch_channel_mark_answered(channel);

View File

@ -126,7 +126,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
switch_mutex_lock(session->read_codec->mutex);
top:
if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) {
switch_ivr_dmachine_ping(session->dmachine, NULL);
}
if (switch_channel_down(session->channel) || !switch_core_codec_ready(session->read_codec)) {
*frame = NULL;
status = SWITCH_STATUS_FALSE;
@ -1150,6 +1154,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio
switch_io_event_hook_recv_dtmf_t *ptr;
switch_status_t status;
switch_dtmf_t new_dtmf;
int fed = 0;
if (switch_channel_down(session->channel)) {
return SWITCH_STATUS_FALSE;
@ -1171,12 +1176,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio
new_dtmf.duration = switch_core_default_dtmf_duration(0);
}
if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) {
char str[2] = { dtmf->digit, '\0' };
switch_ivr_dmachine_feed(session->dmachine, str, NULL);
fed = 1;
}
for (ptr = session->event_hooks.recv_dtmf; ptr; ptr = ptr->next) {
if ((status = ptr->recv_dtmf(session, &new_dtmf, SWITCH_DTMF_RECV)) != SWITCH_STATUS_SUCCESS) {
return status;
}
}
return SWITCH_STATUS_SUCCESS;
return fed ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)

View File

@ -38,6 +38,16 @@
struct switch_session_manager session_manager;
SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine)
{
session->dmachine = dmachine;
}
SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session)
{
return session->dmachine;
}
SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec)
{
session->soft_lock = sec;
@ -1094,6 +1104,10 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
switch_ivr_clear_speech_cache(*session);
switch_channel_uninit((*session)->channel);
if ((*session)->dmachine) {
switch_ivr_dmachine_destroy(&(*session)->dmachine);
}
pool = (*session)->pool;
//#ifndef NDEBUG
//memset(*session, 0, sizeof(switch_core_session_t));

View File

@ -150,10 +150,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *
}
if (binding->is_regex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "binding regex: %s key: %.4d callback: %p data: %p\n",
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "binding regex: %s key: %.4d callback: %p data: %p\n",
digits, key, (void *)(intptr_t) callback, user_data);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "binding digits: %4s key: %.4d callback: %p data: %p\n",
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "binding digits: %4s key: %.4d callback: %p data: %p\n",
digits, key, (void *)(intptr_t) callback, user_data);
}
@ -264,27 +264,25 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *
switch_bool_t is_timeout = switch_ivr_dmachine_check_timeout(dmachine);
dm_match_t is_match = switch_ivr_dmachine_check_match(dmachine, is_timeout);
switch_status_t r;
int exec = 0;
if (zstr(dmachine->digits) && !is_timeout) {
r = SWITCH_STATUS_SUCCESS;
} else if (dmachine->cur_digit_len > dmachine->max_digit_len) {
r = SWITCH_STATUS_FALSE;
} else if (is_match == DM_MATCH_EXACT || (is_match == DM_MATCH_BOTH && is_timeout)) {
r = SWITCH_STATUS_FOUND;
dmachine->match.match_digits = dmachine->last_matching_digits;
dmachine->match.match_key = dmachine->last_matching_binding->key;
dmachine->match.user_data = dmachine->last_matching_binding->user_data;
if (dmachine->last_matching_binding->callback) {
dmachine->last_matching_binding->callback(&dmachine->match);
}
if (match_p) {
*match_p = &dmachine->match;
}
dmachine->is_match = 1;
exec = 1;
} else if (is_timeout) {
r = SWITCH_STATUS_TIMEOUT;
} else if (dmachine->cur_digit_len == dmachine->max_digit_len) {
@ -297,6 +295,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *
switch_ivr_dmachine_clear(dmachine);
}
if (exec && dmachine->last_matching_binding->callback) {
dmachine->last_matching_binding->callback(&dmachine->match);
}
return r;
}
@ -2501,7 +2503,7 @@ static void *SWITCH_THREAD_FUNC bcast_thread(switch_thread_t *thread, void *obj)
return NULL;
}
static void broadcast_in_thread(switch_core_session_t *session, const char *app, int flags)
SWITCH_DECLARE(void) switch_ivr_broadcast_in_thread(switch_core_session_t *session, const char *app, int flags)
{
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
@ -2606,7 +2608,7 @@ static switch_status_t meta_on_dtmf(switch_core_session_t *session, const switch
switch_channel_get_name(channel), dtmf->digit, md->sr[direction].map[dval].app);
if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
broadcast_in_thread(session, md->sr[direction].map[dval].app, flags | SMF_REBRIDGE);
switch_ivr_broadcast_in_thread(session, md->sr[direction].map[dval].app, flags | SMF_REBRIDGE);
} else {
switch_ivr_broadcast(switch_core_session_get_uuid(session), md->sr[direction].map[dval].app, flags);
}

View File

@ -468,6 +468,10 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
continue;
}
if (switch_channel_test_flag(chan_a, CF_BRIDGE_NOWRITE)) {
continue;
}
if (status != SWITCH_STATUS_BREAK && !switch_channel_test_flag(chan_a, CF_HOLD)) {
if (switch_core_session_write_frame(session_b, read_frame, SWITCH_IO_FLAG_NONE, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
@ -839,13 +843,26 @@ static switch_status_t hanguphook(switch_core_session_t *session)
{
switch_core_session_message_t msg = { 0 };
switch_channel_t *channel = NULL;
switch_event_t *event;
switch_channel_state_t state;
channel = switch_core_session_get_channel(session);
state = switch_channel_get_state(channel);
msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
msg.from = __FILE__;
msg.string_arg = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE);
if (state == CS_ROUTING) {
if (switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
switch_channel_clear_flag_recursive(channel, CF_BRIDGE_ORIGINATOR);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
}
}
switch_core_session_receive_message(session, &msg);
switch_core_event_hook_remove_state_change(session, hanguphook);
@ -859,6 +876,7 @@ static switch_status_t signal_bridge_on_hibernate(switch_core_session_t *session
const char *key;
switch_core_session_message_t msg = { 0 };
switch_event_t *event = NULL;
switch_ivr_dmachine_t *dmachine;
channel = switch_core_session_get_channel(session);
switch_assert(channel != NULL);
@ -886,6 +904,19 @@ static switch_status_t signal_bridge_on_hibernate(switch_core_session_t *session
}
}
if ((dmachine = switch_core_session_get_dmachine(session))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s not hibernating due to active digit parser, semi-hibernation engaged.\n", switch_channel_get_name(channel));
while(switch_channel_ready(channel) && switch_channel_get_state(channel) == CS_HIBERNATE) {
if (!switch_channel_test_flag(channel, CF_BROADCAST)) {
switch_ivr_dmachine_ping(dmachine, NULL);
}
switch_yield(20000);
}
}
return SWITCH_STATUS_SUCCESS;
}