]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
introduce new say_string method of doing say and use it in mod_say_en as an example...
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 30 Mar 2011 00:55:28 +0000 (19:55 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 30 Mar 2011 00:55:35 +0000 (19:55 -0500)
src/include/switch_apr.h
src/include/switch_core.h
src/include/switch_ivr.h
src/include/switch_module_interfaces.h
src/include/switch_types.h
src/mod/applications/mod_commands/mod_commands.c
src/mod/say/mod_say_en/mod_say_en.c
src/switch_channel.c
src/switch_event.c
src/switch_ivr.c
src/switch_loadable_module.c

index 62559faf6361a0635fb1da92520bb67bba83d931..2306075e1f8d4b692ab6b487b1215c605078e8ad 100644 (file)
@@ -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);
 
index e54de72027ce7cb43901f15f3b3de1de29c68f6f..2946478c8928c7f497383ae5f02ae2cec63222e8 100644 (file)
@@ -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:
index 9b353f3dedd237e27c2bbc529c56b7def9077c03..36eaaec9ca0a907a12d4699afff57eddc8992cda 100644 (file)
@@ -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);
index 90d7342ef46ff22158dbea9e5cbabaeebb57e5b0..33c4c22bacff90589355309c4b17bb6ff5d549c1 100644 (file)
@@ -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;
index e732bca5977affbebb096ce677e942a5f002b198..81cc3fb719301f122f3cfca2e5b24a0eb57ea750 100644 (file)
@@ -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,
index fd2081e31d87f2f8ecbab9c1a29b65a0066a6ee0..6fb35598c22239babe55dad15e324fde8e8e2e37 100644 (file)
@@ -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);
index 6c604f208e8e9bf79642afc472877b808fe9d5c3..ec577374dc91f4221d18f443cfd4761b8c1422f5 100644 (file)
@@ -51,7 +51,8 @@
 SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load);
 SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
 
-#define say_num(num, meth) {                                                                                   \
+
+#define say_num(_sh, num, meth) {                                                                              \
                char tmp[80];                                                                                                   \
                switch_status_t tstatus;                                                                                \
                switch_say_method_t smeth = say_args->method;                                   \
@@ -59,7 +60,7 @@ SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
                say_args->type = SST_ITEMS; say_args->method = meth;                    \
                switch_snprintf(tmp, sizeof(tmp), "%u", (unsigned)num);                 \
                if ((tstatus =                                                                                                  \
-                        en_say_general_count(session, tmp, say_args, args))            \
+                        en_say_general_count(_sh, tmp, say_args))                                      \
                        != SWITCH_STATUS_SUCCESS) {                                                                     \
                        return tstatus;                                                                                         \
                }                                                                                                                               \
@@ -67,57 +68,44 @@ SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
        }                                                                                                                                       \
 
 
-#define say_file(...) {                                                                                                        \
-               char tmp[80];                                                                                                   \
-               switch_status_t tstatus;                                                                                \
-               switch_snprintf(tmp, sizeof(tmp), __VA_ARGS__);                                 \
-               if ((tstatus =                                                                                                  \
-                        switch_ivr_play_file(session, NULL, tmp, args))                        \
-                       != SWITCH_STATUS_SUCCESS){                                                                      \
-                       return tstatus;                                                                                         \
-               }                                                                                                                               \
-               if (!switch_channel_ready(switch_core_session_get_channel(session))) { \
-                       return SWITCH_STATUS_FALSE;                                                                     \
-               }}                                                                                                                              \
-
 
