Merge remote branch 'fsorig/master'

Conflicts:
	src/mod/applications/mod_commands/mod_commands.c
	src/mod/endpoints/mod_portaudio/mod_portaudio.c
	src/mod/endpoints/mod_portaudio/pablio.c
This commit is contained in:
System Administrator
2011-05-26 00:13:12 -04:00
671 changed files with 140614 additions and 18658 deletions

View File

@@ -29,6 +29,7 @@
* Matt Klein <mklein@nmedia.net>
* Michael Jerris <mike@jerris.com>
* Ken Rice <krice at suspicious dot org>
* Marc Olivier Chouinard <mochouinard@moctel.com>
*
* switch_ivr.c -- IVR Library
*
@@ -304,14 +305,11 @@ static void *SWITCH_THREAD_FUNC unicast_thread_run(switch_thread_t *thread, void
{
switch_unicast_conninfo_t *conninfo = (switch_unicast_conninfo_t *) obj;
switch_size_t len;
switch_channel_t *channel;
if (!conninfo) {
return NULL;
}
channel = switch_core_session_get_channel(conninfo->session);
while (switch_test_flag(conninfo, SUF_READY) && switch_test_flag(conninfo, SUF_THREAD_RUNNING)) {
len = conninfo->write_frame.buflen;
if (switch_socket_recv(conninfo->socket, conninfo->write_frame.data, &len) != SWITCH_STATUS_SUCCESS || len == 0) {
@@ -1358,6 +1356,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_
if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
status = SWITCH_STATUS_SUCCESS;
/* If we had early media in bypass mode before, it is no longer relevant */
if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
switch_core_session_message_t msg2 = { 0 };
msg2.message_id = SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS;
msg2.from = __FILE__;
switch_core_session_receive_message(session, &msg2);
}
if (switch_core_session_receive_message(session, &msg) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't re-establsh media on %s\n", switch_channel_get_name(channel));
switch_core_session_rwunlock(session);
@@ -1368,11 +1376,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_
switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 250, NULL);
switch_yield(250000);
} else {
switch_status_t st;
switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL);
switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL);
st = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
}
if ((flags & SMF_REBRIDGE)
@@ -1963,28 +1970,61 @@ SWITCH_DECLARE(int) switch_ivr_set_xml_profile_data(switch_xml_t xml, switch_cal
}
switch_xml_set_txt_d(param, caller_profile->chan_name);
if (caller_profile->soft) {
profile_node_t *pn;
for (pn = caller_profile->soft; pn; pn = pn->next) {
if (!(param = switch_xml_add_child_d(xml, pn->var, off++))) {
return -1;
}
switch_xml_set_txt_d(param, pn->val);
}
}
return off;
}
static int switch_ivr_set_xml_chan_var(switch_xml_t xml, const char *var, const char *val, int off)
{
char *data;
switch_size_t dlen = strlen(val) * 3 + 1;
switch_xml_t variable;
if (!zstr(var) && !zstr(val) && ((variable = switch_xml_add_child_d(xml, var, off++)))) {
if ((data = malloc(dlen))) {
memset(data, 0, dlen);
switch_url_encode(val, data, dlen);
switch_xml_set_txt_d(variable, data);
free(data);
} else abort();
}
return off;
}
SWITCH_DECLARE(int) switch_ivr_set_xml_chan_vars(switch_xml_t xml, switch_channel_t *channel, int off)
{
switch_xml_t variable;
switch_event_header_t *hi = switch_channel_variable_first(channel);
if (!hi)
return off;
for (; hi; hi = hi->next) {
if (!zstr(hi->name) && !zstr(hi->value) && ((variable = switch_xml_add_child_d(xml, hi->name, off++)))) {
char *data;
switch_size_t dlen = strlen(hi->value) * 3 + 1;
if ((data = malloc(dlen))) {
memset(data, 0, dlen);
switch_url_encode(hi->value, data, dlen);
switch_xml_set_txt_d(variable, data);
free(data);
if (hi->idx) {
int i;
for (i = 0; i < hi->idx; i++) {
off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->array[i], off);
}
} else {
off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->value, off);
}
}
switch_channel_variable_last(channel);
@@ -2052,6 +2092,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_
goto error;
}
for (ap = app_log; ap; ap = ap->next) {
char tmp[128];
if (!(x_application = switch_xml_add_child_d(x_apps, "application", app_off++))) {
goto error;
@@ -2059,6 +2100,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_
switch_xml_set_attr_d(x_application, "app_name", ap->app);
switch_xml_set_attr_d(x_application, "app_data", ap->arg);
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, ap->stamp);
switch_xml_set_attr_d_buf(x_application, "app_stamp", tmp);
}
}
@@ -2228,6 +2272,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
switch_xml_set_txt_d(time_tag, tmp);
if (!(time_tag = switch_xml_add_child_d(x_times, "bridged_time", t_off++))) {
goto error;
}
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
switch_xml_set_txt_d(time_tag, tmp);
if (!(time_tag = switch_xml_add_child_d(x_times, "hangup_time", t_off++))) {
goto error;
}
@@ -2279,7 +2329,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3
switch_frame_t *read_frame, write_frame = { 0 };
switch_status_t status;
switch_channel_t *channel = switch_core_session_get_channel(session);
uint32_t interval, samples;
uint32_t interval;
uint32_t ts = 0;
switch_codec_implementation_t read_impl = { 0 };
switch_core_session_get_read_impl(session, &read_impl);
@@ -2291,7 +2341,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3
}
interval = read_impl.microseconds_per_packet / 1000;
samples = switch_samples_per_packet(read_impl.samples_per_second, interval);
//samples = switch_samples_per_packet(read_impl.samples_per_second, interval);
qlen = delay_ms / (interval);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting delay to %dms (%d frames)\n", delay_ms, qlen);
@@ -2333,25 +2383,42 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
switch_say_interface_t *si;
switch_channel_t *channel;
switch_status_t status = SWITCH_STATUS_FALSE;
const char *save_path = NULL, *chan_lang = NULL, *lang = NULL, *lname = NULL, *sound_path = NULL;
const char *save_path = NULL, *chan_lang = NULL, *lang = NULL, *sound_path = NULL;
switch_event_t *hint_data;
switch_xml_t cfg, xml = NULL, language, macros;
switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL;
char *p;
switch_assert(session);
channel = switch_core_session_get_channel(session);
switch_assert(channel);
lang = switch_channel_get_variable(channel, "language");
if (zstr(module_name)) {
module_name = "en";
}
if (!lang) {
chan_lang = switch_channel_get_variable(channel, "default_language");
if (!chan_lang) {
chan_lang = "en";
if (module_name) {
char *p;
p = switch_core_session_strdup(session, module_name);
module_name = p;
if ((p = strchr(module_name, ':'))) {
*p++ = '\0';
chan_lang = p;
}
}
if (!chan_lang) {
lang = switch_channel_get_variable(channel, "language");
if (!lang) {
chan_lang = switch_channel_get_variable(channel, "default_language");
if (!chan_lang) {
chan_lang = module_name;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
} else {
chan_lang = lang;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
} else {
chan_lang = lang;
}
switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS);
@@ -2361,50 +2428,33 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang);
switch_channel_event_set_data(channel, hint_data);
if (switch_xml_locate("phrases", NULL, NULL, NULL, &xml, &cfg, hint_data, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Open of phrases failed.\n");
if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, &macros, chan_lang) != SWITCH_STATUS_SUCCESS) {
goto done;
}
if (!(macros = switch_xml_child(cfg, "macros"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macros tag.\n");
goto done;
}
if (!(language = switch_xml_child(macros, "language"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language tag.\n");
goto done;
}
while (language) {
if ((lname = (char *) switch_xml_attr(language, "name")) && !strcasecmp(lname, chan_lang)) {
const char *tmp;
if ((tmp = switch_xml_attr(language, "module"))) {
module_name = tmp;
}
break;
}
language = language->next;
}
if (!language) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language %s.\n", chan_lang);
goto done;
}
if (!module_name) {
if ((p = (char *) switch_xml_attr(language, "say-module"))) {
module_name = switch_core_session_strdup(session, p);
} else if ((p = (char *) switch_xml_attr(language, "module"))) {
module_name = switch_core_session_strdup(session, p);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute\n");
} else {
module_name = chan_lang;
}
if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
sound_path = (char *) switch_xml_attr(language, "sound_path");
if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) {
if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
sound_path = (char *) switch_xml_attr(language, "sound_path");
}
}
save_path = switch_channel_get_variable(channel, "sound_prefix");
if (sound_path) {
switch_channel_set_variable(channel, "sound_prefix", sound_path);
if (channel) {
const char *p = switch_channel_get_variable(channel, "sound_prefix_enforced");
if (!switch_true(p)) {
save_path = switch_channel_get_variable(channel, "sound_prefix");
if (sound_path) {
switch_channel_set_variable(channel, "sound_prefix", sound_path);
}
}
}
if ((si = switch_loadable_module_get_say_interface(module_name))) {
@@ -2438,6 +2488,113 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
return status;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_say_string(switch_core_session_t *session,
const char *lang,
const char *ext,
const char *tosay,
const char *module_name,
const char *say_type,
const char *say_method,
const char *say_gender,
char **rstr)
{
switch_say_interface_t *si;
switch_channel_t *channel = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
const char *save_path = NULL, *chan_lang = NULL, *sound_path = NULL;
switch_event_t *hint_data;
switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL;
if (session) {
channel = switch_core_session_get_channel(session);
if (!lang) {
lang = switch_channel_get_variable(channel, "language");
if (!lang) {
chan_lang = switch_channel_get_variable(channel, "default_language");
if (!chan_lang) {
chan_lang = "en";
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
} else {
chan_lang = lang;
}
}
}
if (!lang) lang = "en";
if (!chan_lang) chan_lang = lang;
switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(hint_data);
switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "macro_name", "say_app");
switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang);
if (channel) {
switch_channel_event_set_data(channel, hint_data);
}
if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, &macros, chan_lang) != SWITCH_STATUS_SUCCESS) {
goto done;
}
if ((module_name = switch_xml_attr(language, "say-module"))) {
} else if ((module_name = switch_xml_attr(language, "module"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute\n");
} else {
module_name = chan_lang;
}
if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) {
if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
sound_path = (char *) switch_xml_attr(language, "sound_path");
}
}
if (channel) {
const char *p = switch_channel_get_variable(channel, "sound_prefix_enforced");
if (!switch_true(p)) {
save_path = switch_channel_get_variable(channel, "sound_prefix");
if (sound_path) {
switch_channel_set_variable(channel, "sound_prefix", sound_path);
}
}
}
if ((si = switch_loadable_module_get_say_interface(module_name))) {
/* should go back and proto all the say mods to const.... */
switch_say_args_t say_args = {0};
say_args.type = switch_ivr_get_say_type_by_name(say_type);
say_args.method = switch_ivr_get_say_method_by_name(say_method);
say_args.gender = switch_ivr_get_say_gender_by_name(say_gender);
say_args.ext = ext;
status = si->say_string_function(session, (char *) tosay, &say_args, rstr);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name);
status = SWITCH_STATUS_FALSE;
}
done:
if (hint_data) {
switch_event_destroy(&hint_data);
}
if (save_path && channel) {
switch_channel_set_variable(channel, "sound_prefix", save_path);
}
if (xml) {
switch_xml_free(xml);
}
return status;
}
static const char *get_prefixed_str(char *buffer, size_t buffer_size, const char *prefix, size_t prefix_size, const char *str)
{
size_t str_len;