Mon Mar 20 08:25:45 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

app.h File Reference

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

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_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
 

Enumeration values:
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
 

Enumeration values:
AST_LOCK_SUCCESS 
AST_LOCK_TIMEOUT 
AST_LOCK_PATH_NOT_FOUND 
AST_LOCK_FAILURE 

Definition at line 147 of file app.h.

Referenced by ast_lock_path().

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_exists_extension(), ast_get_indication_tone(), ast_ignore_pattern(), ast_log(), ast_matchmore_extension(), ast_playtones_start(), ast_playtones_stop(), ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, 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, ast_pbx::rtimeout, and s.

Referenced by __login_exec(), auth_exec(), conf_exec(), dictate_exec(), find_conf(), 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(), ast_channel::language, and s.

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_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, ast_frfree(), ast_log(), ast_read(), ast_set_read_format(), ast_streamfile(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_frame::frametype, ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::name, ast_channel::readformat, ast_frame::samples, and ast_frame::subclass.

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 1046 of file app.c.

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

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

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

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 1071 of file app.c.

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

Referenced by group_match_count_exec(), and group_match_count_function_read().

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

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 1032 of file app.c.

References ast_app_group_split_group(), and pbx_builtin_setvar_helper().

Referenced by dial_exec_full(), group_function_write(), and group_set_exec().

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

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 1003 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().

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

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(), do_monitor(), 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 1521 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().

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

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 1103 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().

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

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_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_autoservice_stop(), ast_log(), ast_safe_sleep(), ast_waitfor(), ast_write(), ast_frame::frametype, LOG_WARNING, ast_frame::src, and ast_frame::subclass.

Referenced by ast_bridge_call(), dial_exec_full(), 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 1478 of file app.c.

References ast_ivr_menu_run_internal().

Referenced by skel_exec().

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

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 linear_state::allowoverride, ast_activate_generator(), ast_config_AST_VAR_DIR, ast_log(), ast_strlen_zero(), linear_state::autoclose, linear_state::fd, 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 1137 of file app.c.

References AST_LOCK_RESULT, ast_log(), LOG_DEBUG, LOG_WARNING, and s.

Referenced by vm_lock_path().

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

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 766 of file app.c.

References ast_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), ast_filedelete(), ast_filerename(), AST_FORMAT_SLINEAR, ast_frfree(), ast_getformatname(), ast_log(), ast_play_and_wait(), ast_read(), ast_readfile(), ast_readframe(), ast_set_read_format(), ast_strdupa, ast_stream_rewind(), ast_streamfile(), ast_truncstream(), ast_verbose(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), fmt, ast_frame::frametype, ast_channel::language, LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, option_verbose, ast_channel::readformat, strsep(), ast_frame::subclass, and VERBOSE_PREFIX_3.

Referenced by vm_forwardoptions().

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

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

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(), dial_exec_full(), 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 1488 of file app.c.

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

Referenced by readfile_exec().

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

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 1186 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(), fmt, ast_channel::language, LOG_WARNING, and VERBOSE_PREFIX_3.

Referenced by conf_run().

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

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 422 of file asterisk.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, null_sig_handler(), s, safe_system_level, and safe_system_prev_handler.

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

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

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 1175 of file app.c.

References ast_log(), LOG_DEBUG, and s.

Referenced by ast_play_and_record(), close_mailbox(), copy_message(), count_messages(), last_message_index(), leave_voicemail(), resequence_mailbox(), and save_to_folder().

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


Generated on Mon Mar 20 08:25:45 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1