-static switch_status_t play_group(switch_say_method_t method, int a, int b, int c, char *what, switch_core_session_t *session, switch_input_args_t *args)
+static switch_status_t play_group(switch_say_method_t method, int a, int b, int c, char *what, switch_say_file_handle_t *sh)
 {
 
        if (a) {
-               say_file("digits/%d.wav", a);
-               say_file("digits/hundred.wav");
+               switch_say_file(sh, "digits/%d", a);
+               switch_say_file(sh, "digits/hundred");
        }
 
        if (b) {
                if (b > 1) {
                        if ((c == 0) && (method == SSM_COUNTED)) {
-                               say_file("digits/h-%d0.wav", b);
+                               switch_say_file(sh, "digits/h-%d0", b);
                        } else {
-                               say_file("digits/%d0.wav", b);
+                               switch_say_file(sh, "digits/%d0", b);
                        }
                } else {
-                       say_file("digits/%d%d.wav", b, c);
+                       switch_say_file(sh, "digits/%d%d", b, c);
                        c = 0;
                }
        }
 
        if (c) {
                if (method == SSM_COUNTED) {
-                       say_file("digits/h-%d.wav", c);
+                       switch_say_file(sh, "digits/h-%d", c);
                } else {
-                       say_file("digits/%d.wav", c);
+                       switch_say_file(sh, "digits/%d", c);
                }
        }
 
        if (what && (a || b || c)) {
-               say_file(what);
+               switch_say_file(sh, what);
        }
 
        return SWITCH_STATUS_SUCCESS;
 }
 
-static switch_status_t en_say_general_count(switch_core_session_t *session,    char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
+static switch_status_t en_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
 {
        int in;
        int x = 0;
@@ -129,7 +117,7 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
                if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
                        char *p;
                        for (p = tosay; p && *p; p++) {
-                               say_file("digits/%c.wav", *p);
+                               switch_say_file(sh, "digits/%c", *p);
                        }
                } else {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
@@ -156,13 +144,13 @@ static switch_status_t en_say_general_count(switch_core_session_t *session,       char
                switch (say_args->method) {
                case SSM_COUNTED:
                case SSM_PRONOUNCED:
-                       if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/million.wav", session, args)) != SWITCH_STATUS_SUCCESS) {
+                       if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/million", sh)) != SWITCH_STATUS_SUCCESS) {
                                return status;
                        }
-                       if ((status = play_group(SSM_PRONOUNCED, places[5], places[4], places[3], "digits/thousand.wav", session, args)) != SWITCH_STATUS_SUCCESS) {
+                       if ((status = play_group(SSM_PRONOUNCED, places[5], places[4], places[3], "digits/thousand", sh)) != SWITCH_STATUS_SUCCESS) {
                                return status;
                        }
-                       if ((status = play_group(say_args->method, places[2], places[1], places[0], NULL, session, args)) != SWITCH_STATUS_SUCCESS) {
+                       if ((status = play_group(say_args->method, places[2], places[1], places[0], NULL, sh)) != SWITCH_STATUS_SUCCESS) {
                                return status;
                        }
                        break;
@@ -170,20 +158,21 @@ static switch_status_t en_say_general_count(switch_core_session_t *session,       char
                        break;
                }
        } else {
-               say_file("digits/0.wav");
+               switch_say_file(sh, "digits/0");
        }
 
        return SWITCH_STATUS_SUCCESS;
 }
 
-static switch_status_t en_say_time(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
+static switch_status_t en_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
 {
        int32_t t;
        switch_time_t target = 0, target_now = 0;
        switch_time_exp_t tm, tm_now;
        uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0;
-       switch_channel_t *channel = switch_core_session_get_channel(session);
-       const char *tz = switch_channel_get_variable(channel, "timezone");
+       const char *tz = NULL;
+
+       tz = switch_say_file_handle_get_variable(sh, "timezone");               
 
        if (say_args->type == SST_TIME_MEASUREMENT) {
                int64_t hours = 0;
@@ -192,7 +181,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
                int64_t r = 0;
 
                if (strchr(tosay, ':')) {
-                       char *tme = switch_core_session_strdup(session, tosay);
+                       char *tme = strdup(tosay);
                        char *p;
 
                        if ((p = strrchr(tme, ':'))) {
@@ -208,6 +197,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
                                        minutes = atoi(tme);
                                }
                        }
+                       free(tme);
                } else {
                        if ((seconds = atol(tosay)) <= 0) {
                                seconds = (int64_t) switch_epoch_time_now(NULL);
@@ -227,39 +217,39 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
                }
 
                if (hours) {
-                       say_num(hours, SSM_PRONOUNCED);
+                       say_num(sh, hours, SSM_PRONOUNCED);
                        if (hours == 1) {
-                               say_file("time/hour.wav");
+                               switch_say_file(sh, "time/hour");
                        } else {
-                               say_file("time/hours.wav");
+                               switch_say_file(sh, "time/hours");
                        }
                } else {
-                       say_file("digits/0.wav");
-                       say_file("time/hours.wav");
+                       switch_say_file(sh, "digits/0");
+                       switch_say_file(sh, "time/hours");
                }
 
                if (minutes) {
-                       say_num(minutes, SSM_PRONOUNCED);
+                       say_num(sh, minutes, SSM_PRONOUNCED);
                        if (minutes == 1) {
-                               say_file("time/minute.wav");
+                               switch_say_file(sh, "time/minute");
                        } else {
-                               say_file("time/minutes.wav");
+                               switch_say_file(sh, "time/minutes");
                        }
                } else {
-                       say_file("digits/0.wav");
-                       say_file("time/minutes.wav");
+                       switch_say_file(sh, "digits/0");
+                       switch_say_file(sh, "time/minutes");
                }
 
                if (seconds) {
-                       say_num(seconds, SSM_PRONOUNCED);
+                       say_num(sh, seconds, SSM_PRONOUNCED);
                        if (seconds == 1) {
-                               say_file("time/second.wav");
+                               switch_say_file(sh, "time/second");
                        } else {
-                               say_file("time/seconds.wav");
+                               switch_say_file(sh, "time/seconds");
                        }
                } else {
-                       say_file("digits/0.wav");
-                       say_file("time/seconds.wav");
+                       switch_say_file(sh, "digits/0");
+                       switch_say_file(sh, "time/seconds");
                }
 
                return SWITCH_STATUS_SUCCESS;
@@ -275,7 +265,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
 
        if (tz) {
                int check = atoi(tz);
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
                if (check) {
                        switch_time_exp_tz(&tm, target, check);
                        switch_time_exp_tz(&tm_now, target_now, check);
@@ -329,13 +319,13 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
        }
 
        if (say_today) {
-               say_file("time/today.wav");
+               switch_say_file(sh, "time/today");
        }
        if (say_yesterday) {
-               say_file("time/yesterday.wav");
+               switch_say_file(sh, "time/yesterday");
        }
        if (say_dow) {
-               say_file("time/day-%d.wav", tm.tm_wday);
+               switch_say_file(sh, "time/day-%d", tm.tm_wday);
        }
 
        if (say_date) {
@@ -344,20 +334,20 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
        }
 
        if (say_month) {
-               say_file("time/mon-%d.wav", tm.tm_mon);
+               switch_say_file(sh, "time/mon-%d", tm.tm_mon);
        }
        if (say_day) {
-               say_num(tm.tm_mday, SSM_COUNTED);
+               say_num(sh, tm.tm_mday, SSM_COUNTED);
        }
        if (say_year) {
-               say_num(tm.tm_year + 1900, SSM_PRONOUNCED);
+               say_num(sh, tm.tm_year + 1900, SSM_PRONOUNCED);
        }
 
        if (say_time) {
                int32_t hour = tm.tm_hour, pm = 0;
 
                if (say_date || say_today || say_yesterday || say_dow) {
-                       say_file("time/at.wav");
+                       switch_say_file(sh, "time/at");
                }
 
                if (hour > 12) {
@@ -370,25 +360,25 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
                        pm = 0;
                }
 
-               say_num(hour, SSM_PRONOUNCED);
+               say_num(sh, hour, SSM_PRONOUNCED);
 
                if (tm.tm_min > 9) {
-                       say_num(tm.tm_min, SSM_PRONOUNCED);
+                       say_num(sh, tm.tm_min, SSM_PRONOUNCED);
                } else if (tm.tm_min) {
-                       say_file("time/oh.wav");
-                       say_num(tm.tm_min, SSM_PRONOUNCED);
+                       switch_say_file(sh, "time/oh");
+                       say_num(sh, tm.tm_min, SSM_PRONOUNCED);
                } else {
-                       say_file("time/oclock.wav");
+                       switch_say_file(sh, "time/oclock");
                }
 
-               say_file("time/%s.wav", pm ? "p-m" : "a-m");
+               switch_say_file(sh, "time/%s", pm ? "p-m" : "a-m");
        }
 
        return SWITCH_STATUS_SUCCESS;
 }
 
 
-static switch_status_t en_say_money(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
+static switch_status_t en_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
 {
        char sbuf[16] = "";                     /* enough for 999,999,999,999.99 (w/o the commas or leading $) */
        char *dollars = NULL;
@@ -415,43 +405,108 @@ static switch_status_t en_say_money(switch_core_session_t *session, char *tosay,
 
        /* If negative say "negative" */
        if (sbuf[0] == '-') {
-               say_file("currency/negative.wav");
+               switch_say_file(sh, "currency/negative");
                dollars++;
        }
 
        /* Say dollar amount */
-       en_say_general_count(session, dollars, say_args, args);
+       en_say_general_count(sh, dollars, say_args);
        if (atoi(dollars) == 1) {
-               say_file("currency/dollar.wav");
+               switch_say_file(sh, "currency/dollar");
        } else {
-               say_file("currency/dollars.wav");
+               switch_say_file(sh, "currency/dollars");
        }
 
        /* Say "and" */
-       say_file("currency/and.wav");
+       switch_say_file(sh, "currency/and");
 
        /* Say cents */
        if (cents) {
-               en_say_general_count(session, cents, say_args, args);
+               en_say_general_count(sh, cents, say_args);
                if (atoi(cents) == 1) {
-                       say_file("currency/cent.wav");
+                       switch_say_file(sh, "currency/cent");
                } else {
-                       say_file("currency/cents.wav");
+                       switch_say_file(sh, "currency/cents");
                }
        } else {
-               say_file("digits/0.wav");
-               say_file("currency/cents.wav");
+               switch_say_file(sh, "digits/0");
+               switch_say_file(sh, "currency/cents");
        }
 
        return SWITCH_STATUS_SUCCESS;
 }
 
 
+static switch_status_t say_ip(switch_say_file_handle_t *sh,
+                                                         char *tosay,
+                                                         switch_say_args_t *say_args)
+       
+{
+       char *a, *b, *c, *d;
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       
+       if (!(a = strdup(tosay))) {
+               abort();
+       }
 
-static switch_status_t en_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
+       if (!(b = strchr(a, '.'))) {
+               goto end;
+       }
+
+       *b++ = '\0';
+
+       if (!(c = strchr(b, '.'))) {
+               goto end;
+       }
+
+       *c++ = '\0';
+
+       if (!(d = strchr(c, '.'))) {
+               goto end;
+       }
+
+       *d++ = '\0';
+
+       say_num(sh, atoi(a), say_args->method);
+       switch_say_file(sh, "digits/dot");
+       say_num(sh, atoi(b), say_args->method);
+       switch_say_file(sh, "digits/dot");
+       say_num(sh, atoi(c), say_args->method);
+       switch_say_file(sh, "digits/dot");
+       say_num(sh, atoi(d), say_args->method);
+
+ end:
+       
+       free(a);
+
+       return status;
+}
+
+
+static switch_status_t say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
 {
+       char *p;
+
+       for (p = tosay; p && *p; p++) {
+               int a = tolower((int) *p);
+               if (a >= '0' && a <= '9') {
+                       switch_say_file(sh, "digits/%d", a - '0');
+               } else {
+                       if (say_args->type == SST_NAME_SPELLED) {
+                               switch_say_file(sh, "ascii/%d", a);
+                       } else if (say_args->type == SST_NAME_PHONETIC) {
+                               switch_say_file(sh, "phonetic-ascii/%d", a);
+                       }
+               }
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 
-       switch_say_callback_t say_cb = NULL;
+static switch_new_say_callback_t choose_callback(switch_say_args_t *say_args)
+{
+       switch_new_say_callback_t say_cb = NULL;
 
        switch (say_args->type) {
        case SST_NUMBER:
@@ -468,11 +523,11 @@ static switch_status_t en_say(switch_core_session_t *session, char *tosay, switc
                say_cb = en_say_time;
                break;
        case SST_IP_ADDRESS:
-               return switch_ivr_say_ip(session, tosay, en_say_general_count, say_args, args);
+               say_cb = say_ip;
                break;
        case SST_NAME_SPELLED:
        case SST_NAME_PHONETIC:
-               return switch_ivr_say_spell(session, tosay, say_args, args);
+               say_cb = say_spell;
                break;
        case SST_CURRENCY:
                say_cb = en_say_money;
@@ -482,11 +537,77 @@ static switch_status_t en_say(switch_core_session_t *session, char *tosay, switc
                break;
        }
 
+       return say_cb;
+}
+
+
+static switch_status_t run_callback(switch_new_say_callback_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr)
+{
+       switch_say_file_handle_t *sh;
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       switch_event_t *var_event = NULL;
+       
+       if (session) {
+               switch_channel_t *channel = switch_core_session_get_channel(session);
+               switch_channel_get_variables(channel, &var_event);
+       }
+
+       switch_say_file_handle_create(&sh, say_args->ext, &var_event);
+       
+       status = say_cb(sh, tosay, say_args);
+
+       if ((*rstr = switch_say_file_handle_detach_path(sh))) {
+               status = SWITCH_STATUS_SUCCESS;
+       }
+
+       switch_say_file_handle_destroy(&sh);
+
+       return status;
+}
+
+
+static switch_status_t en_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
+{
+
+       switch_new_say_callback_t say_cb = NULL;
+       char *string = NULL;
+
+       switch_status_t status = SWITCH_STATUS_FALSE;
+
+       say_cb = choose_callback(say_args);
+
+       if (say_cb) {
+               status = run_callback(say_cb, tosay, say_args, session, &string);
+               if (session && string) {
+                       status = switch_ivr_play_file(session, NULL, string, args);
+               }
+               
+               switch_safe_free(string);
+       }
+
+       return status;
+}
+
+
+static switch_status_t en_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr)
+{
+
+       switch_new_say_callback_t say_cb = NULL;
+       char *string = NULL;
+
+       switch_status_t status = SWITCH_STATUS_FALSE;
+
+       say_cb = choose_callback(say_args);
+
        if (say_cb) {
-               return say_cb(session, tosay, say_args, args);
+               status = run_callback(say_cb, tosay, say_args, session, &string);
+               if (string) {
+                       status = SWITCH_STATUS_SUCCESS;
+                       *rstr = string;
+               }
        }
 
-       return SWITCH_STATUS_FALSE;
+       return status;
 }
 
 SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load)
@@ -497,7 +618,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load)
        say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE);
        say_interface->interface_name = "en";
        say_interface->say_function = en_say;
-
+       say_interface->say_string_function = en_say_string;
+       
        /* indicate that the module should continue to be loaded */
        return SWITCH_STATUS_SUCCESS;
 }
index 7d246893f7172acf9bacd0eb4a48e4008b8ede5b..52542e12d69a5c3d8a931c99e422f76c2d4e705e 100644 (file)
@@ -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 == ' ') {
index b7687c2041ed47d87b59cc200c6f68fac70907a1..e290987248f5b73b461f76093011b0099dfe856e 100644 (file)
@@ -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';
                                        }
index 5a082763b2df686c9812d3e55bf0ac68c4743442..b6dac4d71dd0a9e003322ab2cb22c60048b34fcb 100644 (file)
@@ -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;
index d6796c81199b37c807fdc186da2c842ccd9efbc6..ea7bc736846be06dd372f4bcf06ecb7a575dce90 100644 (file)
@@ -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