add pelim say stuff, module framework, xml parser, dialplan app, and add new channel var called sound_prefix for audio files
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3766 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
9db9fae8a2
commit
b7dbea6407
|
@ -632,6 +632,43 @@
|
|||
</user>
|
||||
</domain>
|
||||
</section>
|
||||
|
||||
<!-- phrases section (under development still) -->
|
||||
<section name="phrases" description="Speech Phrase Management">
|
||||
<macros>
|
||||
<language name="en" sound_path="/snds" tts_engine="cepstral" tts_voice="david">
|
||||
<macro name="msgcount">
|
||||
<input pattern="(.*)">
|
||||
<action function="execute" data="sleep(1000)"/>
|
||||
<action function="play-file" data="vm-youhave.wav"/>
|
||||
<action function="say" data="$1" method="pronounced" type="items"/>
|
||||
<action function="play-file" data="vm-messages.wav"/>
|
||||
<!-- or -->
|
||||
<!--<action function="speak-text" data="you have $1 messages"/>-->
|
||||
</input>
|
||||
</macro>
|
||||
<macro name="timeleft">
|
||||
<input pattern="(\d+):(\d+)">
|
||||
<action function="speak-text" data="You have $1 minutes, $2 seconds remaining"/>
|
||||
</input>
|
||||
</macro>
|
||||
</language>
|
||||
<language name="fr" sound_path="/var/sounds/lang/fr/jean" tts_engine="cepstral" tts_voice="jean-pierre">
|
||||
<macro name="msgcount">
|
||||
<input pattern="(.*)">
|
||||
<action function="play-file" data="tuas.wav"/>
|
||||
<action function="say" data="$1" method="pronounced" type="items"/>
|
||||
<action function="play-file" data="messages.wav"/>
|
||||
</input>
|
||||
</macro>
|
||||
<macro name="timeleft">
|
||||
<input pattern="(\d+):(\d+)">
|
||||
<action function="speak-text" data="il y a $1 minutes et de $2 secondes de restant"/>
|
||||
</input>
|
||||
</macro>
|
||||
</language>
|
||||
</macros>
|
||||
</section>
|
||||
</document>
|
||||
|
||||
|
||||
|
|
|
@ -626,6 +626,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_menu_stack_xml_add_custom(switch_ivr_
|
|||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_stack_xml_init(switch_ivr_menu_xml_ctx_t **xml_menu_ctx, switch_memory_pool_t *pool);
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro(switch_core_session_t *session,
|
||||
char *macro_name,
|
||||
char *data,
|
||||
char *lang,
|
||||
switch_input_callback_function_t input_callback,
|
||||
void *buf,
|
||||
uint32_t buflen);
|
||||
/** @} */
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
|
|
|
@ -75,6 +75,8 @@ struct switch_loadable_module_interface {
|
|||
const switch_directory_interface_t *directory_interface;
|
||||
/*! the table of chat interfaces the module has implmented */
|
||||
const switch_chat_interface_t *chat_interface;
|
||||
/*! the table of say interfaces the module has implmented */
|
||||
const switch_say_interface_t *say_interface;
|
||||
/*! the table of asr interfaces the module has implmented */
|
||||
const switch_asr_interface_t *asr_interface;
|
||||
};
|
||||
|
@ -181,6 +183,13 @@ SWITCH_DECLARE(switch_directory_interface_t *) switch_loadable_module_get_direct
|
|||
*/
|
||||
SWITCH_DECLARE(switch_chat_interface_t *) switch_loadable_module_get_chat_interface(char *name);
|
||||
|
||||
/*!
|
||||
\brief Retrieve the say interface by it's registered name
|
||||
\param name the name of the say interface
|
||||
\return the desired say interface
|
||||
*/
|
||||
SWITCH_DECLARE(switch_say_interface_t *) switch_loadable_module_get_say_interface(char *name);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Retrieve the list of loaded codecs into an array
|
||||
|
|
|
@ -412,6 +412,20 @@ struct switch_speech_handle {
|
|||
void *private_info;
|
||||
};
|
||||
|
||||
/*! \brief Abstract interface to a say module */
|
||||
struct switch_say_interface {
|
||||
/*! the name of the interface */
|
||||
const char *interface_name;
|
||||
/*! function to pass down to the module */
|
||||
switch_status_t (*say_function)(switch_core_session_t *session,
|
||||
char *tosay,
|
||||
switch_say_type_t type,
|
||||
switch_say_method_t method,
|
||||
switch_input_callback_function_t dtmf_callback,
|
||||
void *buf,
|
||||
uint32_t buflen);
|
||||
const struct switch_say_interface *next;
|
||||
};
|
||||
|
||||
/*! \brief Abstract interface to a chat module */
|
||||
struct switch_chat_interface {
|
||||
|
|
|
@ -93,6 +93,33 @@ SWITCH_BEGIN_EXTERN_C
|
|||
#define SWITCH_BITS_PER_BYTE 8
|
||||
typedef uint8_t switch_byte_t;
|
||||
|
||||
typedef enum {
|
||||
SSM_NA,
|
||||
SSM_PRONOUNCED,
|
||||
SSM_ITERATED
|
||||
} switch_say_method_t;
|
||||
|
||||
typedef enum {
|
||||
SST_NUMBER,
|
||||
SST_ITEMS,
|
||||
SST_PERSONS,
|
||||
SST_MESSAGES,
|
||||
SST_CURRENCY,
|
||||
SST_TIME_MEASUREMENT,
|
||||
SST_CURRENT_DATE,
|
||||
SST_CURRENT_TIME,
|
||||
SST_CURRENT_DATE_TIME,
|
||||
SST_TELEPHONE_NUMBER,
|
||||
SST_TELEPHONE_EXTENSION,
|
||||
SST_URL,
|
||||
SST_EMAIL_ADDRESS,
|
||||
SST_POSTAL_ADDRESS,
|
||||
SST_ACCOUNT_NUMBER,
|
||||
SST_NAME_SPELLED,
|
||||
SST_NAME_PHONETIC,
|
||||
} switch_say_type_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SMF_NONE = 0,
|
||||
SMF_REBRIDGE = (1 << 0),
|
||||
|
@ -172,7 +199,8 @@ typedef enum {
|
|||
SWITCH_XML_SECTION_RESULT = 0,
|
||||
SWITCH_XML_SECTION_CONFIG = (1 << 0),
|
||||
SWITCH_XML_SECTION_DIRECTORY = (1 << 1),
|
||||
SWITCH_XML_SECTION_DIALPLAN = (1 << 2)
|
||||
SWITCH_XML_SECTION_DIALPLAN = (1 << 2),
|
||||
SWITCH_XML_SECTION_PHRASES = (1 << 3)
|
||||
} switch_xml_section_t;
|
||||
|
||||
/*!
|
||||
|
@ -863,6 +891,7 @@ typedef struct switch_speech_interface switch_speech_interface_t;
|
|||
typedef struct switch_asr_interface switch_asr_interface_t;
|
||||
typedef struct switch_directory_interface switch_directory_interface_t;
|
||||
typedef struct switch_chat_interface switch_chat_interface_t;
|
||||
typedef struct switch_say_interface switch_say_interface_t;
|
||||
typedef struct switch_core_port_allocator switch_core_port_allocator_t;
|
||||
typedef struct switch_media_bug switch_media_bug_t;
|
||||
typedef void (*switch_media_bug_callback_t)(switch_media_bug_t *, void *, switch_abc_type_t);
|
||||
|
|
|
@ -102,6 +102,32 @@ static void eval_function(switch_core_session_t *session, char *data)
|
|||
return;
|
||||
}
|
||||
|
||||
static void phrase_function(switch_core_session_t *session, char *data)
|
||||
{
|
||||
switch_channel_t *channel;
|
||||
char *mydata = NULL;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
if ((mydata = switch_core_session_strdup(session, data))) {
|
||||
char *lang;
|
||||
char *macro = mydata;
|
||||
char *mdata = NULL;
|
||||
|
||||
if ((mdata = strchr(macro, ','))) {
|
||||
*mdata++ = '\0';
|
||||
}
|
||||
if (!(lang = switch_channel_get_variable(channel, "language"))) {
|
||||
lang = "en";
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Execute %s(%s) lang %s\n", macro, mdata, lang);
|
||||
switch_ivr_phrase_macro(session, macro, mdata, lang, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void answer_function(switch_core_session_t *session, char *data)
|
||||
{
|
||||
switch_channel_t *channel;
|
||||
|
@ -462,13 +488,23 @@ static const switch_application_interface_t eval_application_interface = {
|
|||
|
||||
};
|
||||
|
||||
static const switch_application_interface_t phrase_application_interface = {
|
||||
/*.interface_name */ "phrase",
|
||||
/*.application_function */ phrase_function,
|
||||
/* long_desc */ "Say a Phrase",
|
||||
/* short_desc */ "Say a Phrase",
|
||||
/* syntax */ "<macro_name>,<data>",
|
||||
/*.next */ &eval_application_interface
|
||||
|
||||
};
|
||||
|
||||
static const switch_application_interface_t strftime_application_interface = {
|
||||
/*.interface_name */ "strftime",
|
||||
/*.application_function */ strftime_function,
|
||||
/* long_desc */ NULL,
|
||||
/* short_desc */ NULL,
|
||||
/* syntax */ NULL,
|
||||
/*.next */ &eval_application_interface
|
||||
/*.next */ &phrase_application_interface
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* mod_say_en.c -- Say for English
|
||||
*
|
||||
*/
|
||||
#include <switch.h>
|
||||
#include <math.h>
|
||||
|
||||
static const char modname[] = "mod_say_en";
|
||||
|
||||
static switch_status_t en_say(switch_core_session_t *session,
|
||||
char *tosay,
|
||||
switch_say_type_t type,
|
||||
switch_say_method_t method,
|
||||
switch_input_callback_function_t input_callback,
|
||||
void *buf,
|
||||
uint32_t buflen)
|
||||
{
|
||||
switch_channel_t *channel;
|
||||
|
||||
assert(session != NULL);
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
switch(type) {
|
||||
case SST_NUMBER:
|
||||
case SST_ITEMS:
|
||||
case SST_PERSONS:
|
||||
case SST_MESSAGES:
|
||||
{
|
||||
int in;
|
||||
int x, places[7] = {0};
|
||||
char tmp[25];
|
||||
|
||||
in = atoi(tosay);
|
||||
|
||||
for(x = 6; x >= 0; x--) {
|
||||
int num = pow(10, x);
|
||||
if ((places[x] = in / num)) {
|
||||
in -= places[x] * num;
|
||||
}
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case SSM_PRONOUNCED:
|
||||
if (places[6]) {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d.wav", places[6]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
switch_ivr_play_file(session, NULL, "digits/million.wav", NULL, input_callback, buf, buflen);
|
||||
}
|
||||
|
||||
if (places[5]) {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d.wav", places[5]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
switch_ivr_play_file(session, NULL, "digits/hundred.wav", NULL, input_callback, buf, buflen);
|
||||
}
|
||||
|
||||
if (places[4]) {
|
||||
if (places[4] > 1) {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d0.wav", places[4]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d%d.wav", places[4], places[3]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
places[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (places[3]) {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d.wav", places[3]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
}
|
||||
|
||||
if (places[4] || places[3]) {
|
||||
switch_ivr_play_file(session, NULL, "digits/thousand.wav", NULL, input_callback, buf, buflen);
|
||||
}
|
||||
|
||||
if (places[2]) {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d.wav", places[2]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
switch_ivr_play_file(session, NULL, "digits/hundred.wav", NULL, input_callback, buf, buflen);
|
||||
}
|
||||
|
||||
if (places[1]) {
|
||||
if (places[1] > 1) {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d0.wav", places[1]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d%d.wav", places[1], places[0]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
places[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (places[0]) {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d.wav", places[0]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
}
|
||||
|
||||
break;
|
||||
case SSM_ITERATED:
|
||||
for(x = 7; x >= 0; x--) {
|
||||
if (places[x]) {
|
||||
snprintf(tmp, sizeof(tmp), "digits/%d.wav", places[x]);
|
||||
switch_ivr_play_file(session, NULL, tmp, NULL, input_callback, buf, buflen);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Finish ME!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const switch_chat_interface_t en_say_interface= {
|
||||
/*.name */ "en",
|
||||
/*.say_function */ en_say,
|
||||
};
|
||||
|
||||
static switch_loadable_module_interface_t say_en_module_interface = {
|
||||
/*.module_name */ modname,
|
||||
/*.endpoint_interface */ NULL,
|
||||
/*.timer_interface */ NULL,
|
||||
/*.dialplan_interface */ NULL,
|
||||
/*.codec_interface */ NULL,
|
||||
/*.application_interface */ NULL,
|
||||
/*.api_interface */ NULL,
|
||||
/*.file_interface */ NULL,
|
||||
/*.speech_interface */ NULL,
|
||||
/*.directory_interface */ NULL,
|
||||
/*.chat_interface */ NULL,
|
||||
/*.say_inteface*/ &en_say_interface,
|
||||
/*.asr_interface*/ NULL
|
||||
};
|
||||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
|
||||
{
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = &say_en_module_interface;
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
246
src/switch_ivr.c
246
src/switch_ivr.c
|
@ -977,8 +977,23 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
|||
char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
|
||||
uint8_t asis = 0;
|
||||
char *ext;
|
||||
char *prefix;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
prefix = switch_channel_get_variable(channel, "sound_prefix");
|
||||
|
||||
if (file) {
|
||||
if (prefix && *file != '/' && *file != '\\' && *(file+1) != ':') {
|
||||
char *new_file;
|
||||
uint32_t len;
|
||||
len = (uint32_t)strlen(file) + (uint32_t)strlen(prefix) + 10;
|
||||
new_file = switch_core_session_alloc(session, len);
|
||||
snprintf(new_file, len, "%s/%s", prefix, file);
|
||||
file = new_file;
|
||||
}
|
||||
|
||||
if ((ext = strrchr(file, '.'))) {
|
||||
ext++;
|
||||
} else {
|
||||
|
@ -1004,10 +1019,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
|||
fh->samples = 0;
|
||||
}
|
||||
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
if (switch_core_file_open(fh,
|
||||
file,
|
||||
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
|
||||
|
@ -1054,7 +1065,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
|||
date = (char *) switch_core_session_strdup(session, (char *)p);
|
||||
switch_channel_set_variable(channel, "RECORD_DATE", (char *)p);
|
||||
}
|
||||
|
||||
#if 0
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"OPEN FILE %s %uhz %u channels\n"
|
||||
"TITLE=%s\n"
|
||||
|
@ -1069,6 +1080,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
|||
artist,
|
||||
comment,
|
||||
date);
|
||||
#endif
|
||||
|
||||
assert(read_codec != NULL);
|
||||
interval = read_codec->implementation->microseconds_per_frame / 1000;
|
||||
|
@ -4336,6 +4348,230 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_menu_stack_xml_build(switch_ivr_menu_
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
static char *SAY_METHOD_NAMES[] = {
|
||||
"N/A",
|
||||
"PRONOUNCED",
|
||||
"ITERATED",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *SAY_TYPE_NAMES[] = {
|
||||
"NUMBER",
|
||||
"ITEMS",
|
||||
"PERSONS",
|
||||
"MESSAGES",
|
||||
"CURRENCY",
|
||||
"TIME_MEASUREMENT",
|
||||
"CURRENT_DATE",
|
||||
"CURRENT_TIME",
|
||||
"CURRENT_DATE_TIME",
|
||||
"TELEPHONE_NUMBER",
|
||||
"TELEPHONE_EXTENSION",
|
||||
"URL",
|
||||
"EMAIL_ADDRESS",
|
||||
"POSTAL_ADDRESS",
|
||||
"ACCOUNT_NUMBER",
|
||||
"NAME_SPELLED",
|
||||
"NAME_PHONETIC",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static switch_say_method_t get_say_method_by_name(char *name)
|
||||
{
|
||||
int x = 0;
|
||||
for (x = 0; SAY_METHOD_NAMES[x]; x++) {
|
||||
if (!strcasecmp(SAY_METHOD_NAMES[x], name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (switch_say_method_t) x;
|
||||
}
|
||||
|
||||
static switch_say_method_t get_say_type_by_name(char *name)
|
||||
{
|
||||
int x = 0;
|
||||
for (x = 0; SAY_TYPE_NAMES[x]; x++) {
|
||||
if (!strcasecmp(SAY_TYPE_NAMES[x], name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (switch_say_method_t) x;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro(switch_core_session_t *session,
|
||||
char *macro_name,
|
||||
char *data,
|
||||
char *lang,
|
||||
switch_input_callback_function_t input_callback,
|
||||
void *buf,
|
||||
uint32_t buflen)
|
||||
{
|
||||
switch_xml_t cfg, xml = NULL, language, macros, macro, input, action;
|
||||
char *lname = NULL, *mname = NULL, hint_data[1024] = "", enc_hint[1024] = "";
|
||||
switch_status_t status = SWITCH_STATUS_GENERR;
|
||||
char *old_sound_prefix, *sound_path = NULL, *tts_engine = NULL, *tts_voice = NULL;
|
||||
switch_channel_t *channel;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
switch_url_encode(data, enc_hint, sizeof(enc_hint));
|
||||
snprintf(hint_data, sizeof(hint_data), "macro_name=%s&lang=%s&data=%s", macro_name, lang, enc_hint);
|
||||
|
||||
if (switch_xml_locate("phrases", NULL, NULL, NULL, &xml, &cfg, hint_data) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of phrases failed.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(macros = switch_xml_child(cfg, "macros"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "can't find macros tag.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(language = switch_xml_child(macros, "language"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "can't find language tag.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
while(language) {
|
||||
if ((lname = switch_xml_attr(language, "name")) && !strcasecmp(lname, lang)) {
|
||||
break;
|
||||
}
|
||||
language = language->next;
|
||||
}
|
||||
|
||||
if (!language) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "can't find language %s.\n", lang);
|
||||
goto done;
|
||||
}
|
||||
|
||||
sound_path = switch_xml_attr_soft(language, "sound_path");
|
||||
tts_engine = switch_xml_attr_soft(language, "tts_engine");
|
||||
tts_voice = switch_xml_attr_soft(language, "tts_voice");
|
||||
|
||||
old_sound_prefix = switch_channel_get_variable(channel, "sound_prefix");
|
||||
switch_channel_set_variable(channel, "sound_prefix", sound_path);
|
||||
|
||||
if (!(macro = switch_xml_child(language, "macro"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "can't find any macro tags.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
while(macro) {
|
||||
if ((mname = switch_xml_attr(macro, "name")) && !strcasecmp(mname, macro_name)) {
|
||||
break;
|
||||
}
|
||||
macro = macro->next;
|
||||
}
|
||||
|
||||
if (!macro) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "can't find macro %s.\n", macro_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(input = switch_xml_child(macro, "input"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "can't find any input tags.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch_channel_pre_answer(channel);
|
||||
|
||||
while(input) {
|
||||
char *pattern = switch_xml_attr(input, "pattern");
|
||||
|
||||
if (pattern) {
|
||||
pcre *re = NULL;
|
||||
int proceed = 0, ovector[30];
|
||||
char substituted[1024] = "";
|
||||
char *odata = NULL;
|
||||
|
||||
if ((proceed = switch_perform_regex(data, pattern, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
|
||||
for (action = switch_xml_child(input, "action"); action; action = action->next) {
|
||||
char *adata = switch_xml_attr_soft(action, "data");
|
||||
char *func = switch_xml_attr_soft(action, "function");
|
||||
|
||||
if (strchr(pattern, '(') && strchr(adata, '$')) {
|
||||
switch_perform_substitution(re, proceed, adata, data, substituted, sizeof(substituted), ovector);
|
||||
odata = substituted;
|
||||
} else {
|
||||
odata = adata;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Handle %s:[%s] (%s)\n", func, odata, lang);
|
||||
|
||||
if (!strcasecmp(func, "play-file")) {
|
||||
switch_ivr_play_file(session, NULL, odata, NULL, input_callback, buf, buflen);
|
||||
} else if (!strcasecmp(func, "execute")) {
|
||||
const switch_application_interface_t *application_interface;
|
||||
char *app_name = NULL;
|
||||
char *app_arg = NULL;
|
||||
|
||||
if ((app_name = strdup(odata))) {
|
||||
char *e = NULL;
|
||||
if ((app_arg = strchr(app_name, '('))) {
|
||||
*app_arg++ = '\0';
|
||||
if ((e = strchr(app_arg, ')'))) {
|
||||
*e = '\0';
|
||||
}
|
||||
if (app_name && app_arg && e && (application_interface = switch_loadable_module_get_application_interface(app_name))) {
|
||||
if (application_interface->application_function) {
|
||||
application_interface->application_function(session, app_arg);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application!\n");
|
||||
}
|
||||
}
|
||||
switch_safe_free(app_name);
|
||||
}
|
||||
} else if (!strcasecmp(func, "say")) {
|
||||
switch_say_interface_t *si;
|
||||
if ((si = switch_loadable_module_get_say_interface(lang))) {
|
||||
char *say_type = switch_xml_attr_soft(action, "type");
|
||||
char *say_method = switch_xml_attr_soft(action, "method");
|
||||
|
||||
si->say_function(session, odata, get_say_type_by_name(say_type), get_say_method_by_name(say_method), input_callback, buf, buflen);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invaid SAY Interface [%s]!\n", lang);
|
||||
}
|
||||
} else if (!strcasecmp(func, "speak-text")) {
|
||||
switch_codec_t *read_codec;
|
||||
if ((read_codec = switch_core_session_get_read_codec(session))) {
|
||||
switch_ivr_speak_text(session,
|
||||
tts_engine,
|
||||
tts_voice,
|
||||
NULL,
|
||||
read_codec->implementation->samples_per_second,
|
||||
input_callback,
|
||||
odata,
|
||||
buf,
|
||||
buflen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_clean_re(re);
|
||||
}
|
||||
|
||||
input = input->next;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
switch_channel_set_variable(channel, "sound_prefix", old_sound_prefix);
|
||||
|
||||
if (xml) {
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
|
|
@ -54,6 +54,7 @@ struct switch_loadable_module_container {
|
|||
switch_hash_t *asr_hash;
|
||||
switch_hash_t *directory_hash;
|
||||
switch_hash_t *chat_hash;
|
||||
switch_hash_t *say_hash;
|
||||
switch_memory_pool_t *pool;
|
||||
};
|
||||
|
||||
|
@ -260,6 +261,20 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable
|
|||
switch_core_hash_insert(loadable_modules.chat_hash, (char *) ptr->interface_name, (void *) ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_module->module_interface->say_interface) {
|
||||
const switch_say_interface_t *ptr;
|
||||
|
||||
for (ptr = new_module->module_interface->say_interface; ptr; ptr = ptr->next) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Say interface '%s'\n", ptr->interface_name);
|
||||
if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "say");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
switch_core_hash_insert(loadable_modules.say_hash, (char *) ptr->interface_name, (void *) ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -506,6 +521,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
|
|||
switch_core_hash_init(&loadable_modules.asr_hash, loadable_modules.pool);
|
||||
switch_core_hash_init(&loadable_modules.directory_hash, loadable_modules.pool);
|
||||
switch_core_hash_init(&loadable_modules.chat_hash, loadable_modules.pool);
|
||||
switch_core_hash_init(&loadable_modules.say_hash, loadable_modules.pool);
|
||||
switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool);
|
||||
|
||||
if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
|
||||
|
@ -683,6 +699,11 @@ SWITCH_DECLARE(switch_chat_interface_t *) switch_loadable_module_get_chat_interf
|
|||
return switch_core_hash_find(loadable_modules.chat_hash, name);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_say_interface_t *) switch_loadable_module_get_say_interface(char *name)
|
||||
{
|
||||
return switch_core_hash_find(loadable_modules.say_hash, name);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool, const switch_codec_implementation_t **array,
|
||||
int arraylen)
|
||||
{
|
||||
|
|
|
@ -107,6 +107,7 @@ static struct xml_section_t SECTIONS[] = {
|
|||
{ "config", SWITCH_XML_SECTION_CONFIG},
|
||||
{ "directory", SWITCH_XML_SECTION_DIRECTORY},
|
||||
{ "dialplan", SWITCH_XML_SECTION_DIALPLAN},
|
||||
{ "phrases", SWITCH_XML_SECTION_PHRASES},
|
||||
{ NULL, 0}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue