mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-31 02:33:44 +00:00
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>
|
</user>
|
||||||
</domain>
|
</domain>
|
||||||
</section>
|
</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>
|
</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_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
|
SWITCH_END_EXTERN_C
|
||||||
|
@ -75,6 +75,8 @@ struct switch_loadable_module_interface {
|
|||||||
const switch_directory_interface_t *directory_interface;
|
const switch_directory_interface_t *directory_interface;
|
||||||
/*! the table of chat interfaces the module has implmented */
|
/*! the table of chat interfaces the module has implmented */
|
||||||
const switch_chat_interface_t *chat_interface;
|
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 */
|
/*! the table of asr interfaces the module has implmented */
|
||||||
const switch_asr_interface_t *asr_interface;
|
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);
|
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
|
\brief Retrieve the list of loaded codecs into an array
|
||||||
|
@ -412,6 +412,20 @@ struct switch_speech_handle {
|
|||||||
void *private_info;
|
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 */
|
/*! \brief Abstract interface to a chat module */
|
||||||
struct switch_chat_interface {
|
struct switch_chat_interface {
|
||||||
|
@ -93,6 +93,33 @@ SWITCH_BEGIN_EXTERN_C
|
|||||||
#define SWITCH_BITS_PER_BYTE 8
|
#define SWITCH_BITS_PER_BYTE 8
|
||||||
typedef uint8_t switch_byte_t;
|
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 {
|
typedef enum {
|
||||||
SMF_NONE = 0,
|
SMF_NONE = 0,
|
||||||
SMF_REBRIDGE = (1 << 0),
|
SMF_REBRIDGE = (1 << 0),
|
||||||
@ -172,7 +199,8 @@ typedef enum {
|
|||||||
SWITCH_XML_SECTION_RESULT = 0,
|
SWITCH_XML_SECTION_RESULT = 0,
|
||||||
SWITCH_XML_SECTION_CONFIG = (1 << 0),
|
SWITCH_XML_SECTION_CONFIG = (1 << 0),
|
||||||
SWITCH_XML_SECTION_DIRECTORY = (1 << 1),
|
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;
|
} 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_asr_interface switch_asr_interface_t;
|
||||||
typedef struct switch_directory_interface switch_directory_interface_t;
|
typedef struct switch_directory_interface switch_directory_interface_t;
|
||||||
typedef struct switch_chat_interface switch_chat_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_core_port_allocator switch_core_port_allocator_t;
|
||||||
typedef struct switch_media_bug switch_media_bug_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);
|
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;
|
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)
|
static void answer_function(switch_core_session_t *session, char *data)
|
||||||
{
|
{
|
||||||
switch_channel_t *channel;
|
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 = {
|
static const switch_application_interface_t strftime_application_interface = {
|
||||||
/*.interface_name */ "strftime",
|
/*.interface_name */ "strftime",
|
||||||
/*.application_function */ strftime_function,
|
/*.application_function */ strftime_function,
|
||||||
/* long_desc */ NULL,
|
/* long_desc */ NULL,
|
||||||
/* short_desc */ NULL,
|
/* short_desc */ NULL,
|
||||||
/* syntax */ NULL,
|
/* syntax */ NULL,
|
||||||
/*.next */ &eval_application_interface
|
/*.next */ &phrase_application_interface
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
178
src/mod/say/mod_say_en/mod_say_en.c
Normal file
178
src/mod/say/mod_say_en/mod_say_en.c
Normal file
@ -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 = "";
|
char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
|
||||||
uint8_t asis = 0;
|
uint8_t asis = 0;
|
||||||
char *ext;
|
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 (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, '.'))) {
|
if ((ext = strrchr(file, '.'))) {
|
||||||
ext++;
|
ext++;
|
||||||
} else {
|
} else {
|
||||||
@ -1004,10 +1019,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
|||||||
fh->samples = 0;
|
fh->samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(session);
|
|
||||||
assert(channel != NULL);
|
|
||||||
|
|
||||||
if (switch_core_file_open(fh,
|
if (switch_core_file_open(fh,
|
||||||
file,
|
file,
|
||||||
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
|
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);
|
date = (char *) switch_core_session_strdup(session, (char *)p);
|
||||||
switch_channel_set_variable(channel, "RECORD_DATE", (char *)p);
|
switch_channel_set_variable(channel, "RECORD_DATE", (char *)p);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||||
"OPEN FILE %s %uhz %u channels\n"
|
"OPEN FILE %s %uhz %u channels\n"
|
||||||
"TITLE=%s\n"
|
"TITLE=%s\n"
|
||||||
@ -1069,6 +1080,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
|||||||
artist,
|
artist,
|
||||||
comment,
|
comment,
|
||||||
date);
|
date);
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(read_codec != NULL);
|
assert(read_codec != NULL);
|
||||||
interval = read_codec->implementation->microseconds_per_frame / 1000;
|
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;
|
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:
|
/* For Emacs:
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* mode:c
|
* mode:c
|
||||||
|
@ -54,6 +54,7 @@ struct switch_loadable_module_container {
|
|||||||
switch_hash_t *asr_hash;
|
switch_hash_t *asr_hash;
|
||||||
switch_hash_t *directory_hash;
|
switch_hash_t *directory_hash;
|
||||||
switch_hash_t *chat_hash;
|
switch_hash_t *chat_hash;
|
||||||
|
switch_hash_t *say_hash;
|
||||||
switch_memory_pool_t *pool;
|
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);
|
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;
|
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.asr_hash, loadable_modules.pool);
|
||||||
switch_core_hash_init(&loadable_modules.directory_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.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);
|
switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool);
|
||||||
|
|
||||||
if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
|
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);
|
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,
|
SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool, const switch_codec_implementation_t **array,
|
||||||
int arraylen)
|
int arraylen)
|
||||||
{
|
{
|
||||||
|
@ -107,6 +107,7 @@ static struct xml_section_t SECTIONS[] = {
|
|||||||
{ "config", SWITCH_XML_SECTION_CONFIG},
|
{ "config", SWITCH_XML_SECTION_CONFIG},
|
||||||
{ "directory", SWITCH_XML_SECTION_DIRECTORY},
|
{ "directory", SWITCH_XML_SECTION_DIRECTORY},
|
||||||
{ "dialplan", SWITCH_XML_SECTION_DIALPLAN},
|
{ "dialplan", SWITCH_XML_SECTION_DIALPLAN},
|
||||||
|
{ "phrases", SWITCH_XML_SECTION_PHRASES},
|
||||||
{ NULL, 0}
|
{ NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user