Sat Sep 16 07:28:10 2006

Asterisk developer's documentation


app.c File Reference

Convenient Application Routines. More...

#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.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"

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

int ast_app_dtget (struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
 Present a dialtone and collect a certain length extension.
int ast_app_getdata (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
 Plays a stream and gets DTMF data from a channel.
int ast_app_getdata_full (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
 Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions.
int ast_app_getvoice (struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
int ast_app_group_get_count (char *group, char *category)
int ast_app_group_match_get_count (char *groupmatch, char *category)
int ast_app_group_set_channel (struct ast_channel *chan, char *data)
int ast_app_group_split_group (char *data, char *group, int group_max, char *category, int category_max)
int ast_app_has_voicemail (const char *mailbox, const char *folder)
int ast_app_messagecount (const char *mailbox, int *newmsgs, int *oldmsgs)
int ast_app_parse_options (const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
 Parses a string containing application options and sets flags/arguments.
unsigned int ast_app_separate_args (char *buf, char delim, char **array, int arraylen)
 Separate a string into arguments in an array.
int ast_control_streamfile (struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms)
int ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, char *digits, int between)
void ast_install_vm_functions (int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs))
int ast_ivr_menu_run (struct ast_channel *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_messagecount_func (const char *mailbox, int *newmsgs, int *oldmsgs) = NULL
static char default_acceptdtmf [] = "#"
static char default_canceldtmf [] = "0"
static int global_maxsilence = 0
static int global_silence_threshold = 128
static struct ast_generator linearstream


Detailed Description

Convenient Application Routines.

Definition in file app.c.


Define Documentation

#define MAX_OTHER_FORMATS   10

Definition at line 52 of file app.c.

Referenced by ast_play_and_prepend(), and ast_play_and_record_full().

#define RES_EXIT   (1 << 17)

Definition at line 1302 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_REPEAT   (1 << 18)

Definition at line 1303 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

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

Definition at line 1304 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_UPONE   (1 << 16)

Definition at line 1301 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().


Function Documentation

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

Present a dialtone and collect a certain length extension.

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

Definition at line 62 of file app.c.

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

Referenced by builtin_atxfer(), and builtin_blindtransfer().

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

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

Plays a stream and gets DTMF data from a channel.

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

Definition at line 109 of file app.c.

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

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

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

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

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

Definition at line 132 of file app.c.

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

Referenced by handle_getdata().

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

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

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

Definition at line 150 of file app.c.

References ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_set_read_format(), ast_streamfile(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_dsp::f, ast_frame::frametype, ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::name, ast_channel::readformat, ast_frame::samples, ast_frame::subclass, and total.

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

int ast_app_group_get_count ( char *  group,
char *  category 
)

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

Definition at line 1051 of file app.c.

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

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

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

int ast_app_group_match_get_count ( char *  groupmatch,
char *  category 
)

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

Definition at line 1076 of file app.c.

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

Referenced by group_match_count_exec(), and group_match_count_function_read().

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

int ast_app_group_set_channel ( struct ast_channel chan,
char *  data 
)

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

Definition at line 1037 of file app.c.

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

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

01038 {
01039    int res=0;
01040    char group[80] = "";
01041    char category[80] = "";
01042 
01043    if (!ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) {
01044       pbx_builtin_setvar_helper(chan, category, group);
01045    } else
01046       res = -1;
01047 
01048    return res;
01049 }

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

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

Definition at line 1008 of file app.c.

References ast_strlen_zero(), and GROUP_CATEGORY_PREFIX.

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

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

int ast_app_has_voicemail ( const char *  mailbox,
const char *  folder 
)

Determine if a given mailbox has any voicemail

Definition at line 249 of file app.c.

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

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

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

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

Determine number of new/old messages in a mailbox

Definition at line 263 of file app.c.

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

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

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

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

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

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

Definition at line 1538 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 app_exec(), chanspy_exec(), conf_exec(), dial_exec_full(), mixmonitor_exec(), page_exec(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_waitexten(), vm_exec(), and vm_execmain().

01539 {
01540    char *s;
01541    int curarg;
01542    unsigned int argloc;
01543    char *arg;
01544    int res = 0;
01545 
01546    ast_clear_flag(flags, AST_FLAGS_ALL);
01547 
01548    if (!optstr)
01549       return 0;
01550 
01551    s = optstr;
01552    while (*s) {
01553       curarg = *s++ & 0x7f;
01554       ast_set_flag(flags, options[curarg].flag);
01555       argloc = options[curarg].arg_index;
01556       if (*s == '(') {
01557          /* Has argument */
01558          arg = ++s;
01559          while (*s && (*s != ')'))
01560             s++;
01561          if (*s) {
01562             if (argloc)
01563                args[argloc - 1] = arg;
01564             *s++ = '\0';
01565          } else {
01566             ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
01567             res = -1;
01568          }
01569       } else if (argloc) {
01570          args[argloc - 1] = NULL;
01571       }
01572    }
01573 
01574    return res;
01575 }

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

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

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

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

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

Definition at line 432 of file app.c.

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

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

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

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

Send DTMF to chan (optionally entertain peer)

Definition at line 281 of file app.c.

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

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

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

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

Definition at line 236 of file app.c.

References ast_has_voicemail_func, and ast_messagecount_func.

Referenced by load_module().

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

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

Runs an IVR menu.

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

Definition at line 1495 of file app.c.

References ast_ivr_menu_run_internal().

Referenced by skel_exec().

01496 {
01497    int res;
01498    res = ast_ivr_menu_run_internal(chan, menu, cbdata);
01499    /* Hide internal coding */
01500    if (res > 0)
01501       res = 0;
01502    return res;
01503 }

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

Definition at line 1415 of file app.c.

References AST_DIGIT_ANY, ast_log(), AST_MAX_EXTENSION, exten, ivr_dispatch(), LOG_DEBUG, 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().

01416 {
01417    /* Execute an IVR menu structure */
01418    int res=0;
01419    int pos = 0;
01420    int retries = 0;
01421    char exten[AST_MAX_EXTENSION] = "s";
01422    if (option_exists(menu, "s") < 0) {
01423       strcpy(exten, "g");
01424       if (option_exists(menu, "g") < 0) {
01425          ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
01426          return -1;
01427       }
01428    }
01429    while(!res) {
01430       while(menu->options[pos].option) {
01431          if (!strcasecmp(menu->options[pos].option, exten)) {
01432             res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
01433             ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
01434             if (res < 0)
01435                break;
01436             else if (res & RES_UPONE)
01437                return 0;
01438             else if (res & RES_EXIT)
01439                return res;
01440             else if (res & RES_REPEAT) {
01441                int maxretries = res & 0xffff;
01442                if ((res & RES_RESTART) == RES_RESTART) {
01443                   retries = 0;
01444                } else
01445                   retries++;
01446                if (!maxretries)
01447                   maxretries = 3;
01448                if ((maxretries > 0) && (retries >= maxretries)) {
01449                   ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries);
01450                   return -2;
01451                } else {
01452                   if (option_exists(menu, "g") > -1) 
01453                      strcpy(exten, "g");
01454                   else if (option_exists(menu, "s") > -1)
01455                      strcpy(exten, "s");
01456                }
01457                pos=0;
01458                continue;
01459             } else if (res && strchr(AST_DIGIT_ANY, res)) {
01460                ast_log(LOG_DEBUG, "Got start of extension, %c\n", res);
01461                exten[1] = '\0';
01462                exten[0] = res;
01463                if ((res = read_newoption(chan, menu, exten, sizeof(exten))))
01464                   break;
01465                if (option_exists(menu, exten) < 0) {
01466                   if (option_exists(menu, "i")) {
01467                      ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n");
01468                      strcpy(exten, "i");
01469                      pos = 0;
01470                      continue;
01471                   } else {
01472                      ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n");
01473                      res = -2;
01474                      break;
01475                   }
01476                } else {
01477                   ast_log(LOG_DEBUG, "New existing extension: %s\n", exten);
01478                   pos = 0;
01479                   continue;
01480                }
01481             }
01482          }
01483          pos++;
01484       }
01485       ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res);
01486       pos = 0;
01487       if (!strcasecmp(exten, "s"))
01488          strcpy(exten, "g");
01489       else
01490          break;
01491    }
01492    return res;
01493 }

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

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

Definition at line 401 of file app.c.

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

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

enum AST_LOCK_RESULT ast_lock_path ( const char *  path  ) 

Lock a filesystem path.

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

Definition at line 1142 of file app.c.

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

Referenced by vm_lock_path().

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

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

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

Referenced by vm_forwardoptions().

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

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

References ast_play_and_record_full().

Referenced by ast_record_review(), and dial_exec_full().

00768 {
00769    return ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path, default_acceptdtmf, default_canceldtmf);
00770 }

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

References ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_indicate(), ast_log(), ast_play_and_wait(), ast_read(), ast_set_read_format(), ast_strdupa, ast_stream_rewind(), ast_streamfile(), ast_truncstream(), ast_unlock_path(), ast_verbose(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_frame::frametype, ast_channel::language, LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, option_transmit_silence_during_record, option_verbose, ast_channel::readformat, strsep(), ast_frame::subclass, ast_dsp::totalsilence, and VERBOSE_PREFIX_3.

Referenced by ast_play_and_record(), and play_record_review().

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

int ast_play_and_wait ( struct ast_channel chan,
const char *  fn 
)

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

Definition at line 526 of file app.c.

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

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

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

char* ast_read_textfile ( const char *  file  ) 

Read a file into asterisk

Definition at line 1505 of file app.c.

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

Referenced by readfile_exec().

01506 {
01507    int fd;
01508    char *output=NULL;
01509    struct stat filesize;
01510    int count=0;
01511    int res;
01512    if(stat(filename,&filesize)== -1){
01513       ast_log(LOG_WARNING,"Error can't stat %s\n", filename);
01514       return NULL;
01515    }
01516    count=filesize.st_size + 1;
01517    fd = open(filename, O_RDONLY);
01518    if (fd < 0) {
01519       ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
01520       return NULL;
01521    }
01522    output=(char *)malloc(count);
01523    if (output) {
01524       res = read(fd, output, count - 1);
01525       if (res == count - 1) {
01526          output[res] = '\0';
01527       } else {
01528          ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count -  1, strerror(errno));
01529          free(output);
01530          output = NULL;
01531       }
01532    } else 
01533       ast_log(LOG_WARNING, "Out of memory!\n");
01534    close(fd);
01535    return output;
01536 }

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

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

Referenced by conf_run().

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

void ast_uninstall_vm_functions ( void   ) 

Definition at line 243 of file app.c.

References ast_has_voicemail_func, and ast_messagecount_func.

Referenced by unload_module().

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

int ast_unlock_path ( const char *  path  ) 

Unlock a path

Definition at line 1182 of file app.c.

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

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

01183 {
01184    char *s;
01185    int res;
01186 
01187    s = alloca(strlen(path) + 10);
01188    if (!s) {
01189       ast_log(LOG_WARNING, "Out of memory!\n");
01190       return -1;
01191    }
01192 
01193    snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
01194 
01195    if ((res = unlink(s)))
01196       ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
01197    else
01198       ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
01199 
01200    return res;
01201 }

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

Definition at line 1307 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_streamfile(), ast_waitfordigit(), ast_waitstream(), ast_channel::language, LOG_NOTICE, n, ast_channel::pbx, RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, ast_pbx::rtimeout, and strsep().

Referenced by ast_ivr_menu_run_internal().

01308 {
01309    int res;
01310    int (*ivr_func)(struct ast_channel *, void *);
01311    char *c;
01312    char *n;
01313    
01314    switch(option->action) {
01315    case AST_ACTION_UPONE:
01316       return RES_UPONE;
01317    case AST_ACTION_EXIT:
01318       return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
01319    case AST_ACTION_REPEAT:
01320       return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
01321    case AST_ACTION_RESTART:
01322       return RES_RESTART ;
01323    case AST_ACTION_NOOP:
01324       return 0;
01325    case AST_ACTION_BACKGROUND:
01326       res = ast_streamfile(chan, (char *)option->adata, chan->language);
01327       if (!res) {
01328          res = ast_waitstream(chan, AST_DIGIT_ANY);
01329       } else {
01330          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01331          res = 0;
01332       }
01333       return res;
01334    case AST_ACTION_PLAYBACK:
01335       res = ast_streamfile(chan, (char *)option->adata, chan->language);
01336       if (!res) {
01337          res = ast_waitstream(chan, "");
01338       } else {
01339          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01340          res = 0;
01341       }
01342       return res;
01343    case AST_ACTION_MENU:
01344       res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata);
01345       /* Do not pass entry errors back up, treaat ast though ti was an "UPONE" */
01346       if (res == -2)
01347          res = 0;
01348       return res;
01349    case AST_ACTION_WAITOPTION:
01350       res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10));
01351       if (!res)
01352          return 't';
01353       return res;
01354    case AST_ACTION_CALLBACK:
01355       ivr_func = option->adata;
01356       res = ivr_func(chan, cbdata);
01357       return res;
01358    case AST_ACTION_TRANSFER:
01359       res = ast_parseable_goto(chan, option->adata);
01360       return 0;
01361    case AST_ACTION_PLAYLIST:
01362    case AST_ACTION_BACKLIST:
01363       res = 0;
01364       c = ast_strdupa(option->adata);
01365       if (c) {
01366          while((n = strsep(&c, ";")))
01367             if ((res = ast_streamfile(chan, n, chan->language)) || (res = ast_waitstream(chan, (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : "")))
01368                break;
01369          ast_stopstream(chan);
01370       }
01371       return res;
01372    default:
01373       ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
01374       return 0;
01375    };
01376    return -1;
01377 }

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

Definition at line 374 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, ast_channel::name, linear_state::origwfmt, and ast_channel::writeformat.

00375 {
00376    struct linear_state *ls;
00377    /* In this case, params is already malloc'd */
00378    if (params) {
00379       ls = params;
00380       if (ls->allowoverride)
00381          ast_set_flag(chan, AST_FLAG_WRITE_INT);
00382       else
00383          ast_clear_flag(chan, AST_FLAG_WRITE_INT);
00384       ls->origwfmt = chan->writeformat;
00385       if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
00386          ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
00387          free(ls);
00388          ls = params = NULL;
00389       }
00390    }
00391    return params;
00392 }

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

