[Freeswitch-trunk] [commit] r3766 - in freeswitch/trunk: conf src src/include src/mod/applications/mod_dptools src/mod/say src/mod/say/mod_say_en

Freeswitch SVN anthm at freeswitch.org
Wed Dec 20 16:25:15 EST 2006


Author: anthm
Date: Wed Dec 20 16:25:14 2006
New Revision: 3766

Added:
   freeswitch/trunk/src/mod/say/
   freeswitch/trunk/src/mod/say/mod_say_en/
   freeswitch/trunk/src/mod/say/mod_say_en/mod_say_en.c
Modified:
   freeswitch/trunk/conf/freeswitch.xml
   freeswitch/trunk/src/include/switch_ivr.h
   freeswitch/trunk/src/include/switch_loadable_module.h
   freeswitch/trunk/src/include/switch_module_interfaces.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
   freeswitch/trunk/src/switch_ivr.c
   freeswitch/trunk/src/switch_loadable_module.c
   freeswitch/trunk/src/switch_xml.c

Log:
add pelim say stuff, module framework, xml parser, dialplan app, and add new channel var called sound_prefix for audio files

Modified: freeswitch/trunk/conf/freeswitch.xml
==============================================================================
--- freeswitch/trunk/conf/freeswitch.xml	(original)
+++ freeswitch/trunk/conf/freeswitch.xml	Wed Dec 20 16:25:14 2006
@@ -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>
 
 

Modified: freeswitch/trunk/src/include/switch_ivr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_ivr.h	(original)
+++ freeswitch/trunk/src/include/switch_ivr.h	Wed Dec 20 16:25:14 2006
@@ -626,6 +626,13 @@
  */
 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

Modified: freeswitch/trunk/src/include/switch_loadable_module.h
==============================================================================
--- freeswitch/trunk/src/include/switch_loadable_module.h	(original)
+++ freeswitch/trunk/src/include/switch_loadable_module.h	Wed Dec 20 16:25:14 2006
@@ -75,6 +75,8 @@
 	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;
 };
@@ -180,6 +182,13 @@
   \return the desired chat interface
  */
 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);
 
 
 /*!

Modified: freeswitch/trunk/src/include/switch_module_interfaces.h
==============================================================================
--- freeswitch/trunk/src/include/switch_module_interfaces.h	(original)
+++ freeswitch/trunk/src/include/switch_module_interfaces.h	Wed Dec 20 16:25:14 2006
@@ -412,6 +412,20 @@
 	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 {

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Wed Dec 20 16:25:14 2006
@@ -94,6 +94,33 @@
 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),
 	SMF_ECHO_ALEG = (1 << 1),
@@ -172,7 +199,8 @@
 	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_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);

Modified: freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	Wed Dec 20 16:25:14 2006
@@ -102,6 +102,32 @@
 	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 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
 
 };
 

Added: freeswitch/trunk/src/mod/say/mod_say_en/mod_say_en.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/say/mod_say_en/mod_say_en.c	Wed Dec 20 16:25:14 2006
@@ -0,0 +1,178 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at 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 at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct at 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;
+}
+

Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c	(original)
+++ freeswitch/trunk/src/switch_ivr.c	Wed Dec 20 16:25:14 2006
@@ -977,8 +977,23 @@
 	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 @@
 		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 @@
 		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 @@
 					  artist,
 					  comment,
 					  date);
+#endif
 
 	assert(read_codec != NULL);
 	interval = read_codec->implementation->microseconds_per_frame / 1000;
@@ -4335,6 +4347,230 @@
 
 	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:

Modified: freeswitch/trunk/src/switch_loadable_module.c
==============================================================================
--- freeswitch/trunk/src/switch_loadable_module.c	(original)
+++ freeswitch/trunk/src/switch_loadable_module.c	Wed Dec 20 16:25:14 2006
@@ -54,6 +54,7 @@
 	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 @@
 			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_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))) {
@@ -681,6 +697,11 @@
 SWITCH_DECLARE(switch_chat_interface_t *) switch_loadable_module_get_chat_interface(char *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,

Modified: freeswitch/trunk/src/switch_xml.c
==============================================================================
--- freeswitch/trunk/src/switch_xml.c	(original)
+++ freeswitch/trunk/src/switch_xml.c	Wed Dec 20 16:25:14 2006
@@ -107,6 +107,7 @@
 	{ "config", SWITCH_XML_SECTION_CONFIG},
 	{ "directory", SWITCH_XML_SECTION_DIRECTORY},
 	{ "dialplan", SWITCH_XML_SECTION_DIALPLAN},
+	{ "phrases", SWITCH_XML_SECTION_PHRASES},
 	{ NULL, 0}
 };
 



More information about the Freeswitch-trunk mailing list