Sat Mar 24 23:26:10 2007

Asterisk developer's documentation


app.h File Reference

Application convenience functions, designed to give consistent look and feel to Asterisk apps. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_app_option
 A structure to hold the description of an application 'option'. More...
struct  ast_ivr_menu
struct  ast_ivr_option

Defines

#define AST_APP_ARG(name)   char *name
 Define an application argument.
#define AST_APP_OPTION(option, flagno)   [option] = { .flag = flagno }
 Declares an application option that does not accept an argument.
#define AST_APP_OPTION_ARG(option, flagno, argno)   [option] = { .flag = flagno, .arg_index = argno + 1 }
 Declares an application option that accepts an argument.
#define AST_APP_OPTIONS(holder, options...)   static const struct ast_app_option holder[128] = options
 Declares an array of options for an application.
#define AST_DECLARE_APP_ARGS(name, arglist)
 Declare a structure to hold the application's arguments.
#define AST_IVR_DECLARE_MENU(holder, title, flags, foo...)
#define AST_IVR_FLAG_AUTORESTART   (1 << 0)
#define AST_STANDARD_APP_ARGS(args, parse)   args.argc = ast_app_separate_args(parse, '|', args.argv, (sizeof(args) - sizeof(args.argc)) / sizeof(args.argv[0]))
 Performs the 'standard' argument separation process for an application.
#define GROUP_CATEGORY_PREFIX   "GROUP"

Typedefs

typedef int(* ast_ivr_callback )(struct ast_channel *chan, char *option, void *cbdata)
 Callback function for IVR.

Enumerations

enum  ast_ivr_action {
  AST_ACTION_UPONE, AST_ACTION_EXIT, AST_ACTION_CALLBACK, AST_ACTION_PLAYBACK,
  AST_ACTION_BACKGROUND, AST_ACTION_PLAYLIST, AST_ACTION_MENU, AST_ACTION_REPEAT,
  AST_ACTION_RESTART, AST_ACTION_TRANSFER, AST_ACTION_WAITOPTION, AST_ACTION_NOOP,
  AST_ACTION_BACKLIST
}
enum  AST_LOCK_RESULT { AST_LOCK_SUCCESS = 0, AST_LOCK_TIMEOUT = -1, AST_LOCK_PATH_NOT_FOUND = -2, AST_LOCK_FAILURE = -3 }

Functions

int ast_app_dtget (struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
 Present a dialtone and collect a certain length extension.
int ast_app_getdata (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
 Plays a stream and gets DTMF data from a channel.
int ast_app_getdata_full (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
 Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions.
int ast_app_getvoice (struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
int ast_app_group_get_count (char *group, char *category)
int ast_app_group_match_get_count (char *groupmatch, char *category)
int ast_app_group_set_channel (struct ast_channel *chan, char *data)
int ast_app_group_split_group (char *data, char *group, int group_max, char *category, int category_max)
int ast_app_has_voicemail (const char *mailbox, const char *folder)
int ast_app_messagecount (const char *mailbox, int *newmsgs, int *oldmsgs)
int ast_app_parse_options (const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
 Parses a string containing application options and sets flags/arguments.
unsigned int ast_app_separate_args (char *buf, char delim, char **array, int arraylen)
 Separate a string into arguments in an array.
int ast_control_streamfile (struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms)
int ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, char *digits, int between)
void ast_install_vm_functions (int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs))
int ast_ivr_menu_run (struct ast_channel *c, struct ast_ivr_menu *menu, void *cbdata)
 Runs an IVR menu.
int ast_linear_stream (struct ast_channel *chan, const char *filename, int fd, int allowoverride)
enum AST_LOCK_RESULT ast_lock_path (const char *path)
 Lock a filesystem path.
int ast_play_and_prepend (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence_ms)
int ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int silencethreshold, int maxsilence_ms, const char *path)
int ast_play_and_wait (struct ast_channel *chan, const char *fn)
char * ast_read_textfile (const char *file)
int ast_record_review (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
int ast_safe_system (const char *s)
void ast_uninstall_vm_functions (void)
int ast_unlock_path (const char *path)


Detailed Description

Application convenience functions, designed to give consistent look and feel to Asterisk apps.

Definition in file app.h.


Define Documentation

#define AST_APP_ARG name   )     char *name
 

Define an application argument.

Parameters:
name The name of the argument

Definition at line 185 of file app.h.

Referenced by __login_exec(), aqm_exec(), dial_exec_full(), disa_exec(), enumlookup_exec(), group_check_exec(), hasvoicemail_exec(), md5check_exec(), mixmonitor_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), transfer_exec(), txtcidname_exec(), upqm_exec(), and vm_box_exists().

#define AST_APP_OPTION option,
flagno   )     [option] = { .flag = flagno }
 

Declares an application option that does not accept an argument.

Parameters:
option The single character representing the option
flagno The flag index to be set if this option is present
See also:
AST_APP_OPTIONS, ast_app_parse_options

Definition at line 314 of file app.h.

#define AST_APP_OPTION_ARG option,
flagno,
argno   )     [option] = { .flag = flagno, .arg_index = argno + 1 }
 

Declares an application option that accepts an argument.

Parameters:
option The single character representing the option
flagno The flag index to be set if this option is present
argno The index into the argument array where the argument should be placed
See also:
AST_APP_OPTIONS, ast_app_parse_options

Definition at line 325 of file app.h.

#define AST_APP_OPTIONS holder,
options...   )     static const struct ast_app_option holder[128] = options
 

Declares an array of options for an application.

Parameters:
holder The name of the array to be created
options The actual options to be placed into the array
See also:
ast_app_parse_options
This macro declares a 'static const' array of struct ast_option elements to hold the list of available options for an application. Each option must be declared using either the AST_APP_OPTION() or AST_APP_OPTION_ARG() macros.

Example usage:

  enum {
        OPT_JUMP = (1 << 0),
        OPT_BLAH = (1 << 1),
        OPT_BLORT = (1 << 2),
  } my_app_option_flags;

  enum {
        OPT_ARG_BLAH = 0,
        OPT_ARG_BLORT,
        !! this entry tells how many possible arguments there are,
           and must be the last entry in the list
        OPT_ARG_ARRAY_SIZE,
  } my_app_option_args;

  AST_APP_OPTIONS(my_app_options, {
        AST_APP_OPTION('j', OPT_JUMP),
        AST_APP_OPTION_ARG('b', OPT_BLAH, OPT_ARG_BLAH),
        AST_APP_OPTION_BLORT('B', OPT_BLORT, OPT_ARG_BLORT),
  });

  static int my_app_exec(struct ast_channel *chan, void *data)
  {
   char *options;
   struct ast_flags opts = { 0, };
   char *opt_args[OPT_ARG_ARRAY_SIZE];

   ... do any argument parsing here ...

   if (ast_parseoptions(my_app_options, &opts, opt_args, options)) {
      LOCAL_USER_REMOVE(u);
      return -1;
   }
  }

Definition at line 305 of file app.h.

#define AST_DECLARE_APP_ARGS name,
arglist   ) 
 

Value:

struct { \
      unsigned int argc; \
      char *argv[0]; \
      arglist \
   } name
Declare a structure to hold the application's arguments.

Parameters:
name The name of the structure
arglist The list of arguments, defined using AST_APP_ARG
This macro defines a structure intended to be used in a call to ast_app_separate_args(). The structure includes all the arguments specified, plus an argv array that overlays them and an argc argument counter. The arguments must be declared using AST_APP_ARG, and they will all be character pointers (strings).

Note:
The structure is not initialized, as the call to ast_app_separate_args() will perform that function before parsing the arguments.

Definition at line 202 of file app.h.

Referenced by __login_exec(), aqm_exec(), dial_exec_full(), disa_exec(), enumlookup_exec(), group_check_exec(), hasvoicemail_exec(), md5check_exec(), mixmonitor_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), transfer_exec(), txtcidname_exec(), upqm_exec(), and vm_box_exists().

#define AST_IVR_DECLARE_MENU holder,
title,
flags,
foo...   ) 
 

Value:

static struct ast_ivr_option __options_##holder[] = foo;\
   static struct ast_ivr_menu holder = { title, flags, __options_##holder }

Definition at line 76 of file app.h.

#define AST_IVR_FLAG_AUTORESTART   (1 << 0)
 

Definition at line 74 of file app.h.

#define AST_STANDARD_APP_ARGS args,
parse   )     args.argc = ast_app_separate_args(parse, '|', args.argv, (sizeof(args) - sizeof(args.argc)) / sizeof(args.argv[0]))
 

Performs the 'standard' argument separation process for an application.

Parameters:
args An argument structure defined using AST_DECLARE_APP_ARGS
parse A modifiable buffer containing the input to be parsed
This function will separate the input string using the standard argument separator character '|' and fill in the provided structure, including the argc argument counter field.

Definition at line 218 of file app.h.

Referenced by __login_exec(), aqm_exec(), dial_exec_full(), disa_exec(), enumlookup_exec(), group_check_exec(), hasvoicemail_exec(), md5check_exec(), mixmonitor_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), transfer_exec(), txtcidname_exec(), upqm_exec(), and vm_box_exists().

#define GROUP_CATEGORY_PREFIX   "GROUP"
 

Definition at line 167 of file app.h.

Referenced by ast_app_group_get_count(), ast_app_group_match_get_count(), ast_app_group_split_group(), clone_variables(), group_function_read(), group_list_function_read(), and group_show_channels().


Typedef Documentation

typedef int(* ast_ivr_callback)(struct ast_channel *chan, char *option, void *cbdata)
 

Callback function for IVR.

Returns:
returns 0 on completion, -1 on hangup or digit if interrupted

Definition at line 35 of file app.h.


Enumeration Type Documentation

enum ast_ivr_action
 

Enumerator:
AST_ACTION_UPONE  adata is unused
AST_ACTION_EXIT  adata is the return value for ast_ivr_menu_run if channel was not hungup
AST_ACTION_CALLBACK  adata is an ast_ivr_callback
AST_ACTION_PLAYBACK  adata is file to play
AST_ACTION_BACKGROUND  adata is file to play
AST_ACTION_PLAYLIST  adata is list of files, separated by ; to play
AST_ACTION_MENU  adata is a pointer to an ast_ivr_menu
AST_ACTION_REPEAT  adata is max # of repeats, cast to a pointer
AST_ACTION_RESTART  adata is like repeat, but resets repeats to 0
AST_ACTION_TRANSFER  adata is a string with exten[]
AST_ACTION_WAITOPTION  adata is a timeout, or 0 for defaults
AST_ACTION_NOOP  adata is unused
AST_ACTION_BACKLIST  adata is list of files separated by ; allows interruption

Definition at line 37 of file app.h.

00037              {
00038    AST_ACTION_UPONE, /*!< adata is unused */
00039    AST_ACTION_EXIT,  /*!< adata is the return value for ast_ivr_menu_run if channel was not hungup */
00040    AST_ACTION_CALLBACK, /*!< adata is an ast_ivr_callback */
00041    AST_ACTION_PLAYBACK, /*!< adata is file to play */
00042    AST_ACTION_BACKGROUND,  /*!< adata is file to play */
00043    AST_ACTION_PLAYLIST, /*!< adata is list of files, separated by ; to play */
00044    AST_ACTION_MENU,  /*!< adata is a pointer to an ast_ivr_menu */
00045    AST_ACTION_REPEAT,   /*!< adata is max # of repeats, cast to a pointer */
00046    AST_ACTION_RESTART,  /*!< adata is like repeat, but resets repeats to 0 */
00047    AST_ACTION_TRANSFER, /*!< adata is a string with exten[@context] */
00048    AST_ACTION_WAITOPTION,  /*!< adata is a timeout, or 0 for defaults */
00049    AST_ACTION_NOOP,  /*!< adata is unused */
00050    AST_ACTION_BACKLIST, /*!< adata is list of files separated by ; allows interruption */
00051 } ast_ivr_action;

enum AST_LOCK_RESULT
 

Enumerator:
AST_LOCK_SUCCESS 
AST_LOCK_TIMEOUT 
AST_LOCK_PATH_NOT_FOUND 
AST_LOCK_FAILURE 

Definition at line 147 of file app.h.

00147                      {
00148    AST_LOCK_SUCCESS = 0,
00149    AST_LOCK_TIMEOUT = -1,
00150    AST_LOCK_PATH_NOT_FOUND = -2,
00151    AST_LOCK_FAILURE = -3,
00152 };


Function Documentation

int ast_app_dtget struct ast_channel chan,
const char *  context,
char *  collect,
size_t  size,
int  maxlen,
int  timeout
 

Present a dialtone and collect a certain length extension.

Returns:
Returns 1 on valid extension entered, -1 on hangup, or 0 on invalid extension.
Note:
Note that if 'collect' holds digits already, new digits will be appended, so be sure it's initialized properly

Definition at line 62 of file app.c.

References ast_get_indication_tone(), ast_ignore_pattern(), ast_log(), ast_matchmore_extension(), ast_playtones_start(), ast_playtones_stop(), ast_waitfordigit(), tone_zone_sound::data, ast_pbx::dtimeout, LOG_NOTICE, ast_channel::pbx, and ast_channel::zone.

Referenced by builtin_atxfer(), and builtin_blindtransfer().

00063 {
00064    struct tone_zone_sound *ts;
00065    int res=0, x=0;
00066 
00067    if(maxlen > size)
00068       maxlen = size;
00069    
00070    if(!timeout && chan->pbx)
00071       timeout = chan->pbx->dtimeout;
00072    else if(!timeout)
00073       timeout = 5;
00074    
00075    ts = ast_get_indication_tone(chan->zone,"dial");
00076    if (ts && ts->data[0])
00077       res = ast_playtones_start(chan, 0, ts->data, 0);
00078    else 
00079       ast_log(LOG_NOTICE,"Huh....? no dial for indications?\n");
00080    
00081    for (x = strlen(collect); strlen(collect) < maxlen; ) {
00082       res = ast_waitfordigit(chan, timeout);
00083       if (!ast_ignore_pattern(context, collect))
00084          ast_playtones_stop(chan);
00085       if (res < 1)
00086          break;
00087       collect[x++] = res;
00088       if (!ast_matchmore_extension(chan, context, collect, 1, chan->cid.cid_num)) {
00089          if (collect[x-1] == '#') {
00090             /* Not a valid extension, ending in #, assume the # was to finish dialing */
00091             collect[x-1] = '\0';
00092          }
00093          break;
00094       }
00095    }
00096    if (res >= 0) {
00097       if (ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num))
00098          res = 1;
00099       else
00100          res = 0;
00101    }
00102    return res;
00103 }

int ast_app_getdata struct ast_channel c,
char *  prompt,
char *  s,
int  maxlen,
int  timeout
 

Plays a stream and gets DTMF data from a channel.

Parameters:
timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for "ludicrous time" (essentially never times out)

Definition at line 109 of file app.c.

References ast_readstring(), ast_streamfile(), ast_pbx::dtimeout, ast_channel::language, ast_channel::pbx, and ast_pbx::rtimeout.

Referenced by __login_exec(), auth_exec(), conf_exec(), dictate_exec(), read_exec(), testclient_exec(), testserver_exec(), and vm_exec().

00110 {
00111    int res,to,fto;
00112    /* XXX Merge with full version? XXX */
00113    if (maxlen)
00114       s[0] = '\0';
00115    if (prompt) {
00116       res = ast_streamfile(c, prompt, c->language);
00117       if (res < 0)
00118          return res;
00119    }
00120    fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
00121    to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
00122 
00123    if (timeout > 0) 
00124       fto = to = timeout;
00125    if (timeout < 0) 
00126       fto = to = 1000000000;
00127    res = ast_readstring(c, s, maxlen, to, fto, "#");
00128    return res;
00129 }

int ast_app_getdata_full struct ast_channel c,
char *  prompt,
char *  s,
int  maxlen,
int  timeout,
int  audiofd,
int  ctrlfd
 

Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions.

Definition at line 132 of file app.c.

References ast_readstring_full(), ast_streamfile(), and ast_channel::language.

Referenced by handle_getdata().

00133 {
00134    int res,to,fto;
00135    if (prompt) {
00136       res = ast_streamfile(c, prompt, c->language);
00137       if (res < 0)
00138          return res;
00139    }
00140    fto = 6000;
00141    to = 2000;
00142    if (timeout > 0) 
00143       fto = to = timeout;
00144    if (timeout < 0) 
00145       fto = to = 1000000000;
00146    res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
00147    return res;
00148 }

int ast_app_getvoice struct ast_channel c,
char *  dest,
char *  dstfmt,
char *  prompt,
int  silence,
int  maxsec
 

Record voice (after playing prompt if specified), waiting for silence (in ms) up to a given timeout (in s) or '#'

Definition at line 150 of file app.c.

References ast_dsp_free(), ast_dsp_new(), AST_FORMAT_SLINEAR, ast_log(), ast_set_read_format(), ast_streamfile(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::readformat, and total.

00151 {
00152    int res;
00153    struct ast_filestream *writer;
00154    int rfmt;
00155    int totalms=0, total;
00156    
00157    struct ast_frame *f;
00158    struct ast_dsp *sildet;
00159    /* Play prompt if requested */
00160    if (prompt) {
00161       res = ast_streamfile(c, prompt, c->language);
00162       if (res < 0)
00163          return res;
00164       res = ast_waitstream(c,"");
00165       if (res < 0)
00166          return res;
00167    }
00168    rfmt = c->readformat;
00169    res = ast_set_read_format(c, AST_FORMAT_SLINEAR);
00170    if (res < 0) {
00171       ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00172       return -1;
00173    }
00174    sildet = ast_dsp_new();
00175    if (!sildet) {
00176       ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00177       return -1;
00178    }
00179    writer = ast_writefile(dest, dstfmt, "Voice file", 0, 0, 0666);
00180    if (!writer) {
00181       ast_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
00182       ast_dsp_free(sildet);
00183       return -1;
00184    }
00185    for(;;) {
00186       if ((res = ast_waitfor(c, 2000)) < 0) {
00187          ast_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
00188          break;
00189       }
00190       if (res) {
00191          f = ast_read(c);
00192          if (!f) {
00193             ast_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
00194             break;
00195          }
00196          if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
00197             /* Ended happily with DTMF */
00198             ast_frfree(f);
00199             break;
00200          } else if (f->frametype == AST_FRAME_VOICE) {
00201             ast_dsp_silence(sildet, f, &total); 
00202             if (total > silence) {
00203                /* Ended happily with silence */
00204                ast_frfree(f);
00205                break;
00206             }
00207             totalms += f->samples / 8;
00208             if (totalms > maxsec * 1000) {
00209                /* Ended happily with too much stuff */
00210                ast_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec);
00211                ast_frfree(f);
00212                break;
00213             }
00214             res = ast_writestream(writer, f);
00215             if (res < 0) {
00216                ast_log(LOG_WARNING, "Failed to write to stream at %s!\n", dest);
00217                ast_frfree(f);
00218                break;
00219             }
00220                
00221          }
00222          ast_frfree(f);
00223       }
00224    }
00225    res = ast_set_read_format(c, rfmt);
00226    if (res)
00227       ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name);
00228    ast_dsp_free(sildet);
00229    ast_closestream(writer);
00230    return 0;
00231 }

int ast_app_group_get_count char *  group,
char *  category
 

Get the current channel count of the specified group and category.

Definition at line 1044 of file app.c.

References ast_channel_walk_locked(), ast_mutex_unlock(), ast_strlen_zero(), GROUP_CATEGORY_PREFIX, ast_channel::lock, pbx_builtin_getvar_helper(), and s.

Referenced by group_check_exec(), group_count_exec(), and group_count_function_read().

