提交 d5ef86d7 authored 作者: Anthony Minessale's avatar Anthony Minessale

introduce new say_string method of doing say and use it in mod_say_en as an…

introduce new say_string method of doing say and use it in mod_say_en as an example.  try: eval ${say_string en.gsm en current_date_time pronounced ${strepoch()}} from the cli with this patch.  We can do more to centralize the say things and go back and apply it to other langs, using this method you can set the desired file ext as well which I think is a bounty....
上级 1552ecf5
......@@ -145,6 +145,8 @@ SWITCH_DECLARE(int) switch_snprintf(_Out_z_cap_(len)
SWITCH_DECLARE(int) switch_vasprintf(_Out_opt_ char **buf, _In_z_ _Printf_format_string_ const char *format, _In_ va_list ap);
SWITCH_DECLARE(int) switch_vsnprintf(char *buf, switch_size_t len, const char *format, va_list ap);
SWITCH_DECLARE(char *) switch_copy_string(_Out_z_cap_(dst_size)
char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size);
......
......@@ -2240,6 +2240,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, c
*/
SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force);
SWITCH_DECLARE(char *) switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var);
SWITCH_DECLARE(char *) switch_say_file_handle_get_path(switch_say_file_handle_t *sh);
SWITCH_DECLARE(char *) switch_say_file_handle_detach_path(switch_say_file_handle_t *sh);
SWITCH_DECLARE(void) switch_say_file_handle_destroy(switch_say_file_handle_t **sh);
SWITCH_DECLARE(switch_status_t) switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event);
SWITCH_DECLARE(void) switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...);
SWITCH_END_EXTERN_C
#endif
/* For Emacs:
......
......@@ -859,6 +859,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
const char *say_gender,
switch_input_args_t *args);
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_DECLARE(switch_say_method_t) switch_ivr_get_say_method_by_name(const char *name);
SWITCH_DECLARE(switch_say_gender_t) switch_ivr_get_say_gender_by_name(const char *name);
SWITCH_DECLARE(switch_say_type_t) switch_ivr_get_say_type_by_name(const char *name);
......
......@@ -103,29 +103,9 @@ struct switch_stream_handle {
};
struct switch_io_event_hooks;
struct switch_say_file_handle;
typedef switch_call_cause_t (*switch_io_outgoing_channel_t)
typedef switch_call_cause_t (*switch_io_outgoing_channel_t)
(switch_core_session_t *, switch_event_t *, switch_caller_profile_t *, switch_core_session_t **, switch_memory_pool_t **, switch_originate_flag_t,
switch_call_cause_t *);
typedef switch_status_t (*switch_io_read_frame_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int);
......@@ -490,6 +470,7 @@ struct switch_say_interface {
const char *interface_name;
/*! function to pass down to the module */
switch_say_callback_t say_function;
switch_say_string_callback_t say_string_function;
switch_thread_rwlock_t *rwlock;
int refs;
switch_mutex_t *reflock;
......
......@@ -36,6 +36,7 @@
#define SWITCH_TYPES_H
#include <switch.h>
SWITCH_BEGIN_EXTERN_C
#define SWITCH_ENT_ORIGINATE_DELIM ":_:"
#define SWITCH_BLANK_STRING ""
......@@ -1735,6 +1736,7 @@ typedef switch_status_t (*switch_stream_handle_raw_write_function_t) (switch_str
typedef switch_status_t (*switch_api_function_t) (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session,
_In_ switch_stream_handle_t *stream);
#define SWITCH_STANDARD_API(name) static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream)
typedef switch_status_t (*switch_input_callback_function_t) (switch_core_session_t *session, void *input,
......@@ -1772,17 +1774,32 @@ typedef struct {
switch_ivr_dmachine_t *dmachine;
} switch_input_args_t;
typedef struct {
switch_say_type_t type;
switch_say_method_t method;
switch_say_gender_t gender;
const char *ext;
} switch_say_args_t;
typedef switch_status_t (*switch_say_callback_t) (switch_core_session_t *session,
char *tosay,
switch_say_args_t *say_args,
switch_input_args_t *args);
typedef switch_status_t (*switch_say_string_callback_t) (switch_core_session_t *session,
char *tosay,
switch_say_args_t *say_args, char **rstr);
struct switch_say_file_handle;
typedef struct switch_say_file_handle switch_say_file_handle_t;
typedef switch_status_t (*switch_new_say_callback_t) (switch_say_file_handle_t *sh,
char *tosay,
switch_say_args_t *say_args);
typedef struct switch_xml *switch_xml_t;
typedef struct switch_core_time_duration switch_core_time_duration_t;
typedef switch_xml_t(*switch_xml_search_function_t) (const char *section,
......
......@@ -116,6 +116,59 @@ static switch_status_t select_url(const char *user,
return SWITCH_STATUS_SUCCESS;
}
#define SAY_STRING_SYNTAX "<module_name>[.<ext>] <lang>[.<ext>] <say_type> <say_method> [<say_gender>] <text>"
SWITCH_STANDARD_API(say_string_function)
{
char *argv[6] = { 0 };
int argc;
char *lbuf = NULL, *string = NULL;
int err = 1, par = 0;
char *p, *ext = "wav";
if (cmd) {
lbuf = strdup(cmd);
}
if (lbuf && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) && (argc == 5 || argc == 6)) {
if ((p = strchr(argv[0], '.'))) {
*p++ = '\0';
ext = p;
par++;
}
if (!par && (p = strchr(argv[1], '.'))) {
*p++ = '\0';
ext = p;
}
switch_ivr_say_string(session,
argv[1],
ext,
(argc == 5) ? argv[4] : argv[5],
argv[0],
argv[2],
argv[3],
(argc == 6) ? argv[4] : NULL ,
&string);
if (string) {
stream->write_function(stream, "%s", string);
free(string);
err = 0;
}
}
if (err) {
stream->write_function(stream, "-ERR Usage: %s\n", SAY_STRING_SYNTAX);
}
free(lbuf);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(reg_url_function)
{
char *data;
......@@ -5105,6 +5158,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "reload", "Reload Module", reload_function, UNLOAD_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "reloadxml", "Reload XML", reload_xml_function, "");
SWITCH_ADD_API(commands_api_interface, "replace", "replace a string", replace_function, "<data>|<string1>|<string2>");
SWITCH_ADD_API(commands_api_interface, "say_string", "", say_string_function, SAY_STRING_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "sched_api", "Schedule an api command", sched_api_function, SCHED_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "sched_broadcast", "Schedule a broadcast event to a running call", sched_broadcast_function,
SCHED_BROADCAST_SYNTAX);
......
......@@ -2943,7 +2943,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
char *data, *indup, *endof_indup;
size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
char *cloned_sub_val = NULL, *sub_val = NULL;
char *func_val = NULL;
char *func_val = NULL, *sb = NULL;
int nv = 0;
if (zstr(in)) {
......@@ -3033,8 +3033,19 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
}
p = e > endof_indup ? endof_indup : e;
if ((vval = strchr(vname, '(')) || (vval = strchr(vname, ' '))) {
if (*vval == '(') br = 1;
vval = NULL;
for(sb = vname; sb && *sb; sb++) {
if (*sb == ' ') {
vval = sb;
break;
} else if (*sb == '(') {
vval = sb;
br = 1;
break;
}
}
if (vval) {
e = vval - 1;
*vval++ = '\0';
while (*e == ' ') {
......
......@@ -1563,7 +1563,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
char *cloned_sub_val = NULL;
char *func_val = NULL;
int nv = 0;
char *gvar = NULL;
char *gvar = NULL, *sb = NULL;
if (zstr(in)) {
return (char *) in;
......@@ -1651,10 +1651,22 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
}
p = e > endof_indup ? endof_indup : e;
if ((vval = strchr(vname, '(')) || (vval = strchr(vname, ' '))) {
if (*vval == '(') br = 1;
vval = NULL;
for(sb = vname; sb && *sb; sb++) {
if (*sb == ' ') {
vval = sb;
break;
} else if (*sb == '(') {
vval = sb;
br = 1;
break;
}
}
if (vval) {
e = vval - 1;
*vval++ = '\0';
while (*e == ' ') {
*e-- = '\0';
}
......
......@@ -2432,6 +2432,134 @@ 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, *lname = NULL, *sound_path = NULL;
switch_event_t *hint_data;
switch_xml_t cfg, xml = NULL, language, macros;
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("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");
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) {
module_name = chan_lang;
}
if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
sound_path = (char *) switch_xml_attr(language, "sound_path");
}
if (channel) {
save_path = switch_channel_get_variable(channel, "sound_prefix");
}
if (sound_path && channel) {
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;
......
......@@ -1918,6 +1918,97 @@ SWITCH_DECLARE(void *) switch_loadable_module_create_interface(switch_loadable_m
}
}
struct switch_say_file_handle {
char *ext;
int cnt;
struct switch_stream_handle stream;
switch_event_t *param_event;
};
SWITCH_DECLARE(char *) switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var)
{
char *ret = NULL;
if (sh->param_event) {
ret = switch_event_get_header(sh->param_event, var);
}
return ret;
}
SWITCH_DECLARE(char *) switch_say_file_handle_get_path(switch_say_file_handle_t *sh)
{
return (char *) sh->stream.data;
}
SWITCH_DECLARE(char *) switch_say_file_handle_detach_path(switch_say_file_handle_t *sh)
{
char *path;
switch_assert(sh);
path = (char *) sh->stream.data;
sh->stream.data = NULL;
return path;
}
SWITCH_DECLARE(void) switch_say_file_handle_destroy(switch_say_file_handle_t **sh)
{
switch_assert(sh);
switch_safe_free((*sh)->stream.data);
switch_safe_free((*sh)->ext);
if ((*sh)->param_event) {
switch_event_destroy(&(*sh)->param_event);
}
free(*sh);
*sh = NULL;
}
SWITCH_DECLARE(switch_status_t) switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event)
{
switch_assert(sh);
*sh = malloc(sizeof(**sh));
memset(*sh, 0, sizeof(**sh));
SWITCH_STANDARD_STREAM((*sh)->stream);
if (var_event) {
(*sh)->param_event = *var_event;
*var_event = NULL;
}
(*sh)->ext = strdup(ext);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(void) switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...)
{
char buf[256] = "";
int ret;
va_list ap;
va_start(ap, fmt);
if ((ret = switch_vsnprintf(buf, sizeof(buf), fmt, ap)) > 0) {
if (!sh->cnt++) {
sh->stream.write_function(&sh->stream, "file_string://%s.%s", buf, sh->ext);
} else {
sh->stream.write_function(&sh->stream, "!%s.%s", buf, sh->ext);
}
}
va_end(ap);
}
/* For Emacs:
* Local Variables:
* mode:c
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论