Definition at line 347 of file app.c.

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

00348 {
00349    struct ast_frame f;
00350    short buf[2048 + AST_FRIENDLY_OFFSET / 2];
00351    struct linear_state *ls = data;
00352    int res;
00353    len = samples * 2;
00354    if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
00355       ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len);
00356       len = sizeof(buf) - AST_FRIENDLY_OFFSET;
00357    }
00358    memset(&f, 0, sizeof(f));
00359    res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
00360    if (res > 0) {
00361       f.frametype = AST_FRAME_VOICE;
00362       f.subclass = AST_FORMAT_SLINEAR;
00363       f.data = buf + AST_FRIENDLY_OFFSET/2;
00364       f.datalen = res;
00365       f.samples = res / 2;
00366       f.offset = AST_FRIENDLY_OFFSET;
00367       ast_write(chan, &f);
00368       if (res == len)
00369          return 0;
00370    }
00371    return -1;
00372 }

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

Definition at line 336 of file app.c.

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

00337 {
00338    struct linear_state *ls = params;
00339    if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
00340       ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
00341    }
00342    if (ls->autoclose)
00343       close(ls->fd);
00344    free(params);
00345 }

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

Definition at line 1379 of file app.c.

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

Referenced by ast_ivr_menu_run_internal().

01380 {
01381    int x;
01382    for (x=0;menu->options[x].option;x++)
01383       if (!strcasecmp(menu->options[x].option, option))
01384          return x;
01385    return -1;
01386 }

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

Definition at line 1388 of file app.c.

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

Referenced by read_newoption().

01389 {
01390    int x;
01391    for (x=0;menu->options[x].option;x++)
01392       if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 
01393             (menu->options[x].option[strlen(option)]))
01394          return x;
01395    return -1;
01396 }

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

Definition at line 1398 of file app.c.

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

Referenced by ast_ivr_menu_run_internal().

01399 {
01400    int res=0;
01401    int ms;
01402    while(option_matchmore(menu, exten)) {
01403       ms = chan->pbx ? chan->pbx->dtimeout : 5000;
01404       if (strlen(exten) >= maxexten - 1) 
01405          break;
01406       res = ast_waitfordigit(chan, ms);
01407       if (res < 1)
01408          break;
01409       exten[strlen(exten) + 1] = '\0';
01410       exten[strlen(exten)] = res;
01411    }
01412    return res > 0 ? 0 : res;
01413 }


Variable Documentation

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

Definition at line 233 of file app.c.

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

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

Definition at line 234 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 764 of file app.c.

char default_canceldtmf[] = "0" [static]

Definition at line 765 of file app.c.

int global_maxsilence = 0 [static]

Definition at line 538 of file app.c.

int global_silence_threshold = 128 [static]

Definition at line 537 of file app.c.

struct ast_generator linearstream [static]

Definition at line 394 of file app.c.

Referenced by ast_linear_stream().


Generated on Sat Sep 16 07:28:10 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7