01045 {
01046    struct ast_channel *chan;
01047    int count = 0;
01048    char *test;
01049    char cat[80];
01050    char *s;
01051 
01052    if (ast_strlen_zero(group))
01053       return 0;
01054 
01055    s = (!ast_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX;
01056    ast_copy_string(cat, s, sizeof(cat));
01057 
01058    chan = NULL;
01059    while ((chan = ast_channel_walk_locked(chan)) != NULL) {
01060       test = pbx_builtin_getvar_helper(chan, cat);
01061       if (test && !strcasecmp(test, group))
01062          count++;
01063       ast_mutex_unlock(&chan->lock);
01064    }
01065 
01066    return count;
01067 }

int ast_app_group_match_get_count char *  groupmatch,
char *  category
 

Get the current channel count of all groups that match the specified pattern and category.

Definition at line 1069 of file app.c.

References ast_channel_walk_locked(), ast_mutex_unlock(), ast_strlen_zero(), GROUP_CATEGORY_PREFIX, ast_channel::lock, pbx_builtin_getvar_helper(), and s.

Referenced by group_match_count_exec(), and group_match_count_function_read().

01070 {
01071    regex_t regexbuf;
01072    struct ast_channel *chan;
01073    int count = 0;
01074    char *test;
01075    char cat[80];
01076    char *s;
01077 
01078    if (ast_strlen_zero(groupmatch))
01079       return 0;
01080 
01081    /* if regex compilation fails, return zero matches */
01082    if (regcomp(&regexbuf, groupmatch, REG_EXTENDED | REG_NOSUB))
01083       return 0;
01084 
01085    s = (!ast_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX;
01086    ast_copy_string(cat, s, sizeof(cat));
01087 
01088    chan = NULL;
01089    while ((chan = ast_channel_walk_locked(chan)) != NULL) {
01090       test = pbx_builtin_getvar_helper(chan, cat);
01091       if (test && !regexec(&regexbuf, test, 0, NULL, 0))
01092          count++;
01093       ast_mutex_unlock(&chan->lock);
01094    }
01095 
01096    regfree(&regexbuf);
01097 
01098    return count;
01099 }

int ast_app_group_set_channel struct ast_channel chan,
char *  data
 

Set the group for a channel, splitting the provided data into group and category, if specified.

Definition at line 1030 of file app.c.

References ast_app_group_split_group(), group, and pbx_builtin_setvar_helper().

Referenced by group_function_write(), and group_set_exec().

01031 {
01032    int res=0;
01033    char group[80] = "";
01034    char category[80] = "";
01035 
01036    if (!ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) {
01037       pbx_builtin_setvar_helper(chan, category, group);
01038    } else
01039       res = -1;
01040 
01041    return res;
01042 }

int ast_app_group_split_group char *  data,
char *  group,
int  group_max,
char *  category,
int  category_max
 

Split a group string into group and category, returning a default category if none is provided.

Definition at line 1001 of file app.c.

References ast_strlen_zero(), and GROUP_CATEGORY_PREFIX.

Referenced by ast_app_group_set_channel(), group_check_exec(), group_count_exec(), group_count_function_read(), group_match_count_exec(), and group_match_count_function_read().

01002 {
01003    int res=0;
01004    char tmp[256];
01005    char *grp=NULL, *cat=NULL;
01006 
01007    if (!ast_strlen_zero(data)) {
01008       ast_copy_string(tmp, data, sizeof(tmp));
01009       grp = tmp;
01010       cat = strchr(tmp, '@');
01011       if (cat) {
01012          *cat = '\0';
01013          cat++;
01014       }
01015    }
01016 
01017    if (!ast_strlen_zero(grp))
01018       ast_copy_string(group, grp, group_max);
01019    else
01020       res = -1;
01021 
01022    if (cat)
01023       snprintf(category, category_max, "%s_%s", GROUP_CATEGORY_PREFIX, cat);
01024    else
01025       ast_copy_string(category, GROUP_CATEGORY_PREFIX, category_max);
01026 
01027    return res;
01028 }

int ast_app_has_voicemail const char *  mailbox,
const char *  folder
 

Determine if a given mailbox has any voicemail

Definition at line 249 of file app.c.

References ast_has_voicemail_func, ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.

Referenced by action_mailboxstatus(), has_voicemail(), notify_new_message(), play_dialtone(), and update_registry().

00250 {
00251    static int warned = 0;
00252    if (ast_has_voicemail_func)
00253       return ast_has_voicemail_func(mailbox, folder);
00254 
00255    if ((option_verbose > 2) && !warned) {
00256       ast_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX");
00257       warned++;
00258    }
00259    return 0;
00260 }

int ast_app_messagecount const char *  mailbox,
int *  newmsgs,
int *  oldmsgs
 

Determine number of new/old messages in a mailbox

Definition at line 263 of file app.c.

References ast_messagecount_func, ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.

Referenced by action_mailboxcount(), do_housekeeping(), notify_new_message(), sip_send_mwi_to_peer(), and update_registry().

00264 {
00265    static int warned = 0;
00266    if (newmsgs)
00267       *newmsgs = 0;
00268    if (oldmsgs)
00269       *oldmsgs = 0;
00270    if (ast_messagecount_func)
00271       return ast_messagecount_func(mailbox, newmsgs, oldmsgs);
00272 
00273    if (!warned && (option_verbose > 2)) {
00274       warned++;
00275       ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
00276    }
00277 
00278    return 0;
00279 }

int ast_app_parse_options const struct ast_app_option options,
struct ast_flags flags,
char **  args,
char *  optstr
 

Parses a string containing application options and sets flags/arguments.

Parameters:
options The array of possible options declared with AST_APP_OPTIONS
flags The flag structure to have option flags set
args The array of argument pointers to hold arguments found
optstr The string containing the options to be parsed
Returns:
zero for success, non-zero if an error occurs
See also:
AST_APP_OPTIONS

Definition at line 1519 of file app.c.

References ast_app_option::arg_index, ast_clear_flag, AST_FLAGS_ALL, ast_log(), ast_set_flag, LOG_WARNING, and s.

Referenced by chanspy_exec(), conf_exec(), dial_exec_full(), mixmonitor_exec(), page_exec(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_waitexten(), vm_exec(), and vm_execmain().

01520 {
01521    char *s;
01522    int curarg;
01523    unsigned int argloc;
01524    char *arg;
01525    int res = 0;
01526 
01527    ast_clear_flag(flags, AST_FLAGS_ALL);
01528 
01529    if (!optstr)
01530       return 0;
01531 
01532    s = optstr;
01533    while (*s) {
01534       curarg = *s++ & 0x7f;
01535       ast_set_flag(flags, options[curarg].flag);
01536       argloc = options[curarg].arg_index;
01537       if (*s == '(') {
01538          /* Has argument */
01539          arg = ++s;
01540          while (*s && (*s != ')'))
01541             s++;
01542          if (*s) {
01543             if (argloc)
01544                args[argloc - 1] = arg;
01545             *s++ = '\0';
01546          } else {
01547             ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
01548             res = -1;
01549          }
01550       } else if (argloc) {
01551          args[argloc - 1] = NULL;
01552       }
01553    }
01554 
01555    return res;
01556 }

unsigned int ast_app_separate_args char *  buf,
char  delim,
char **  array,
int  arraylen
 

Separate a string into arguments in an array.

Parameters:
buf The string to be parsed (this must be a writable copy, as it will be modified)
delim The character to be used to delimit arguments
array An array of 'char *' to be filled in with pointers to the found arguments
arraylen The number of elements in the array (i.e. the number of arguments you will accept)
Note: if there are more arguments in the string than the array will hold, the last element of the array will contain the remaining arguments, not separated.

The array will be completely zeroed by this function before it populates any entries.

Returns:
The number of arguments found, or zero if the function arguments are not valid.

Definition at line 1101 of file app.c.

Referenced by add_agent(), app_exec(), astman_get_variables(), builtin_function_cdr_read(), builtin_function_cdr_write(), builtin_function_checkmd5(), builtin_function_math(), chanspy_exec(), controlplayback_exec(), cut_internal(), dictate_exec(), function_db_exists(), function_db_read(), function_db_write(), pbx_builtin_background(), pbx_builtin_setvar(), pbx_builtin_waitexten(), read_exec(), vm_exec(), and vm_execmain().

01102 {
01103    int argc;
01104    char *scan;
01105    int paren = 0;
01106 
01107    if (!buf || !array || !arraylen)
01108       return 0;
01109 
01110    memset(array, 0, arraylen * sizeof(*array));
01111 
01112    scan = buf;
01113 
01114    for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
01115       array[argc] = scan;
01116       for (; *scan; scan++) {
01117          if (*scan == '(')
01118             paren++;
01119          else if (*scan == ')') {
01120             if (paren)
01121                paren--;
01122          } else if ((*scan == delim) && !paren) {
01123             *scan++ = '\0';
01124             break;
01125          }
01126       }
01127    }
01128 
01129    if (*scan)
01130       array[argc++] = scan;
01131 
01132    return argc;
01133 }

int ast_control_streamfile struct ast_channel chan,
const char *  file,
const char *  fwd,
const char *  rev,
const char *  stop,
const char *  pause,
const char *  restart,
int  skipms
 

Stream a file with fast forward, pause, reverse, restart.

Definition at line 432 of file app.c.

References ast_channel::_state, ast_answer(), ast_log(), ast_seekstream(), AST_STATE_UP, ast_stopstream(), ast_streamfile(), ast_tellstream(), ast_waitfordigit(), ast_waitstream_fr(), ast_channel::language, LOG_DEBUG, and ast_channel::stream.

Referenced by controlplayback_exec(), handle_controlstreamfile(), and wait_file().

00436 {
00437    char *breaks = NULL;
00438    char *end = NULL;
00439    int blen = 2;
00440    int res;
00441    long pause_restart_point = 0;
00442 
00443    if (stop)
00444       blen += strlen(stop);
00445    if (pause)
00446       blen += strlen(pause);
00447    if (restart)
00448       blen += strlen(restart);
00449 
00450    if (blen > 2) {
00451       breaks = alloca(blen + 1);
00452       breaks[0] = '\0';
00453       if (stop)
00454          strcat(breaks, stop);
00455       if (pause)
00456          strcat(breaks, pause);
00457       if (restart)
00458          strcat(breaks, restart);
00459    }
00460    if (chan->_state != AST_STATE_UP)
00461       res = ast_answer(chan);
00462 
00463    if (file) {
00464       if ((end = strchr(file,':'))) {
00465          if (!strcasecmp(end, ":end")) {
00466             *end = '\0';
00467             end++;
00468          }
00469       }
00470    }
00471 
00472    for (;;) {
00473       ast_stopstream(chan);
00474       res = ast_streamfile(chan, file, chan->language);
00475       if (!res) {
00476          if (pause_restart_point) {
00477             ast_seekstream(chan->stream, pause_restart_point, SEEK_SET);
00478             pause_restart_point = 0;
00479          }
00480          else if (end) {
00481             ast_seekstream(chan->stream, 0, SEEK_END);
00482             end = NULL;
00483          };
00484          res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
00485       }
00486 
00487       if (res < 1)
00488          break;
00489 
00490       /* We go at next loop if we got the restart char */
00491       if (restart && strchr(restart, res)) {
00492          ast_log(LOG_DEBUG, "we'll restart the stream here at next loop\n");
00493          pause_restart_point = 0;
00494          continue;
00495       }
00496 
00497       if (pause && strchr(pause, res)) {
00498          pause_restart_point = ast_tellstream(chan->stream);
00499          for (;;) {
00500             ast_stopstream(chan);
00501             res = ast_waitfordigit(chan, 1000);
00502             if (!res)
00503                continue;
00504             else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
00505                break;
00506          }
00507          if (res == *pause) {
00508             res = 0;
00509             continue;
00510          }
00511       }
00512 
00513       if (res == -1)
00514          break;
00515 
00516       /* if we get one of our stop chars, return it to the calling function */
00517       if (stop && strchr(stop, res))
00518          break;
00519    }
00520 
00521    ast_stopstream(chan);
00522 
00523    return res;
00524 }

int ast_dtmf_stream struct ast_channel chan,
struct ast_channel peer,
char *  digits,
int  between
 

Send DTMF to chan (optionally entertain peer)

Definition at line 281 of file app.c.

References ast_autoservice_start(), AST_FRAME_DTMF, ast_log(), ast_safe_sleep(), ast_waitfor(), ast_write(), and LOG_WARNING.

Referenced by ast_bridge_call(), misdn_send_digit(), senddtmf_exec(), testclient_exec(), and testserver_exec().

00282 {
00283    char *ptr;
00284    int res = 0;
00285    struct ast_frame f;
00286    if (!between)
00287       between = 100;
00288 
00289    if (peer)
00290       res = ast_autoservice_start(peer);
00291 
00292    if (!res) {
00293       res = ast_waitfor(chan,100);
00294       if (res > -1) {
00295          for (ptr=digits; *ptr; ptr++) {
00296             if (*ptr == 'w') {
00297                res = ast_safe_sleep(chan, 500);
00298                if (res) 
00299                   break;
00300                continue;
00301             }
00302             memset(&f, 0, sizeof(f));
00303             f.frametype = AST_FRAME_DTMF;
00304             f.subclass = *ptr;
00305             f.src = "ast_dtmf_stream";
00306             if (strchr("0123456789*#abcdABCD",*ptr)==NULL) {
00307                ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
00308             } else {
00309                res = ast_write(chan, &f);
00310                if (res) 
00311                   break;
00312                /* pause between digits */
00313                res = ast_safe_sleep(chan,between);
00314                if (res) 
00315                   break;
00316             }
00317          }
00318       }
00319       if (peer) {
00320          /* Stop autoservice on the peer channel, but don't overwrite any error condition 
00321             that has occurred previously while acting on the primary channel */  
00322          if (ast_autoservice_stop(peer) && !res)
00323             res = -1;
00324       }
00325    }
00326    return res;
00327 }

void ast_install_vm_functions int(*)(const char *mailbox, const char *folder)  has_voicemail_func,
int(*)(const char *mailbox, int *newmsgs, int *oldmsgs)  messagecount_func
 

Definition at line 236 of file app.c.

References ast_has_voicemail_func, and ast_messagecount_func.

Referenced by load_module().

00238 {
00239    ast_has_voicemail_func = has_voicemail_func;
00240    ast_messagecount_func = messagecount_func;
00241 }

int ast_ivr_menu_run struct ast_channel c,
struct ast_ivr_menu menu,
void *  cbdata
 

Runs an IVR menu.

Returns:
returns 0 on successful completion, -1 on hangup, or -2 on user error in menu

Definition at line 1476 of file app.c.

References ast_ivr_menu_run_internal().

Referenced by skel_exec().

01477 {
01478    int res;
01479    res = ast_ivr_menu_run_internal(chan, menu, cbdata);
01480    /* Hide internal coding */
01481    if (res > 0)
01482       res = 0;
01483    return res;
01484 }

int ast_linear_stream struct ast_channel chan,
const char *  filename,
int  fd,
int  allowoverride
 

Stream a filename (or file descriptor) as a generator.

Definition at line 401 of file app.c.

References ast_activate_generator(), ast_config_AST_VAR_DIR, ast_log(), ast_strlen_zero(), linear_state::autoclose, linearstream, LOG_WARNING, and malloc.

00402 {
00403    struct linear_state *lin;
00404    char tmpf[256];
00405    int res = -1;
00406    int autoclose = 0;
00407    if (fd < 0) {
00408       if (ast_strlen_zero(filename))
00409          return -1;
00410       autoclose = 1;
00411       if (filename[0] == '/') 
00412          ast_copy_string(tmpf, filename, sizeof(tmpf));
00413       else
00414          snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_VAR_DIR, "sounds", filename);
00415       fd = open(tmpf, O_RDONLY);
00416       if (fd < 0){
00417          ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
00418          return -1;
00419       }
00420    }
00421    lin = malloc(sizeof(struct linear_state));
00422    if (lin) {
00423       memset(lin, 0, sizeof(lin));
00424       lin->fd = fd;
00425       lin->allowoverride = allowoverride;
00426       lin->autoclose = autoclose;
00427       res = ast_activate_generator(chan, &linearstream, lin);
00428    }
00429    return res;
00430 }

enum AST_LOCK_RESULT ast_lock_path const char *  path  ) 
 

Lock a filesystem path.

Parameters:
path the path to be locked
Returns:
one of AST_LOCK_RESULT values

Definition at line 1135 of file app.c.

References AST_LOCK_FAILURE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), LOG_WARNING, and s.

Referenced by vm_lock_path().

01136 {
01137    char *s;
01138    char *fs;
01139    int res;
01140    int fd;
01141    time_t start;
01142 
01143    s = alloca(strlen(path) + 10);
01144    fs = alloca(strlen(path) + 20);
01145 
01146    if (!fs || !s) {
01147       ast_log(LOG_WARNING, "Out of memory!\n");
01148       return AST_LOCK_FAILURE;
01149    }
01150 
01151    snprintf(fs, strlen(path) + 19, "%s/.lock-%08x", path, rand());
01152    fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
01153    if (fd < 0) {
01154       fprintf(stderr, "Unable to create lock file '%s': %s\n", path, strerror(errno));
01155       return AST_LOCK_PATH_NOT_FOUND;
01156    }
01157    close(fd);
01158 
01159    snprintf(s, strlen(path) + 9, "%s/.lock", path);
01160    time(&start);
01161    while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
01162       usleep(1);
01163    if (res) {
01164       ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
01165       return AST_LOCK_TIMEOUT;
01166    } else {
01167       unlink(fs);
01168       ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
01169       return AST_LOCK_SUCCESS;
01170    }
01171 }

int ast_play_and_prepend struct ast_channel chan,
char *  playfile,
char *  recordfile,
int  maxtime_sec,
char *  fmt,
int *  duration,
int  beep,
int  silencethreshold,
int  maxsilence_ms
 

Record a message and prepend the message to the given record file after playing the optional playfile (or a beep), storing the duration in 'duration' and with a maximum
permitted silence time in milliseconds of 'maxsilence' under 'silencethreshold' or use '-1' for either or both parameters for defaults.

Definition at line 765 of file app.c.

References ast_log(), ast_play_and_wait(), ast_strdupa, ast_streamfile(), ast_verbose(), ast_waitstream(), ast_writefile(), ast_channel::language, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, strsep(), ast_dsp::totalsilence, and VERBOSE_PREFIX_3.

Referenced by vm_forwardoptions().

