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
 

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

Definition at line 385 of file app.c.

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

Referenced by handle_controlstreamfile().

00389 {
00390    char *breaks = NULL;
00391    char *end = NULL;
00392    int blen = 2;
00393    int res;
00394    long pause_restart_point = 0;
00395 
00396    if (stop)
00397       blen += strlen(stop);
00398    if (pause)
00399       blen += strlen(pause);
00400    if (restart)
00401       blen += strlen(restart);
00402 
00403    if (blen > 2) {
00404       breaks = alloca(blen + 1);
00405       breaks[0] = '\0';
00406       if (stop)
00407          strcat(breaks, stop);
00408       if (pause)
00409          strcat(breaks, pause);
00410       if (restart)
00411          strcat(breaks, restart);
00412    }
00413    if (chan->_state != AST_STATE_UP)
00414       res = ast_answer(chan);
00415 
00416    if (file) {
00417       if ((end = strchr(file,':'))) {
00418          if (!strcasecmp(end, ":end")) {
00419             *end = '\0';
00420             end++;
00421          }
00422       }
00423    }
00424 
00425    for (;;) {
00426       ast_stopstream(chan);
00427       res = ast_streamfile(chan, file, chan->language);
00428       if (!res) {
00429          if (pause_restart_point) {
00430             ast_seekstream(chan->stream, pause_restart_point, SEEK_SET);
00431             pause_restart_point = 0;
00432          }
00433          else if (end) {
00434             ast_seekstream(chan->stream, 0, SEEK_END);
00435             end = NULL;
00436          };
00437          res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
00438       }
00439 
00440       if (res < 1)
00441          break;
00442 
00443       /* We go at next loop if we got the restart char */
00444       if (restart && strchr(restart, res)) {
00445          if (option_debug)
00446             ast_log(LOG_DEBUG, "we'll restart the stream here at next loop\n");
00447          pause_restart_point = 0;
00448          continue;
00449       }
00450 
00451       if (pause && strchr(pause, res)) {
00452          pause_restart_point = ast_tellstream(chan->stream);
00453          for (;;) {
00454             ast_stopstream(chan);
00455             res = ast_waitfordigit(chan, 1000);
00456             if (!res)
00457                continue;
00458             else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
00459                break;
00460          }
00461          if (res == *pause) {
00462             res = 0;
00463             continue;
00464          }
00465       }
00466 
00467       if (res == -1)
00468          break;
00469 
00470       /* if we get one of our stop chars, return it to the calling function */
00471       if (stop && strchr(stop, res))
00472          break;
00473    }
00474 
00475    ast_stopstream(chan);
00476 
00477    return res;
00478 }

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

Send DTMF to a channel.

Parameters:
chan The channel that will receive the DTMF frames
peer (optional) Peer channel that will be autoserviced while the primary channel is receiving DTMF
digits This is a string of characters representing the DTMF digits to be sent to the channel. Valid characters are "0123456789*#abcdABCD". Note: You can pass arguments 'f' or 'F', if you want to Flash the channel (if supported by the channel), or 'w' to add a 500 millisecond pause to the DTMF sequence.
between This is the number of milliseconds to wait in between each DTMF digit. If zero milliseconds is specified, then the default value of 100 will be used.

Definition at line 237 of file app.c.

References ast_autoservice_start(), ast_safe_sleep(), and ast_waitfor().

Referenced by ast_bridge_call(), and misdn_send_digit().

00238 {
00239    const char *ptr;
00240    int res = 0;
00241 
00242    if (!between)
00243       between = 100;
00244 
00245    if (peer)
00246       res = ast_autoservice_start(peer);
00247 
00248    if (!res)
00249       res = ast_waitfor(chan, 100);
00250 
00251    /* ast_waitfor will return the number of remaining ms on success */
00252    if (res < 0)
00253       return res;
00254 
00255    for (ptr = digits; *ptr; ptr++) {
00256       if (*ptr == 'w') {
00257          /* 'w' -- wait half a second */
00258          if ((res = ast_safe_sleep(chan, 500)))
00259             break;
00260       } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
00261          /* Character represents valid DTMF */
00262          if (*ptr == 'f' || *ptr == 'F') {
00263             /* ignore return values if not supported by channel */
00264             ast_indicate(chan, AST_CONTROL_FLASH);
00265          } else
00266             ast_senddigit(chan, *ptr);
00267          /* pause between digits */
00268          if ((res = ast_safe_sleep(chan, between)))
00269             break;
00270       } else
00271          ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
00272    }
00273 
00274    if (peer) {
00275       /* Stop autoservice on the peer channel, but don't overwrite any error condition 
00276          that has occurred previously while acting on the primary channel */
00277       if (ast_autoservice_stop(peer) && !res)
00278          res = -1;
00279    }
00280 
00281    return res;
00282 }

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

Definition at line 175 of file app.c.

References ast_has_voicemail_func, ast_inboxcount_func, and ast_messagecount_func.

00178 {
00179    ast_has_voicemail_func = has_voicemail_func;
00180    ast_inboxcount_func = inboxcount_func;
00181    ast_messagecount_func = messagecount_func;
00182 }

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

References ast_ivr_menu_run_internal().

01287 {
01288    int res = ast_ivr_menu_run_internal(chan, menu, cbdata);
01289    /* Hide internal coding */
01290    return res > 0 ? 0 : res;
01291 }

static int ast_ivr_menu_run_internal struct ast_channel chan,
struct ast_ivr_menu menu,
void *  cbdata
[static]
 

Definition at line 1199 of file app.c.

References AST_DIGIT_ANY, ast_log(), AST_MAX_EXTENSION, exten, ivr_dispatch(), LOG_WARNING, maxretries, ast_ivr_option::option, option_exists(), ast_ivr_menu::options, read_newoption(), RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, and ast_ivr_menu::title.

Referenced by ast_ivr_menu_run(), and ivr_dispatch().

01200 {
01201    /* Execute an IVR menu structure */
01202    int res=0;
01203    int pos = 0;
01204    int retries = 0;
01205    char exten[AST_MAX_EXTENSION] = "s";
01206    if (option_exists(menu, "s") < 0) {
01207       strcpy(exten, "g");
01208       if (option_exists(menu, "g") < 0) {
01209          ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
01210          return -1;
01211       }
01212    }
01213    while (!res) {
01214       while (menu->options[pos].option) {
01215          if (!strcasecmp(menu->options[pos].option, exten)) {
01216             res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
01217             if (option_debug)
01218                ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
01219             if (res < 0)
01220                break;
01221             else if (res & RES_UPONE)
01222                return 0;
01223             else if (res & RES_EXIT)
01224                return res;
01225             else if (res & RES_REPEAT) {
01226                int maxretries = res & 0xffff;
01227                if ((res & RES_RESTART) == RES_RESTART) {
01228                   retries = 0;
01229                } else
01230                   retries++;
01231                if (!maxretries)
01232                   maxretries = 3;
01233                if ((maxretries > 0) && (retries >= maxretries)) {
01234                   if (option_debug)
01235                      ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries);
01236                   return -2;
01237                } else {
01238                   if (option_exists(menu, "g") > -1) 
01239                      strcpy(exten, "g");
01240                   else if (option_exists(menu, "s") > -1)
01241                      strcpy(exten, "s");
01242                }
01243                pos = 0;
01244                continue;
01245             } else if (res && strchr(AST_DIGIT_ANY, res)) {
01246                if (option_debug)
01247                   ast_log(LOG_DEBUG, "Got start of extension, %c\n", res);
01248                exten[1] = '\0';
01249                exten[0] = res;
01250                if ((res = read_newoption(chan, menu, exten, sizeof(exten))))
01251                   break;
01252                if (option_exists(menu, exten) < 0) {
01253                   if (option_exists(menu, "i")) {
01254                      if (option_debug)
01255                         ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n");
01256                      strcpy(exten, "i");
01257                      pos = 0;
01258                      continue;
01259                   } else {
01260                      if (option_debug)
01261                         ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n");
01262                      res = -2;
01263                      break;
01264                   }
01265                } else {
01266                   if (option_debug)
01267                      ast_log(LOG_DEBUG, "New existing extension: %s\n", exten);
01268                   pos = 0;
01269                   continue;
01270                }
01271             }
01272          }
01273          pos++;
01274       }
01275       if (option_debug)
01276          ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res);
01277       pos = 0;
01278       if (!strcasecmp(exten, "s"))
01279          strcpy(exten, "g");
01280       else
01281          break;
01282    }
01283    return res;
01284 }

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

References ast_activate_generator(), ast_calloc, ast_config_AST_DATA_DIR, ast_log(), ast_strlen_zero(), linear_state::autoclose, linearstream, and LOG_WARNING.

00357 {
00358    struct linear_state *lin;
00359    char tmpf[256];
00360    int res = -1;
00361    int autoclose = 0;
00362    if (fd < 0) {
00363       if (ast_strlen_zero(filename))
00364          return -1;
00365       autoclose = 1;
00366       if (filename[0] == '/') 
00367          ast_copy_string(tmpf, filename, sizeof(tmpf));
00368       else
00369          snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", ast_config_AST_DATA_DIR, "sounds", filename);
00370       fd = open(tmpf, O_RDONLY);
00371       if (fd < 0){
00372          ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
00373          return -1;
00374       }
00375    }
00376    if ((lin = ast_calloc(1, sizeof(*lin)))) {
00377       lin->fd = fd;
00378       lin->allowoverride = allowoverride;
00379       lin->autoclose = autoclose;
00380       res = ast_activate_generator(chan, &linearstream, lin);
00381    }
00382    return res;
00383 }

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

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

00932 {
00933    char *s;
00934    char *fs;
00935    int res;
00936    int fd;
00937    int lp = strlen(path);
00938    time_t start;
00939 
00940    if (!(s = alloca(lp + 10)) || !(fs = alloca(lp + 20))) {
00941       ast_log(LOG_WARNING, "Out of memory!\n");
00942       return AST_LOCK_FAILURE;
00943    }
00944 
00945    snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, ast_random());
00946    fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, AST_FILE_MODE);
00947    if (fd < 0) {
00948       ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
00949       return AST_LOCK_PATH_NOT_FOUND;
00950    }
00951    close(fd);
00952 
00953    snprintf(s, strlen(path) + 9, "%s/.lock", path);
00954    start = time(NULL);
00955    while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
00956       usleep(1);
00957 
00958    unlink(fs);
00959 
00960    if (res) {
00961       ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
00962       return AST_LOCK_TIMEOUT;
00963    } else {
00964       if (option_debug)
00965          ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
00966       return AST_LOCK_SUCCESS;
00967    }
00968 }

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

References __ast_play_and_record().

00783 {
00784    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf);
00785 }

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

References __ast_play_and_record().

Referenced by ast_record_review().

00778 {
00779    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf);
00780 }

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
 

Definition at line 772 of file app.c.

References __ast_play_and_record(), and S_OR.

00773 {
00774    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, default_acceptdtmf), S_OR(canceldtmf, default_canceldtmf));
00775 }

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

References AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), and ast_waitstream().

Referenced by __ast_play_and_record(), and ast_record_review().

00481 {
00482    int d;
00483    d = ast_streamfile(chan, fn, chan->language);
00484    if (d)
00485       return d;
00486    d = ast_waitstream(chan, AST_DIGIT_ANY);
00487    ast_stopstream(chan);
00488    return d;
00489 }

char* ast_read_textfile const char *  file  ) 
 

Read a file into asterisk

Definition at line 1293 of file app.c.

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

01294 {
01295    int fd;
01296    char *output = NULL;
01297    struct stat filesize;
01298    int count = 0;
01299    int res;
01300    if (stat(filename, &filesize) == -1) {
01301       ast_log(LOG_WARNING, "Error can't stat %s\n", filename);
01302       return NULL;
01303    }
01304    count = filesize.st_size + 1;
01305    fd = open(filename, O_RDONLY);
01306    if (fd < 0) {
01307       ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
01308       return NULL;
01309    }
01310    if ((output = ast_malloc(count))) {
01311       res = read(fd, output, count - 1);
01312       if (res == count - 1) {
01313          output[res] = '\0';
01314       } else {
01315          ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
01316          free(output);
01317          output = NULL;
01318       }
01319    }
01320    close(fd);
01321    return output;
01322 }

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

References AST_DIGIT_ANY, ast_log(), ast_play_and_record(), ast_play_and_wait(), ast_stream_and_wait(), ast_verbose(), ast_waitfordigit(), LOG_WARNING, silencethreshold, and VERBOSE_PREFIX_3.

00993 {
00994    int silencethreshold = 128; 
00995    int maxsilence=0;
00996    int res = 0;
00997    int cmd = 0;
00998    int max_attempts = 3;
00999    int attempts = 0;
01000    int recorded = 0;
01001    int message_exists = 0;
01002    /* Note that urgent and private are for flagging messages as such in the future */
01003 
01004    /* barf if no pointer passed to store duration in */
01005    if (duration == NULL) {
01006       ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
01007       return -1;
01008    }
01009 
01010    cmd = '3';   /* Want to start by recording */
01011 
01012    while ((cmd >= 0) && (cmd != 't')) {
01013       switch (cmd) {
01014       case '1':
01015          if (!message_exists) {
01016             /* In this case, 1 is to record a message */
01017             cmd = '3';
01018             break;
01019          } else {
01020             ast_stream_and_wait(chan, "vm-msgsaved", "");
01021             cmd = 't';
01022             return res;
01023          }
01024       case '2':
01025          /* Review */
01026          ast_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n");
01027          cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY);
01028          break;
01029       case '3':
01030          message_exists = 0;
01031          /* Record */
01032          if (recorded == 1)
01033             ast_verbose(VERBOSE_PREFIX_3 "Re-recording\n");
01034          else  
01035             ast_verbose(VERBOSE_PREFIX_3 "Recording\n");
01036          recorded = 1;
01037          cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path);
01038          if (cmd == -1) {
01039          /* User has hung up, no options to give */
01040             return cmd;
01041          }
01042          if (cmd == '0') {
01043             break;
01044          } else if (cmd == '*') {
01045             break;
01046          } 
01047          else {
01048             /* If all is well, a message exists */
01049             message_exists = 1;
01050             cmd = 0;
01051          }
01052          break;
01053       case '4':
01054       case '5':
01055       case '6':
01056       case '7':
01057       case '8':
01058       case '9':
01059       case '*':
01060       case '#':
01061          cmd = ast_play_and_wait(chan, "vm-sorry");
01062          break;
01063       default:
01064          if (message_exists) {
01065             cmd = ast_play_and_wait(chan, "vm-review");
01066          }
01067          else {
01068             cmd = ast_play_and_wait(chan, "vm-torerecord");
01069             if (!cmd)
01070                cmd = ast_waitfordigit(chan, 600);
01071          }
01072          
01073          if (!cmd)
01074             cmd = ast_waitfordigit(chan, 6000);
01075          if (!cmd) {
01076             attempts++;
01077          }
01078          if (attempts > max_attempts) {
01079             cmd = 't';
01080          }
01081       }
01082    }
01083    if (cmd == 't')
01084       cmd = 0;
01085    return cmd;
01086 }

void ast_uninstall_vm_functions void   ) 
 

Definition at line 184 of file app.c.

References ast_has_voicemail_func, ast_inboxcount_func, and ast_messagecount_func.

00185 {
00186    ast_has_voicemail_func = NULL;
00187    ast_inboxcount_func = NULL;
00188    ast_messagecount_func = NULL;
00189 }

int ast_unlock_path const char *  path  ) 
 

Unlock a path

Definition at line 970 of file app.c.

References ast_log(), LOG_ERROR, LOG_WARNING, and s.

00971 {
00972    char *s;
00973    int res;
00974 
00975    if (!(s = alloca(strlen(path) + 10))) {
00976       ast_log(LOG_WARNING, "Out of memory!\n");
00977       return -1;
00978    }
00979 
00980    snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
00981 
00982    if ((res = unlink(s)))
00983       ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
00984    else {
00985       if (option_debug)
00986          ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
00987    }
00988 
00989    return res;
00990 }

static int ivr_dispatch struct ast_channel chan,
struct ast_ivr_option option,
char *  exten,
void *  cbdata
[static]
 

Definition at line 1095 of file app.c.

