Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:00:59 2007

Asterisk developer's documentation :: Codename Pineapple


app.c File Reference


Detailed Description

Convenient Application Routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file app.c.

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/indications.h"

Include dependency graph for app.c:

Go to the source code of this file.

Data Structures

struct  linear_state

Defines

#define MAX_OTHER_FORMATS   10
#define RES_EXIT   (1 << 17)
#define RES_REPEAT   (1 << 18)
#define RES_RESTART   ((1 << 19) | RES_REPEAT)
#define RES_UPONE   (1 << 16)

Functions

static int __ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf)
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, const 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_group_get_count (const char *group, const char *category)
int ast_app_group_match_get_count (const char *groupmatch, const char *category)
int ast_app_group_set_channel (struct ast_channel *chan, const char *data)
int ast_app_group_split_group (const 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_inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs)
int ast_app_messagecount (const char *context, const char *mailbox, const char *folder)
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, const char *digits, int between)
 Send DTMF to a channel.
void ast_install_vm_functions (int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs), int(*messagecount_func)(const char *context, const char *mailbox, const char *folder))
int ast_ivr_menu_run (struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
 Runs an IVR menu.
static int ast_ivr_menu_run_internal (struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
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, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
int ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
int ast_play_and_record_full (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf)
int ast_play_and_wait (struct ast_channel *chan, const char *fn)
char * ast_read_textfile (const char *filename)
int ast_record_review (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
void ast_uninstall_vm_functions (void)
int ast_unlock_path (const char *path)
static int ivr_dispatch (struct ast_channel *chan, struct ast_ivr_option *option, char *exten, void *cbdata)
static void * linear_alloc (struct ast_channel *chan, void *params)
static int linear_generator (struct ast_channel *chan, void *data, int len, int samples)
static void linear_release (struct ast_channel *chan, void *params)
static int option_exists (struct ast_ivr_menu *menu, char *option)
static int option_matchmore (struct ast_ivr_menu *menu, char *option)
static int read_newoption (struct ast_channel *chan, struct ast_ivr_menu *menu, char *exten, int maxexten)

Variables

static int(* ast_has_voicemail_func )(const char *mailbox, const char *folder) = NULL
static int(* ast_inboxcount_func )(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL
static int(* ast_messagecount_func )(const char *context, const char *mailbox, const char *folder) = NULL
static char default_acceptdtmf [] = "#"
static char default_canceldtmf [] = ""
static int global_maxsilence = 0
static int global_silence_threshold = 128
static struct ast_generator linearstream


Define Documentation

#define MAX_OTHER_FORMATS   10
 

Definition at line 53 of file app.c.

Referenced by __ast_play_and_record().

#define RES_EXIT   (1 << 17)
 

Definition at line 1089 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_REPEAT   (1 << 18)
 

Definition at line 1090 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_RESTART   ((1 << 19) | RES_REPEAT)
 

Definition at line 1091 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_UPONE   (1 << 16)
 

Definition at line 1088 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().


Function Documentation

static int __ast_play_and_record struct ast_channel chan,
const char *  playfile,
const char *  recordfile,
int  maxtime,
const char *  fmt,
int *  duration,
int  beep,
int  silencethreshold,
int  maxsilence,
const char *  path,
int  prepend,
const char *  acceptdtmf,
const char *  canceldtmf
[static]
 

Optionally play a sound file or a beep, then record audio and video from the channel.

Parameters:
chan Channel to playback to/record from.
playfile Filename of sound to play before recording begins.
recordfile Filename to record to.
maxtime Maximum length of recording (in milliseconds).
fmt Format(s) to record message in. Multiple formats may be specified by separating them with a '|'.
duration Where to store actual length of the recorded message (in milliseconds).
beep Whether to play a beep before starting to record.
silencethreshold 
maxsilence Length of silence that will end a recording (in milliseconds).
path Optional filesystem path to unlock.
prepend If true, prepend the recorded audio to an existing file.
acceptdtmf DTMF digits that will end the recording.
canceldtmf DTMF digits that will cancel the recording.

Definition at line 510 of file app.c.

References AST_FILE_MODE, ast_log(), ast_play_and_wait(), ast_strdupa, ast_stream_and_wait(), ast_verbose(), ast_writefile(), LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, option_debug, option_verbose, strsep(), ast_dsp::totalsilence, and VERBOSE_PREFIX_3.

Referenced by ast_play_and_prepend(), ast_play_and_record(), and ast_play_and_record_full().

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

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 63 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(), ind_tone_zone_sound::data, ast_pbx::dtimeout, LOG_NOTICE, ast_channel::pbx, and ast_channel::zone.

Referenced by builtin_atxfer(), and builtin_blindtransfer().

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

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

Plays a stream and gets DTMF data from a channel.

Parameters:
c The channel to read from
prompt The file to stream to the channel
s The string to read in to. Must be at least the size of your length
maxlen How many digits to read (maximum)
timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for "ludicrous time" (essentially never times out)

Definition at line 108 of file app.c.

References ast_readstring(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_pbx::dtimeout, ast_channel::pbx, ast_pbx::rtimeout, and strsep().

Referenced by __login_exec().

00109 {
00110    int res = 0, to, fto;
00111    char *front, *filename;
00112 
00113    /* XXX Merge with full version? XXX */
00114    
00115    if (maxlen)
00116       s[0] = '\0';
00117 
00118    if (!prompt)
00119       prompt="";
00120 
00121    filename = ast_strdupa(prompt);
00122    while ((front = strsep(&filename, "&"))) {
00123       if (!ast_strlen_zero(front)) {
00124          res = ast_streamfile(c, front, c->language);
00125          if (res)
00126             continue;
00127       }
00128       if (ast_strlen_zero(filename)) {
00129          /* set timeouts for the last prompt */
00130          fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
00131          to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
00132 
00133          if (timeout > 0) 
00134             fto = to = timeout;
00135          if (timeout < 0) 
00136             fto = to = 1000000000;
00137       } else {
00138          /* there is more than one prompt, so
00139             get rid of the long timeout between 
00140             prompts, and make it 50ms */
00141          fto = 50;
00142          to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
00143       }
00144       res = ast_readstring(c, s, maxlen, to, fto, "#");
00145       if (!ast_strlen_zero(s))
00146          return res;
00147    }
00148    
00149    return res;
00150 }

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

References ast_readstring_full(), and ast_streamfile().

Referenced by handle_getdata().

00154 {
00155    int res, to, fto;
00156    if (prompt) {
00157       res = ast_streamfile(c, prompt, c->language);
00158       if (res < 0)
00159          return res;
00160    }
00161    fto = 6000;
00162    to = 2000;
00163    if (timeout > 0) 
00164       fto = to = timeout;
00165    if (timeout < 0) 
00166       fto = to = 1000000000;
00167    res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
00168    return res;
00169 }

int ast_app_group_get_count const char *  group,
const char *  category
 

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

Definition at line 832 of file app.c.

References ast_channel_unlock, ast_channel_walk_locked(), ast_strlen_zero(), GROUP_CATEGORY_PREFIX, pbx_builtin_getvar_helper(), s, and S_OR.

00833 {
00834    struct ast_channel *chan;
00835    int count = 0;
00836    const char *test;
00837    char cat[80];
00838    const char *s;
00839 
00840    if (ast_strlen_zero(group))
00841       return 0;
00842 
00843    s = S_OR(category, GROUP_CATEGORY_PREFIX);
00844    ast_copy_string(cat, s, sizeof(cat));
00845 
00846    chan = NULL;
00847    while ((chan = ast_channel_walk_locked(chan)) != NULL) {
00848       test = pbx_builtin_getvar_helper(chan, cat);
00849       if (test && !strcasecmp(test, group))
00850          count++;
00851       ast_channel_unlock(chan);
00852    }
00853 
00854    return count;
00855 }

int ast_app_group_match_get_count const char *  groupmatch,
const char *  category
 

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

Definition at line 857 of file app.c.

References ast_channel_unlock, ast_channel_walk_locked(), ast_strlen_zero(), GROUP_CATEGORY_PREFIX, pbx_builtin_getvar_helper(), s, and S_OR.

00858 {
00859    regex_t regexbuf;
00860    struct ast_channel *chan;
00861    int count = 0;
00862    const char *test;
00863    char cat[80];
00864    const char *s;
00865 
00866    if (ast_strlen_zero(groupmatch))
00867       return 0;
00868 
00869    /* if regex compilation fails, return zero matches */
00870    if (regcomp(&regexbuf, groupmatch, REG_EXTENDED | REG_NOSUB))
00871       return 0;
00872 
00873    s = S_OR(category, GROUP_CATEGORY_PREFIX);
00874    ast_copy_string(cat, s, sizeof(cat));
00875 
00876    chan = NULL;
00877    while ((chan = ast_channel_walk_locked(chan)) != NULL) {
00878       test = pbx_builtin_getvar_helper(chan, cat);
00879       if (test && !regexec(&regexbuf, test, 0, NULL, 0))
00880          count++;
00881       ast_channel_unlock(chan);
00882    }
00883 
00884    regfree(&regexbuf);
00885 
00886    return count;
00887 }

int ast_app_group_set_channel struct ast_channel chan,
const char *  data
 

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

Definition at line 818 of file app.c.

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

00819 {
00820    int res=0;
00821    char group[80] = "";
00822    char category[80] = "";
00823 
00824    if (!ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) {
00825       pbx_builtin_setvar_helper(chan, category, group);
00826    } else
00827       res = -1;
00828 
00829    return res;
00830 }

int ast_app_group_split_group const 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 789 of file app.c.

References ast_strlen_zero(), and GROUP_CATEGORY_PREFIX.

Referenced by ast_app_group_set_channel().

00790 {
00791    int res=0;
00792    char tmp[256];
00793    char *grp=NULL, *cat=NULL;
00794 
00795    if (!ast_strlen_zero(data)) {
00796       ast_copy_string(tmp, data, sizeof(tmp));
00797       grp = tmp;
00798       cat = strchr(tmp, '@');
00799       if (cat) {
00800          *cat = '\0';
00801          cat++;
00802       }
00803    }
00804 
00805    if (!ast_strlen_zero(grp))
00806       ast_copy_string(group, grp, group_max);
00807    else
00808       res = -1;
00809 
00810    if (cat)
00811       snprintf(category, category_max, "%s_%s", GROUP_CATEGORY_PREFIX, cat);
00812    else
00813       ast_copy_string(category, GROUP_CATEGORY_PREFIX, category_max);
00814 
00815    return res;
00816 }

int ast_app_has_voicemail const char *  mailbox,
const char *  folder
 

Determine if a given mailbox has any voicemail

Definition at line 191 of file app.c.

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

Referenced by action_mailboxstatus(), and has_voicemail().

00192 {
00193    static int warned = 0;
00194    if (ast_has_voicemail_func)
00195       return ast_has_voicemail_func(mailbox, folder);
00196 
00197    if ((option_verbose > 2) && !warned) {
00198       ast_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX");
00199       warned++;
00200    }
00201    return 0;
00202 }

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

Determine number of new/old messages in a mailbox

Definition at line 205 of file app.c.

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

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

00206 {
00207    static int warned = 0;
00208    if (newmsgs)
00209       *newmsgs = 0;
00210    if (oldmsgs)
00211       *oldmsgs = 0;
00212    if (ast_inboxcount_func)
00213       return ast_inboxcount_func(mailbox, newmsgs, oldmsgs);
00214 
00215    if (!warned && (option_verbose > 2)) {
00216       warned++;
00217       ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
00218    }
00219 
00220    return 0;
00221 }

int ast_app_messagecount const char *  context,
const char *  mailbox,
const char *  folder
 

Determine number of messages in a given mailbox and folder

Definition at line 223 of file app.c.

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

00224 {
00225    static int warned = 0;
00226    if (ast_messagecount_func)
00227       return ast_messagecount_func(context, mailbox, folder);
00228 
00229    if (!warned && (option_verbose > 2)) {
00230       warned++;
00231       ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s@%s/%s but voicemail not loaded.\n", mailbox, context, folder);
00232    }
00233 
00234    return 0;
00235 }

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 1324 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 pbx_builtin_background(), pbx_builtin_resetcdr(), and pbx_builtin_waitexten().

01325 {
01326    char *s;
01327    int curarg;
01328    unsigned int argloc;
01329    char *arg;
01330    int res = 0;
01331 
01332    ast_clear_flag(flags, AST_FLAGS_ALL);
01333 
01334    if (!optstr)
01335       return 0;
01336 
01337    s = optstr;
01338    while (*s) {
01339       curarg = *s++ & 0x7f;   /* the array (in app.h) has 128 entries */
01340       ast_set_flag(flags, options[curarg].flag);
01341       argloc = options[curarg].arg_index;
01342       if (*s == '(') {
01343          /* Has argument */
01344          arg = ++s;
01345          if ((s = strchr(s, ')'))) {
01346             if (argloc)
01347                args[argloc - 1] = arg;
01348             *s++ = '\0';
01349          } else {
01350             ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
01351             res = -1;
01352             break;
01353          }
01354       } else if (argloc) {
01355          args[argloc - 1] = NULL;
01356       }
01357    }
01358 
01359    return res;
01360 }

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

Referenced by pbx_builtin_setvar().

00890 {
00891    int argc;
00892    char *scan;
00893    int paren = 0, quote = 0;
00894 
00895    if (!buf || !array || !arraylen)
00896       return 0;
00897 
00898    memset(array, 0, arraylen * sizeof(*array));
00899 
00900    scan = buf;
00901 
00902    for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
00903       array[argc] = scan;
00904       for (; *scan; scan++) {
00905          if (*scan == '(')
00906             paren++;
00907          else if (*scan == ')') {
00908             if (paren)
00909                paren--;
00910          } else if (*scan == '"' && delim != '"') {
00911             quote = quote ? 0 : 1;
00912             /* Remove quote character from argument */
00913             memmove(scan, scan + 1, strlen(scan));
00914             scan--;
00915          } else if (*scan == '\\') {
00916             /* Literal character, don't parse */
00917             memmove(scan, scan + 1, strlen(scan));
00918          } else if ((*scan == delim) && !paren && !quote) {
00919             *scan++ = '\0';
00920             break;
00921          }
00922       }
00923    }
00924 
00925    if (*scan)
00926       array[argc++] = scan;
00927 
00928    return argc;
00929 }

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