00766 {
00767    int d = 0;
00768    char *fmts;
00769    char comment[256];
00770    int x, fmtcnt=1, res=-1,outmsg=0;
00771    struct ast_frame *f;
00772    struct ast_filestream *others[MAX_OTHER_FORMATS];
00773    struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
00774    char *sfmt[MAX_OTHER_FORMATS];
00775    char *stringp=NULL;
00776    time_t start, end;
00777    struct ast_dsp *sildet;    /* silence detector dsp */
00778    int totalsilence = 0;
00779    int dspsilence = 0;
00780    int rfmt=0; 
00781    char prependfile[80];
00782    
00783    if (silencethreshold < 0)
00784       silencethreshold = global_silence_threshold;
00785 
00786    if (maxsilence < 0)
00787       maxsilence = global_maxsilence;
00788 
00789    /* barf if no pointer passed to store duration in */
00790    if (duration == NULL) {
00791       ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n");
00792       return -1;
00793    }
00794 
00795    ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
00796    snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
00797 
00798    if (playfile || beep) { 
00799       if (!beep)
00800          d = ast_play_and_wait(chan, playfile);
00801       if (d > -1)
00802          d = ast_streamfile(chan, "beep",chan->language);
00803       if (!d)
00804          d = ast_waitstream(chan,"");
00805       if (d < 0)
00806          return -1;
00807    }
00808    ast_copy_string(prependfile, recordfile, sizeof(prependfile)); 
00809    strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
00810          
00811    fmts = ast_strdupa(fmt);
00812    
00813    stringp=fmts;
00814    strsep(&stringp, "|");
00815    ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);   
00816    sfmt[0] = ast_strdupa(fmts);
00817    
00818    while((fmt = strsep(&stringp, "|"))) {
00819       if (fmtcnt > MAX_OTHER_FORMATS - 1) {
00820          ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n");
00821          break;
00822       }
00823       sfmt[fmtcnt++] = ast_strdupa(fmt);
00824    }
00825 
00826    time(&start);
00827    end=start;  /* pre-initialize end to be same as start in case we never get into loop */
00828    for (x=0;x<fmtcnt;x++) {
00829       others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700);
00830       ast_verbose( VERBOSE_PREFIX_3 "x=%d, open writing:  %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]);
00831       if (!others[x]) {
00832          break;
00833       }
00834    }
00835    
00836    sildet = ast_dsp_new(); /* Create the silence detector */
00837    if (!sildet) {
00838       ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00839       return -1;
00840    }
00841    ast_dsp_set_threshold(sildet, silencethreshold);
00842 
00843    if (maxsilence > 0) {
00844       rfmt = chan->readformat;
00845       res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00846       if (res < 0) {
00847          ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00848          ast_dsp_free(sildet);
00849          return -1;
00850       }
00851    }
00852                   
00853    if (x == fmtcnt) {
00854    /* Loop forever, writing the packets we read to the writer(s), until
00855       we read a # or get a hangup */
00856       f = NULL;
00857       for(;;) {
00858          res = ast_waitfor(chan, 2000);
00859          if (!res) {
00860             ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
00861             /* Try one more time in case of masq */
00862             res = ast_waitfor(chan, 2000);
00863             if (!res) {
00864                ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
00865                res = -1;
00866             }
00867          }
00868          
00869          if (res < 0) {
00870             f = NULL;
00871             break;
00872          }
00873          f = ast_read(chan);
00874          if (!f)
00875             break;
00876          if (f->frametype == AST_FRAME_VOICE) {
00877             /* write each format */
00878             for (x=0;x<fmtcnt;x++) {
00879                if (!others[x])
00880                   break;
00881                res = ast_writestream(others[x], f);
00882             }
00883             
00884             /* Silence Detection */
00885             if (maxsilence > 0) {
00886                dspsilence = 0;
00887                ast_dsp_silence(sildet, f, &dspsilence);
00888                if (dspsilence)
00889                   totalsilence = dspsilence;
00890                else
00891                   totalsilence = 0;
00892                
00893                if (totalsilence > maxsilence) {
00894                /* Ended happily with silence */
00895                if (option_verbose > 2) 
00896                   ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
00897                ast_frfree(f);
00898                res = 'S';
00899                outmsg=2;
00900                break;
00901                }
00902             }
00903             /* Exit on any error */
00904             if (res) {
00905                ast_log(LOG_WARNING, "Error writing frame\n");
00906                ast_frfree(f);
00907                break;
00908             }
00909          } else if (f->frametype == AST_FRAME_VIDEO) {
00910             /* Write only once */
00911             ast_writestream(others[0], f);
00912          } else if (f->frametype == AST_FRAME_DTMF) {
00913             /* stop recording with any digit */
00914             if (option_verbose > 2) 
00915                ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
00916             res = 't';
00917             outmsg = 2;
00918             ast_frfree(f);
00919             break;
00920          }
00921          if (maxtime) {
00922             time(&end);
00923             if (maxtime < (end - start)) {
00924                if (option_verbose > 2)
00925                   ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
00926                res = 't';
00927                outmsg=2;
00928                ast_frfree(f);
00929                break;
00930             }
00931          }
00932          ast_frfree(f);
00933       }
00934       if (end == start) time(&end);
00935       if (!f) {
00936          if (option_verbose > 2) 
00937             ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
00938          res = -1;
00939          outmsg=1;
00940 #if 0
00941          /* delete all the prepend files */
00942          for (x=0;x<fmtcnt;x++) {
00943             if (!others[x])
00944                break;
00945             ast_closestream(others[x]);
00946             ast_filedelete(prependfile, sfmt[x]);
00947          }
00948 #endif
00949       }
00950    } else {
00951       ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); 
00952    }
00953    ast_dsp_free(sildet);
00954    *duration = end - start;
00955 #if 0
00956    if (outmsg > 1) {
00957 #else
00958    if (outmsg) {
00959 #endif
00960       struct ast_frame *fr;
00961       for (x=0;x<fmtcnt;x++) {
00962          snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
00963          realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
00964          if (!others[x] || !realfiles[x])
00965             break;
00966          if (totalsilence)
00967             ast_stream_rewind(others[x], totalsilence-200);
00968          else
00969             ast_stream_rewind(others[x], 200);
00970          ast_truncstream(others[x]);
00971          /* add the original file too */
00972          while ((fr = ast_readframe(realfiles[x]))) {
00973             ast_writestream(others[x],fr);
00974          }
00975          ast_closestream(others[x]);
00976          ast_closestream(realfiles[x]);
00977          ast_filerename(prependfile, recordfile, sfmt[x]);
00978 #if 0
00979          ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile);
00980 #endif
00981          ast_filedelete(prependfile, sfmt[x]);
00982       }
00983    }
00984    if (rfmt) {
00985       if (ast_set_read_format(chan, rfmt)) {
00986          ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00987       }
00988    }
00989    if (outmsg) {
00990       if (outmsg > 1) {
00991          /* Let them know it worked */
00992          ast_streamfile(chan, "auth-thankyou", chan->language);
00993          ast_waitstream(chan, "");
00994       }
00995    }  
00996    return res;
00997 }

int ast_play_and_record struct ast_channel chan,
const char *  playfile,
const char *  recordfile,
int  maxtime_sec,
const char *  fmt,
int *  duration,
int  silencethreshold,
int  maxsilence_ms,
const char *  path
 

Record a file for a max amount of time (in seconds), in a given list of formats separated by '|', outputting the duration of the recording, and with a maximum
permitted silence time in milliseconds of 'maxsilence' under 'silencethreshold' or use '-1' for either or both parameters for defaults. calls ast_unlock_path() on 'path' if passed

Definition at line 540 of file app.c.

References ast_log(), ast_play_and_wait(), ast_strdupa, ast_streamfile(), ast_verbose(), ast_waitstream(), ast_writefile(), ast_channel::language, LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, strsep(), ast_dsp::totalsilence, and VERBOSE_PREFIX_3.

Referenced by ast_record_review(), dial_exec_full(), and play_record_review().

00541 {
00542    int d;
00543    char *fmts;
00544    char comment[256];
00545    int x, fmtcnt=1, res=-1,outmsg=0;
00546    struct ast_frame *f;
00547    struct ast_filestream *others[MAX_OTHER_FORMATS];
00548    char *sfmt[MAX_OTHER_FORMATS];
00549    char *stringp=NULL;
00550    time_t start, end;
00551    struct ast_dsp *sildet=NULL;     /* silence detector dsp */
00552    int totalsilence = 0;
00553    int dspsilence = 0;
00554    int rfmt=0;
00555    struct ast_silence_generator *silgen = NULL;
00556 
00557    if (silencethreshold < 0)
00558       silencethreshold = global_silence_threshold;
00559 
00560    if (maxsilence < 0)
00561       maxsilence = global_maxsilence;
00562 
00563    /* barf if no pointer passed to store duration in */
00564    if (duration == NULL) {
00565       ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
00566       return -1;
00567    }
00568 
00569    ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
00570    snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
00571 
00572    if (playfile) {
00573       d = ast_play_and_wait(chan, playfile);
00574       if (d > -1)
00575          d = ast_streamfile(chan, "beep",chan->language);
00576       if (!d)
00577          d = ast_waitstream(chan,"");
00578       if (d < 0)
00579          return -1;
00580    }
00581 
00582    fmts = ast_strdupa(fmt);
00583 
00584    stringp=fmts;
00585    strsep(&stringp, "|");
00586    ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
00587    sfmt[0] = ast_strdupa(fmts);
00588 
00589    while((fmt = strsep(&stringp, "|"))) {
00590       if (fmtcnt > MAX_OTHER_FORMATS - 1) {
00591          ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n");
00592          break;
00593       }
00594       sfmt[fmtcnt++] = ast_strdupa(fmt);
00595    }
00596 
00597    time(&start);
00598    end=start;  /* pre-initialize end to be same as start in case we never get into loop */
00599    for (x=0;x<fmtcnt;x++) {
00600       others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
00601       ast_verbose( VERBOSE_PREFIX_3 "x=%d, open writing:  %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);
00602 
00603       if (!others[x]) {
00604          break;
00605       }
00606    }
00607 
00608    if (path)
00609       ast_unlock_path(path);
00610 
00611    if (maxsilence > 0) {
00612       sildet = ast_dsp_new(); /* Create the silence detector */
00613       if (!sildet) {
00614          ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00615          return -1;
00616       }
00617       ast_dsp_set_threshold(sildet, silencethreshold);
00618       rfmt = chan->readformat;
00619       res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00620       if (res < 0) {
00621          ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00622          ast_dsp_free(sildet);
00623          return -1;
00624       }
00625    }
00626 
00627    /* Request a video update */
00628    ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00629 
00630    if (option_transmit_silence_during_record)
00631       silgen = ast_channel_start_silence_generator(chan);
00632 
00633    if (x == fmtcnt) {
00634    /* Loop forever, writing the packets we read to the writer(s), until
00635       we read a # or get a hangup */
00636       f = NULL;
00637       for(;;) {
00638          res = ast_waitfor(chan, 2000);
00639          if (!res) {
00640             ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
00641             /* Try one more time in case of masq */
00642             res = ast_waitfor(chan, 2000);
00643             if (!res) {
00644                ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
00645                res = -1;
00646             }
00647          }
00648 
00649          if (res < 0) {
00650             f = NULL;
00651             break;
00652          }
00653          f = ast_read(chan);
00654          if (!f)
00655             break;
00656          if (f->frametype == AST_FRAME_VOICE) {
00657             /* write each format */
00658             for (x=0;x<fmtcnt;x++) {
00659                res = ast_writestream(others[x], f);
00660             }
00661 
00662             /* Silence Detection */
00663             if (maxsilence > 0) {
00664                dspsilence = 0;
00665                ast_dsp_silence(sildet, f, &dspsilence);
00666                if (dspsilence)
00667                   totalsilence = dspsilence;
00668                else
00669                   totalsilence = 0;
00670 
00671                if (totalsilence > maxsilence) {
00672                   /* Ended happily with silence */
00673                   if (option_verbose > 2)
00674                      ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
00675                   ast_frfree(f);
00676                   res = 'S';
00677                   outmsg=2;
00678                   break;
00679                }
00680             }
00681             /* Exit on any error */
00682             if (res) {
00683                ast_log(LOG_WARNING, "Error writing frame\n");
00684                ast_frfree(f);
00685                break;
00686             }
00687          } else if (f->frametype == AST_FRAME_VIDEO) {
00688             /* Write only once */
00689             ast_writestream(others[0], f);
00690          } else if (f->frametype == AST_FRAME_DTMF) {
00691             if (f->subclass == '#') {
00692                if (option_verbose > 2)
00693                   ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
00694                res = '#';
00695                outmsg = 2;
00696                ast_frfree(f);
00697                break;
00698             }
00699             if (f->subclass == '0') {
00700             /* Check for a '0' during message recording also, in case caller wants operator */
00701                if (option_verbose > 2)
00702                   ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass);
00703                res = '0';
00704                outmsg = 0;
00705                ast_frfree(f);
00706                break;
00707             }
00708          }
00709          if (maxtime) {
00710             time(&end);
00711             if (maxtime < (end - start)) {
00712                if (option_verbose > 2)
00713                   ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
00714                outmsg = 2;
00715                res = 't';
00716                ast_frfree(f);
00717                break;
00718             }
00719          }
00720          ast_frfree(f);
00721       }
00722       if (end == start) time(&end);
00723       if (!f) {
00724          if (option_verbose > 2)
00725             ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
00726          res = -1;
00727          outmsg=1;
00728       }
00729    } else {
00730       ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
00731    }
00732 
00733    if (silgen)
00734       ast_channel_stop_silence_generator(chan, silgen);
00735 
00736    *duration = end - start;
00737 
00738    for (x=0;x<fmtcnt;x++) {
00739       if (!others[x])
00740          break;
00741       if (res > 0) {
00742          if (totalsilence)
00743             ast_stream_rewind(others[x], totalsilence-200);
00744          else
00745             ast_stream_rewind(others[x], 200);
00746       }
00747       ast_truncstream(others[x]);
00748       ast_closestream(others[x]);
00749    }
00750    if (rfmt) {
00751       if (ast_set_read_format(chan, rfmt)) {
00752          ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00753       }
00754    }
00755    if (outmsg > 1) {
00756       /* Let them know recording is stopped */
00757       if(!ast_streamfile(chan, "auth-thankyou", chan->language))
00758          ast_waitstream(chan, "");
00759    }
00760    if (sildet)
00761       ast_dsp_free(sildet);
00762    return res;
00763 }

int ast_play_and_wait struct ast_channel chan,
const char *  fn
 

Play a stream and wait for a digit, returning the digit that was pressed

Definition at line 526 of file app.c.

References AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), ast_waitstream(), and ast_channel::language.

Referenced by advanced_options(), ast_play_and_prepend(), ast_play_and_record(), ast_record_review(), dialout(), forward_message(), get_folder(), get_folder2(), leave_voicemail(), play_message_category(), play_record_review(), vm_authenticate(), vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_execmain(), vm_forwardoptions(), vm_instructions(), vm_intro_cz(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_gr(), vm_intro_it(), vm_intro_nl(), vm_intro_no(), vm_intro_pt(), vm_intro_se(), vm_newuser(), vm_options(), vm_play_folder_name(), vm_play_folder_name_gr(), vm_tempgreeting(), and vmauthenticate().

00527 {
00528    int d;
00529    d = ast_streamfile(chan, fn, chan->language);
00530    if (d)
00531       return d;
00532    d = ast_waitstream(chan, AST_DIGIT_ANY);
00533    ast_stopstream(chan);
00534    return d;
00535 }

char* ast_read_textfile const char *  file  ) 
 