References ast_ivr_option::action, ast_ivr_option::adata, AST_ACTION_BACKGROUND, AST_ACTION_BACKLIST, AST_ACTION_CALLBACK, AST_ACTION_EXIT, AST_ACTION_MENU, AST_ACTION_NOOP, AST_ACTION_PLAYBACK, AST_ACTION_PLAYLIST, AST_ACTION_REPEAT, AST_ACTION_RESTART, AST_ACTION_TRANSFER, AST_ACTION_UPONE, AST_ACTION_WAITOPTION, AST_DIGIT_ANY, ast_ivr_menu_run_internal(), ast_log(), ast_parseable_goto(), ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_waitfordigit(), LOG_NOTICE, ast_channel::pbx, RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, ast_pbx::rtimeout, and strsep().

Referenced by ast_ivr_menu_run_internal().

01096 {
01097    int res;
01098    int (*ivr_func)(struct ast_channel *, void *);
01099    char *c;
01100    char *n;
01101    
01102    switch (option->action) {
01103    case AST_ACTION_UPONE:
01104       return RES_UPONE;
01105    case AST_ACTION_EXIT:
01106       return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
01107    case AST_ACTION_REPEAT:
01108       return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
01109    case AST_ACTION_RESTART:
01110       return RES_RESTART ;
01111    case AST_ACTION_NOOP:
01112       return 0;
01113    case AST_ACTION_BACKGROUND:
01114       res = ast_stream_and_wait(chan, (char *)option->adata, AST_DIGIT_ANY);
01115       if (res < 0) {
01116          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01117          res = 0;
01118       }
01119       return res;
01120    case AST_ACTION_PLAYBACK:
01121       res = ast_stream_and_wait(chan, (char *)option->adata, "");
01122       if (res < 0) {
01123          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01124          res = 0;
01125       }
01126       return res;
01127    case AST_ACTION_MENU:
01128       res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata);
01129       /* Do not pass entry errors back up, treaat ast though ti was an "UPONE" */
01130       if (res == -2)
01131          res = 0;
01132       return res;
01133    case AST_ACTION_WAITOPTION:
01134       res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10));
01135       if (!res)
01136          return 't';
01137       return res;
01138    case AST_ACTION_CALLBACK:
01139       ivr_func = option->adata;
01140       res = ivr_func(chan, cbdata);
01141       return res;
01142    case AST_ACTION_TRANSFER:
01143       res = ast_parseable_goto(chan, option->adata);
01144       return 0;
01145    case AST_ACTION_PLAYLIST:
01146    case AST_ACTION_BACKLIST:
01147       res = 0;
01148       c = ast_strdupa(option->adata);
01149       while ((n = strsep(&c, ";"))) {
01150          if ((res = ast_stream_and_wait(chan, n,
01151                (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : "")))
01152             break;
01153       }
01154       ast_stopstream(chan);
01155       return res;
01156    default:
01157       ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
01158       return 0;
01159    };
01160    return -1;
01161 }

static void* linear_alloc struct ast_channel chan,
void *  params
[static]
 

Definition at line 329 of file app.c.

References linear_state::allowoverride, ast_clear_flag, AST_FLAG_WRITE_INT, AST_FORMAT_SLINEAR, ast_log(), ast_set_flag, ast_set_write_format(), free, LOG_WARNING, linear_state::origwfmt, and ast_channel::writeformat.

00330 {
00331    struct linear_state *ls;
00332    /* In this case, params is already malloc'd */
00333    if (params) {
00334       ls = params;
00335       if (ls->allowoverride)
00336          ast_set_flag(chan, AST_FLAG_WRITE_INT);
00337       else
00338          ast_clear_flag(chan, AST_FLAG_WRITE_INT);
00339       ls->origwfmt = chan->writeformat;
00340       if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
00341          ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
00342          free(ls);
00343          ls = params = NULL;
00344       }
00345    }
00346    return params;
00347 }

static int linear_generator struct ast_channel chan,
void *  data,
int  len,
int  samples
[static]
 

Definition at line 302 of file app.c.

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), linear_state::fd, and LOG_WARNING.

