diff --git a/Makefile b/Makefile index 0b3d88194b5a79d0d4934d0592240d5d2661748d..bec360ae49ca0ec8da5d9d29fb88964478a602a8 100644 --- a/Makefile +++ b/Makefile @@ -357,7 +357,7 @@ endif SUBDIRS=res channels pbx apps codecs formats agi cdr funcs utils stdtime OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \ - translate.o file.o say.o pbx.o cli.o md5.o term.o \ + translate.o file.o pbx.o cli.o md5.o term.o \ ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \ cdr.o tdd.o acl.o rtp.o udptl.o manager.o asterisk.o \ dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \ @@ -366,6 +366,15 @@ OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \ netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \ cryptostub.o sha1.o +# we need to link in the objects statically, not as a library, because +# otherwise modules will not have them available if none of the static +# objects use it. +OBJS+= stdtime/localtime.o + +# At the moment say.o is an optional component which can be overridden +# by a module. +OBJS+= say.o + ifeq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/sys/poll.h),) OBJS+= poll.o ASTCFLAGS+=-DPOLLCOMPAT diff --git a/include/asterisk/say.h b/include/asterisk/say.h index ac498cde203d9568527eafea2cc5d83bfa7443a4..6c2396fc90e1ef6abee2452f64ef05fd7abb161c 100644 --- a/include/asterisk/say.h +++ b/include/asterisk/say.h @@ -32,6 +32,35 @@ extern "C" { #endif +/*! \brief + * All ast_say_* functions are implemented as function pointers, + * initialized to the function say_stub() which simply returns an error. + * An implementation of these functions (e.g. say.c, if available, or + * a dynamically loaded module) will just have to reassign the pointers + * to the relevant functions to override the previous implementation. + * As the conversion from the old implementation of say.c to the new + * implementation will be completed, and the API suitably reworked by + * removing redundant functions and/or arguments, this mechanism may be + * reverted back to pure static functions, if needed. + */ +#if defined(SAY_STUBS) +/* provide declarations for the *say*() functions + * and initialize them to the stub function + */ +static int say_stub(struct ast_channel *chan, ...) +{ + ast_log(LOG_WARNING, "no implementation for the say() functions\n"); + return -1; +}; + +#undef SAY_STUBS +#define SAY_INIT(x) = (typeof (x))say_stub +#define SAY_EXTERN +#else +#define SAY_INIT(x) +#define SAY_EXTERN extern +#endif + /* says a number * \param chan channel to say them number on * \param num number to say on the channel @@ -41,10 +70,10 @@ extern "C" { * Vocally says a number on a given channel * Returns 0 on success, DTMF digit on interrupt, -1 on failure */ -int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options); +SAY_EXTERN int (*ast_say_number)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options) SAY_INIT(ast_say_number); /* Same as above with audiofd for received audio and returns 1 on ctrlfd being readable */ -int ast_say_number_full(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd); +SAY_EXTERN int (* ast_say_number_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_number_full); /* says an enumeration * \param chan channel to say them enumeration on @@ -56,8 +85,8 @@ int ast_say_number_full(struct ast_channel *chan, int num, const char *ints, con * especially useful for dates and messages. says 'last' if num equals to INT_MAX * Returns 0 on success, DTMF digit on interrupt, -1 on failure */ -int ast_say_enumeration(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options); -int ast_say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd); +SAY_EXTERN int (* ast_say_enumeration)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options) SAY_INIT(ast_say_enumeration); +SAY_EXTERN int (* ast_say_enumeration_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_enumeration_full); /* says digits * \param chan channel to act upon @@ -67,8 +96,8 @@ int ast_say_enumeration_full(struct ast_channel *chan, int num, const char *ints * Vocally says digits of a given number * Returns 0 on success, dtmf if interrupted, -1 on failure */ -int ast_say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang); -int ast_say_digits_full(struct ast_channel *chan, int num, const char *ints, const char *lang, int audiofd, int ctrlfd); +SAY_EXTERN int (*ast_say_digits)(struct ast_channel *chan, int num, const char *ints, const char *lang) SAY_INIT(ast_say_digits); +SAY_EXTERN int (*ast_say_digits_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_digits_full); /* says digits of a string * \param chan channel to act upon @@ -78,22 +107,27 @@ int ast_say_digits_full(struct ast_channel *chan, int num, const char *ints, con * Vocally says the digits of a given string * Returns 0 on success, dtmf if interrupted, -1 on failure */ -int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang); -int ast_say_digit_str_full(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd); -int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang); -int ast_say_character_str_full(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd); -int ast_say_phonetic_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang); -int ast_say_phonetic_str_full(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd); +SAY_EXTERN int (* ast_say_digit_str)(struct ast_channel *chan, const char *num, const char *ints, const char *lang) SAY_INIT(ast_say_digit_str); +SAY_EXTERN int (* ast_say_digit_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_digit_str_full); -int ast_say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang); +/* + * the generic 'say' routine, with the first chars in the string + * defining the format to use + */ +SAY_EXTERN int (* ast_say_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_full); +SAY_EXTERN int (* ast_say_character_str)(struct ast_channel *chan, const char *num, const char *ints, const char *lang) SAY_INIT(ast_say_character_str); +SAY_EXTERN int (* ast_say_character_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_character_str_full); +SAY_EXTERN int (* ast_say_phonetic_str)(struct ast_channel *chan, const char *num, const char *ints, const char *lang) SAY_INIT(ast_say_phonetic_str); +SAY_EXTERN int (* ast_say_phonetic_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_phonetic_str_full); -int ast_say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang); +SAY_EXTERN int (* ast_say_datetime)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_datetime); +SAY_EXTERN int (* ast_say_time)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_time); -int ast_say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang); +SAY_EXTERN int (* ast_say_date)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_date); -int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, const char *ints, const char *lang); +SAY_EXTERN int (* ast_say_datetime_from_now)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_datetime_from_now); -int ast_say_date_with_format(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone); +SAY_EXTERN int (* ast_say_date_with_format)(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone) SAY_INIT(ast_say_date_with_format); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/pbx.c b/pbx.c index a4750b2540957640abf42ef2018e34a907d40159..0d94de23510e96fbc2138444d1be1118ef2c11ae 100644 --- a/pbx.c +++ b/pbx.c @@ -51,6 +51,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/manager.h" #include "asterisk/ast_expr.h" #include "asterisk/linkedlists.h" +#define SAY_STUBS /* generate declarations and stubs for say methods */ #include "asterisk/say.h" #include "asterisk/utils.h" #include "asterisk/causes.h" diff --git a/say.c b/say.c index 4f8f380f8298b919594e7ac5a4e7cbd4ceb4fb0e..908660efa82b882a70d716a743889f44f5eda355 100644 --- a/say.c +++ b/say.c @@ -56,7 +56,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") /* Forward declaration */ static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang); -int ast_say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd) + +static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd) { const char *fn; char fnbuf[256]; @@ -131,12 +132,12 @@ int ast_say_character_str_full(struct ast_channel *chan, const char *str, const return res; } -int ast_say_character_str(struct ast_channel *chan, const char *str, const char *ints, const char *lang) +static int say_character_str(struct ast_channel *chan, const char *str, const char *ints, const char *lang) { return ast_say_character_str_full(chan, str, ints, lang, -1, -1); } -int ast_say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd) +static int say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd) { const char *fn; char fnbuf[256]; @@ -210,12 +211,12 @@ int ast_say_phonetic_str_full(struct ast_channel *chan, const char *str, const c return res; } -int ast_say_phonetic_str(struct ast_channel *chan, const char *str, const char *ints, const char *lang) +static int say_phonetic_str(struct ast_channel *chan, const char *str, const char *ints, const char *lang) { return ast_say_phonetic_str_full(chan, str, ints, lang, -1, -1); } -int ast_say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd) +static int say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd) { const char *fn; char fnbuf[256]; @@ -261,12 +262,12 @@ int ast_say_digit_str_full(struct ast_channel *chan, const char *str, const char return res; } -int ast_say_digit_str(struct ast_channel *chan, const char *str, const char *ints, const char *lang) +static int say_digit_str(struct ast_channel *chan, const char *str, const char *ints, const char *lang) { return ast_say_digit_str_full(chan, str, ints, lang, -1, -1); } -int ast_say_digits_full(struct ast_channel *chan, int num, const char *ints, const char *lang, int audiofd, int ctrlfd) +static int say_digits_full(struct ast_channel *chan, int num, const char *ints, const char *lang, int audiofd, int ctrlfd) { char fn2[256]; @@ -274,7 +275,7 @@ int ast_say_digits_full(struct ast_channel *chan, int num, const char *ints, con return ast_say_digit_str_full(chan, fn2, ints, lang, audiofd, ctrlfd); } -int ast_say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang) +static int say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang) { return ast_say_digits_full(chan, num, ints, lang, -1, -1); } @@ -413,7 +414,7 @@ static int wait_file(struct ast_channel *chan, const char *ints, const char *fil /*! \brief ast_say_number_full: call language-specific functions */ /* Called from AGI */ -int ast_say_number_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd) +static int say_number_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd) { if (!strcasecmp(language,"en") ) { /* English syntax */ return(ast_say_number_full_en(chan, num, ints, language, audiofd, ctrlfd)); @@ -456,7 +457,7 @@ int ast_say_number_full(struct ast_channel *chan, int num, const char *ints, con } /*! \brief ast_say_number: call language-specific functions without file descriptors */ -int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options) +static int say_number(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options) { return(ast_say_number_full(chan, num, ints, language, options, -1, -1)); } @@ -2273,7 +2274,7 @@ static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char /*! \brief ast_say_enumeration_full: call language-specific functions */ /* Called from AGI */ -int ast_say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd) +static int say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd) { if (!strcasecmp(language,"en") ) { /* English syntax */ return(ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd)); @@ -2288,7 +2289,7 @@ int ast_say_enumeration_full(struct ast_channel *chan, int num, const char *ints } /*! \brief ast_say_enumeration: call language-specific functions without file descriptors */ -int ast_say_enumeration(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options) +static int say_enumeration(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options) { return(ast_say_enumeration_full(chan, num, ints, language, options, -1, -1)); } @@ -2718,7 +2719,7 @@ static int ast_say_enumeration_full_de(struct ast_channel *chan, int num, const return res; } -int ast_say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang) +static int say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang) { if (!strcasecmp(lang, "en") ) { /* English syntax */ return(ast_say_date_en(chan, t, ints, lang)); @@ -2947,7 +2948,7 @@ int ast_say_date_pt(struct ast_channel *chan, time_t t, const char *ints, const return res; } -int ast_say_date_with_format(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone) +static int say_date_with_format(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone) { /* If no format is given, use default english format */ if (format == NULL) @@ -5164,7 +5165,7 @@ int ast_say_date_with_format_tw(struct ast_channel *chan, time_t time, const cha return res; } -int ast_say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang) +static int say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang) { if (!strcasecmp(lang, "en") ) { /* English syntax */ return(ast_say_time_en(chan, t, ints, lang)); @@ -5353,7 +5354,7 @@ int ast_say_time_tw(struct ast_channel *chan, time_t t, const char *ints, const return res; } -int ast_say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang) +static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang) { if (!strcasecmp(lang, "en") ) { /* English syntax */ return(ast_say_datetime_en(chan, t, ints, lang)); @@ -5632,7 +5633,7 @@ int ast_say_datetime_tw(struct ast_channel *chan, time_t t, const char *ints, co return res; } -int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, const char *ints, const char *lang) +static int say_datetime_from_now(struct ast_channel *chan, time_t t, const char *ints, const char *lang) { if (!strcasecmp(lang, "en") ) { /* English syntax */ return(ast_say_datetime_from_now_en(chan, t, ints, lang)); @@ -6194,3 +6195,27 @@ static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t time, co } return res; } + +/* + * remap the 'say' functions to use those in this file + */ +static void __attribute__((constructor)) __say_init(void) +{ + ast_say_number = say_number; + ast_say_number_full = say_number_full; + ast_say_enumeration = say_enumeration; + ast_say_enumeration_full = say_enumeration_full; + ast_say_digits = say_digits; + ast_say_digits_full = say_digits_full; + ast_say_digit_str = say_digit_str; + ast_say_digit_str_full = say_digit_str_full; + ast_say_character_str = say_character_str; + ast_say_character_str_full = say_character_str_full; + ast_say_phonetic_str = say_phonetic_str; + ast_say_phonetic_str_full = say_phonetic_str_full; + ast_say_datetime = say_datetime; + ast_say_time = say_time; + ast_say_date = say_date; + ast_say_datetime_from_now = say_datetime_from_now; + ast_say_date_with_format = say_date_with_format; +}