Read a file into asterisk

Definition at line 1486 of file app.c.

References ast_log(), free, LOG_WARNING, and malloc.

Referenced by readfile_exec().

01487 {
01488    int fd;
01489    char *output=NULL;
01490    struct stat filesize;
01491    int count=0;
01492    int res;
01493    if(stat(filename,&filesize)== -1){
01494       ast_log(LOG_WARNING,"Error can't stat %s\n", filename);
01495       return NULL;
01496    }
01497    count=filesize.st_size + 1;
01498    fd = open(filename, O_RDONLY);
01499    if (fd < 0) {
01500       ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
01501       return NULL;
01502    }
01503    output=(char *)malloc(count);
01504    if (output) {
01505       res = read(fd, output, count - 1);
01506       if (res == count - 1) {
01507          output[res] = '\0';
01508       } else {
01509          ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count -  1, strerror(errno));
01510          free(output);
01511          output = NULL;
01512       }
01513    } else 
01514       ast_log(LOG_WARNING, "Out of memory!\n");
01515    close(fd);
01516    return output;
01517 }

int ast_record_review struct ast_channel chan,
const char *  playfile,
const char *  recordfile,
int  maxtime,
const char *  fmt,
int *  duration,
const char *  path
 

Allow to record message and have a review option

Definition at line 1184 of file app.c.

References AST_DIGIT_ANY, ast_log(), ast_play_and_record(), ast_play_and_wait(), ast_streamfile(), ast_verbose(), ast_waitfordigit(), ast_waitstream(), ast_channel::language, LOG_WARNING, maxsilence, silencethreshold, and VERBOSE_PREFIX_3.

Referenced by conf_run().

01185 {
01186    int silencethreshold = 128; 
01187    int maxsilence=0;
01188    int res = 0;
01189    int cmd = 0;
01190    int max_attempts = 3;
01191    int attempts = 0;
01192    int recorded = 0;
01193    int message_exists = 0;
01194    /* Note that urgent and private are for flagging messages as such in the future */
01195 
01196    /* barf if no pointer passed to store duration in */
01197    if (duration == NULL) {
01198       ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
01199       return -1;
01200    }
01201 
01202    cmd = '3';   /* Want to start by recording */
01203 
01204    while ((cmd >= 0) && (cmd != 't')) {
01205       switch (cmd) {
01206       case '1':
01207          if (!message_exists) {
01208             /* In this case, 1 is to record a message */
01209             cmd = '3';
01210             break;
01211          } else {
01212             ast_streamfile(chan, "vm-msgsaved", chan->language);
01213             ast_waitstream(chan, "");
01214             cmd = 't';
01215             return res;
01216          }
01217       case '2':
01218          /* Review */
01219          ast_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n");
01220          ast_streamfile(chan, recordfile, chan->language);
01221          cmd = ast_waitstream(chan, AST_DIGIT_ANY);
01222          break;
01223       case '3':
01224          message_exists = 0;
01225          /* Record */
01226          if (recorded == 1)
01227             ast_verbose(VERBOSE_PREFIX_3 "Re-recording\n");
01228          else  
01229             ast_verbose(VERBOSE_PREFIX_3 "Recording\n");
01230          recorded = 1;
01231          cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path);
01232          if (cmd == -1) {
01233          /* User has hung up, no options to give */
01234             return cmd;
01235          }
01236          if (cmd == '0') {
01237             break;
01238          } else if (cmd == '*') {
01239             break;
01240          } 
01241          else {
01242             /* If all is well, a message exists */
01243             message_exists = 1;
01244             cmd = 0;
01245          }
01246          break;
01247       case '4':
01248       case '5':
01249       case '6':
01250       case '7':
01251       case '8':
01252       case '9':
01253       case '*':
01254       case '#':
01255          cmd = ast_play_and_wait(chan, "vm-sorry");
01256          break;
01257       default:
01258          if (message_exists) {
01259             cmd = ast_play_and_wait(chan, "vm-review");
01260          }
01261          else {
01262             cmd = ast_play_and_wait(chan, "vm-torerecord");
01263             if (!cmd)
01264                cmd = ast_waitfordigit(chan, 600);
01265          }
01266          
01267          if (!cmd)
01268             cmd = ast_waitfordigit(chan, 6000);
01269          if (!cmd) {
01270             attempts++;
01271          }
01272          if (attempts > max_attempts) {
01273             cmd = 't';
01274          }
01275       }
01276    }
01277    if (cmd == 't')
01278       cmd = 0;
01279    return cmd;
01280 }

int ast_safe_system const char *  s  ) 
 

Safely spawn an external program while closing file descriptors

Note:
This replaces the system call in all Asterisk modules

Definition at line 424 of file asterisk.c.

References ast_mutex_lock(), ast_mutex_unlock(), and null_sig_handler().

Referenced by alarmreceiver_exec(), ast_closestream(), ast_monitor_change_fname(), ast_monitor_start(), ast_monitor_stop(), consolehandler(), forward_message(), process_text_line(), remoteconsolehandler(), run_externnotify(), sendmail(), sendpage(), system_exec_helper(), and vm_change_password_shell().

00425 {
00426    pid_t pid;
00427    int x;
00428    int res;
00429    struct rusage rusage;
00430    int status;
00431    unsigned int level;
00432 
00433    /* keep track of how many ast_safe_system() functions
00434       are running at this moment
00435    */
00436    ast_mutex_lock(&safe_system_lock);
00437    level = safe_system_level++;
00438 
00439    /* only replace the handler if it has not already been done */
00440    if (level == 0)
00441       safe_system_prev_handler = signal(SIGCHLD, null_sig_handler);
00442 
00443    ast_mutex_unlock(&safe_system_lock);
00444 
00445    pid = fork();
00446 
00447    if (pid == 0) {
00448       /* Close file descriptors and launch system command */
00449       for (x = STDERR_FILENO + 1; x < 4096; x++)
00450          close(x);
00451       execl("/bin/sh", "/bin/sh", "-c", s, NULL);
00452       exit(1);
00453    } else if (pid > 0) {
00454       for(;;) {
00455          res = wait4(pid, &status, 0, &rusage);
00456          if (res > -1) {
00457             res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
00458             break;
00459          } else if (errno != EINTR) 
00460             break;
00461       }
00462    } else {
00463       ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
00464       res = -1;
00465    }
00466 
00467    ast_mutex_lock(&safe_system_lock);
00468    level = --safe_system_level;
00469 
00470    /* only restore the handler if we are the last one */
00471    if (level == 0)
00472       signal(SIGCHLD, safe_system_prev_handler);
00473 
00474    ast_mutex_unlock(&safe_system_lock);
00475 
00476    return res;
00477 }

void ast_uninstall_vm_functions void   ) 
 

Definition at line 243 of file app.c.

References ast_has_voicemail_func, and ast_messagecount_func.

Referenced by unload_module().

00244 {
00245    ast_has_voicemail_func = NULL;
00246    ast_messagecount_func = NULL;
00247 }

int ast_unlock_path const char *  path  ) 
 

Unlock a path

Definition at line 1173 of file app.c.

References ast_log(), and s.

Referenced by copy_message(), count_messages(), and leave_voicemail().

01174 {
01175    char *s;
01176    s = alloca(strlen(path) + 10);
01177    if (!s)
01178       return -1;
01179    snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
01180    ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
01181    return unlink(s);
01182 }


Generated on Sat Mar 24 23:26:10 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.6