00303 {
00304    struct ast_frame f;
00305    short buf[2048 + AST_FRIENDLY_OFFSET / 2];
00306    struct linear_state *ls = data;
00307    int res;
00308    len = samples * 2;
00309    if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
00310       ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len);
00311       len = sizeof(buf) - AST_FRIENDLY_OFFSET;
00312    }
00313    memset(&f, 0, sizeof(f));
00314    res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
00315    if (res > 0) {
00316       f.frametype = AST_FRAME_VOICE;
00317       f.subclass = AST_FORMAT_SLINEAR;
00318       f.data = buf + AST_FRIENDLY_OFFSET/2;
00319       f.datalen = res;
00320       f.samples = res / 2;
00321       f.offset = AST_FRIENDLY_OFFSET;
00322       ast_write(chan, &f);
00323       if (res == len)
00324          return 0;
00325    }
00326    return -1;
00327 }

static void linear_release struct ast_channel chan,
void *  params
[static]
 

Definition at line 291 of file app.c.

References ast_log(), ast_set_write_format(), linear_state::autoclose, linear_state::fd, free, LOG_WARNING, and linear_state::origwfmt.

00292 {
00293    struct linear_state *ls = params;
00294    if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
00295       ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
00296    }
00297    if (ls->autoclose)
00298       close(ls->fd);
00299    free(params);
00300 }

static int option_exists struct ast_ivr_menu menu,
char *  option
[static]
 

Definition at line 1163 of file app.c.

References ast_ivr_option::option, and ast_ivr_menu::options.

Referenced by ast_ivr_menu_run_internal().

01164 {
01165    int x;
01166    for (x = 0; menu->options[x].option; x++)
01167       if (!strcasecmp(menu->options[x].option, option))
01168          return x;
01169    return -1;
01170 }

static int option_matchmore struct ast_ivr_menu menu,
char *  option
[static]
 

Definition at line 1172 of file app.c.

References ast_ivr_option::option, and ast_ivr_menu::options.

Referenced by read_newoption().

01173 {
01174    int x;
01175    for (x = 0; menu->options[x].option; x++)
01176       if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 
01177             (menu->options[x].option[strlen(option)]))
01178          return x;
01179    return -1;
01180 }

static int read_newoption struct ast_channel chan,
struct ast_ivr_menu menu,
char *  exten,
int  maxexten
[static]
 

Definition at line 1182 of file app.c.

References ast_waitfordigit(), ast_pbx::dtimeout, option_matchmore(), and ast_channel::pbx.

Referenced by ast_ivr_menu_run_internal().

01183 {
01184    int res=0;
01185    int ms;
01186    while (option_matchmore(menu, exten)) {
01187       ms = chan->pbx ? chan->pbx->dtimeout : 5000;
01188       if (strlen(exten) >= maxexten - 1) 
01189          break;
01190       res = ast_waitfordigit(chan, ms);
01191       if (res < 1)
01192          break;
01193       exten[strlen(exten) + 1] = '\0';
01194       exten[strlen(exten)] = res;
01195    }
01196    return res > 0 ? 0 : res;
01197 }


Variable Documentation

int(* ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL [static]
 

Definition at line 171 of file app.c.

Referenced by ast_app_has_voicemail(), ast_install_vm_functions(), and ast_uninstall_vm_functions().

int(* ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL [static]
 

Definition at line 172 of file app.c.

Referenced by ast_app_inboxcount(), ast_install_vm_functions(), and ast_uninstall_vm_functions().

int(* ast_messagecount_func)(const char *context, const char *mailbox, const char *folder) = NULL [static]
 

Definition at line 173 of file app.c.

Referenced by ast_app_messagecount(), ast_install_vm_functions(), and ast_uninstall_vm_functions().

char default_acceptdtmf[] = "#" [static]
 

Definition at line 769 of file app.c.

char default_canceldtmf[] = "" [static]
 

Definition at line 770 of file app.c.

int global_maxsilence = 0 [static]
 

Definition at line 492 of file app.c.

int global_silence_threshold = 128 [static]
 

Definition at line 491 of file app.c.

struct ast_generator linearstream [static]
 

Definition at line 349 of file app.c.

Referenced by ast_linear_stream().


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen