Wed Oct 28 15:47:57 2009

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"
#include "asterisk/linkedlists.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

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_discard (struct ast_channel *chan)
int ast_app_group_get_count (char *group, char *category)
struct ast_group_infoast_app_group_list_head (void)
int ast_app_group_list_lock (void)
int ast_app_group_list_unlock (void)
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_group_update (struct ast_channel *old, struct ast_channel *new)
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)
static AST_LIST_HEAD_STATIC (groups, ast_group_info)
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 53 of file app.c.

Referenced by ast_play_and_prepend(), and ast_play_and_record_full().

#define RES_EXIT   (1 << 17)

Definition at line 1360 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_REPEAT   (1 << 18)

Definition at line 1361 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

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

Definition at line 1362 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_UPONE   (1 << 16)

Definition at line 1359 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 64 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().

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

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

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

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

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

Referenced by handle_getdata().

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

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

References ast_closestream(), 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_frame::frametype, ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::name, ast_channel::readformat, ast_frame::samples, ast_frame::subclass, and total.

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

int ast_app_group_discard ( struct ast_channel chan  ) 

Discard all group counting for a channel

Definition at line 1134 of file app.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_group_info::chan, free, and list.

Referenced by ast_channel_free().

01135 {
01136    struct ast_group_info *gi = NULL;
01137 
01138    AST_LIST_LOCK(&groups);
01139    AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
01140       if (gi->chan == chan) {
01141          AST_LIST_REMOVE_CURRENT(&groups, list);
01142          free(gi);
01143       }
01144    }
01145         AST_LIST_TRAVERSE_SAFE_END
01146    AST_LIST_UNLOCK(&groups);
01147 
01148    return 0;
01149 }

int ast_app_group_get_count ( char *  group,
char *  category 
)

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

Definition at line 1077 of file app.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, ast_group_info::group, and list.

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

01078 {
01079    struct ast_group_info *gi = NULL;
01080    int count = 0;
01081 
01082    if (ast_strlen_zero(group))
01083       return 0;
01084 
01085    AST_LIST_LOCK(&groups);
01086    AST_LIST_TRAVERSE(&groups, gi, list) {
01087       if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category))))
01088          count++;
01089    }
01090    AST_LIST_UNLOCK(&groups);
01091 
01092    return count;
01093 }

struct ast_group_info* ast_app_group_list_head ( void   )  [read]

Get the head of the group count list

Definition at line 1156 of file app.c.

References AST_LIST_FIRST.

Referenced by group_function_read(), group_list_function_read(), and group_show_channels().

01157 {
01158    return AST_LIST_FIRST(&groups);
01159 }

int ast_app_group_list_lock ( void   ) 

Lock the group count list

Definition at line 1151 of file app.c.

References AST_LIST_LOCK.

Referenced by group_function_read(), group_list_function_read(), and group_show_channels().

01152 {
01153    return AST_LIST_LOCK(&groups);
01154 }

int ast_app_group_list_unlock ( void   ) 

Unlock the group count list

Definition at line 1161 of file app.c.

References AST_LIST_UNLOCK.

Referenced by group_function_read(), group_list_function_read(), and group_show_channels().

01162 {
01163    return AST_LIST_UNLOCK(&groups);
01164 }

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

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, ast_group_info::group, and list.

Referenced by group_match_count_exec(), and group_match_count_function_read().

01096 {
01097    struct ast_group_info *gi = NULL;
01098    regex_t regexbuf;
01099    int count = 0;
01100 
01101    if (ast_strlen_zero(groupmatch))
01102       return 0;
01103 
01104    /* if regex compilation fails, return zero matches */
01105    if (regcomp(&regexbuf, groupmatch, REG_EXTENDED | REG_NOSUB))
01106       return 0;
01107 
01108    AST_LIST_LOCK(&groups);
01109    AST_LIST_TRAVERSE(&groups, gi, list) {
01110       if (!regexec(&regexbuf, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category))))
01111          count++;
01112    }
01113    AST_LIST_UNLOCK(&groups);
01114 
01115    regfree(&regexbuf);
01116 
01117    return count;
01118 }

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

References ast_app_group_split_group(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_strlen_zero(), calloc, ast_group_info::category, ast_group_info::chan, free, ast_group_info::group, group, and list.

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

01035 {
01036    int res = 0;
01037    char group[80] = "", category[80] = "";
01038    struct ast_group_info *gi = NULL;
01039    size_t len = 0;
01040 
01041    if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category)))
01042       return -1;
01043 
01044    /* Calculate memory we will need if this is new */
01045    len = sizeof(*gi) + strlen(group) + 1;
01046    if (!ast_strlen_zero(category))
01047       len += strlen(category) + 1;
01048 
01049    AST_LIST_LOCK(&groups);
01050    AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
01051       if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
01052          AST_LIST_REMOVE_CURRENT(&groups, list);
01053          free(gi);
01054          break;
01055       }
01056    }
01057    AST_LIST_TRAVERSE_SAFE_END
01058 
01059    if ((gi = calloc(1, len))) {
01060       gi->chan = chan;
01061       gi->group = (char *) gi + sizeof(*gi);
01062       strcpy(gi->group, group);
01063       if (!ast_strlen_zero(category)) {
01064          gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1;
01065          strcpy(gi->category, category);
01066       }
01067       AST_LIST_INSERT_TAIL(&groups, gi, list);
01068    } else {
01069       res = -1;
01070    }
01071 
01072    AST_LIST_UNLOCK(&groups);
01073 
01074    return res;
01075 }

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

References ast_strlen_zero().

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

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

int ast_app_group_update ( struct ast_channel oldchan,
struct ast_channel newchan 
)

Update all group counting for a channel to a new one

Definition at line 1120 of file app.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_group_info::chan, and list.

Referenced by ast_do_masquerade().

01121 {
01122    struct ast_group_info *gi = NULL;
01123 
01124    AST_LIST_LOCK(&groups);
01125    AST_LIST_TRAVERSE(&groups, gi, list) {
01126       if (gi->chan == old)
01127          gi->chan = new;
01128    }
01129    AST_LIST_UNLOCK(&groups);
01130 
01131    return 0;
01132 }

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

Determine if a given mailbox has any voicemail

Definition at line 248 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().

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

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

Determine number of new/old messages in a mailbox

Definition at line 262 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().

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

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

01597 {
01598    char *s;
01599    int curarg;
01600    unsigned int argloc;
01601    char *arg;
01602    int res = 0;
01603 
01604    ast_clear_flag(flags, AST_FLAGS_ALL);
01605 
01606    if (!optstr)
01607       return 0;
01608 
01609    s = optstr;
01610    while (*s) {
01611       curarg = *s++ & 0x7f;
01612       ast_set_flag(flags, options[curarg].flag);
01613       argloc = options[curarg].arg_index;
01614       if (*s == '(') {
01615          /* Has argument */
01616          arg = ++s;
01617          while (*s && (*s != ')'))
01618             s++;
01619          if (*s) {
01620             if (argloc)
01621                args[argloc - 1] = arg;
01622             *s++ = '\0';
01623          } else {
01624             ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
01625             res = -1;
01626          }
01627       } else if (argloc) {
01628          args[argloc - 1] = NULL;
01629       }
01630    }
01631 
01632    return res;
01633 }

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

01167 {
01168    int argc;
01169    char *scan;
01170    int paren = 0;
01171 
01172    if (!buf || !array || !arraylen)
01173       return 0;
01174 
01175    memset(array, 0, arraylen * sizeof(*array));
01176 
01177    scan = buf;
01178 
01179    for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
01180       array[argc] = scan;
01181       for (; *scan; scan++) {
01182          if (*scan == '(')
01183             paren++;
01184          else if (*scan == ')') {
01185             if (paren)
01186                paren--;
01187          } else if ((*scan == delim) && !paren) {
01188             *scan++ = '\0';
01189             break;
01190          }
01191       }
01192    }
01193 
01194    if (*scan)
01195       array[argc++] = scan;
01196 
01197    return argc;
01198 }

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

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

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

References ast_autoservice_start(), ast_autoservice_stop(), AST_FRAME_DTMF, ast_log(), ast_safe_sleep(), ast_waitfor(), ast_write(), ast_frame::frametype, LOG_WARNING, ast_frame::src, and ast_frame::subclass.

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

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

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

References ast_has_voicemail_func, and ast_messagecount_func.

Referenced by load_module().

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

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

References ast_ivr_menu_run_internal().

Referenced by skel_exec().

01554 {
01555    int res;
01556    res = ast_ivr_menu_run_internal(chan, menu, cbdata);
01557    /* Hide internal coding */
01558    if (res > 0)
01559       res = 0;
01560    return res;
01561 }

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

Definition at line 1473 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().

01474 {
01475    /* Execute an IVR menu structure */
01476    int res=0;
01477    int pos = 0;
01478    int retries = 0;
01479    char exten[AST_MAX_EXTENSION] = "s";
01480    if (option_exists(menu, "s") < 0) {
01481       strcpy(exten, "g");
01482       if (option_exists(menu, "g") < 0) {
01483          ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
01484          return -1;
01485       }
01486    }
01487    while(!res) {
01488       while(menu->options[pos].option) {
01489          if (!strcasecmp(menu->options[pos].option, exten)) {
01490             res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
01491             ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
01492             if (res < 0)
01493                break;
01494             else if (res & RES_UPONE)
01495                return 0;
01496             else if (res & RES_EXIT)
01497                return res;
01498             else if (res & RES_REPEAT) {
01499                int maxretries = res & 0xffff;
01500                if ((res & RES_RESTART) == RES_RESTART) {
01501                   retries = 0;
01502                } else
01503                   retries++;
01504                if (!maxretries)
01505                   maxretries = 3;
01506                if ((maxretries > 0) && (retries >= maxretries)) {
01507                   ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries);
01508                   return -2;
01509                } else {
01510                   if (option_exists(menu, "g") > -1) 
01511                      strcpy(exten, "g");
01512                   else if (option_exists(menu, "s") > -1)
01513                      strcpy(exten, "s");
01514                }
01515                pos=0;
01516                continue;
01517             } else if (res && strchr(AST_DIGIT_ANY, res)) {
01518                ast_log(LOG_DEBUG, "Got start of extension, %c\n", res);
01519                exten[1] = '\0';
01520                exten[0] = res;
01521                if ((res = read_newoption(chan, menu, exten, sizeof(exten))))
01522                   break;
01523                if (option_exists(menu, exten) < 0) {
01524                   if (option_exists(menu, "i")) {
01525                      ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n");
01526                      strcpy(exten, "i");
01527                      pos = 0;
01528                      continue;
01529                   } else {
01530                      ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n");
01531                      res = -2;
01532                      break;
01533                   }
01534                } else {
01535                   ast_log(LOG_DEBUG, "New existing extension: %s\n", exten);
01536                   pos = 0;
01537                   continue;
01538                }
01539             }
01540          }
01541          pos++;
01542       }
01543       ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res);
01544       pos = 0;
01545       if (!strcasecmp(exten, "s"))
01546          strcpy(exten, "g");
01547       else
01548          break;
01549    }
01550    return res;
01551 }

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

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

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

static AST_LIST_HEAD_STATIC ( groups  ,
ast_group_info   
) [static]

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

01201 {
01202    char *s;
01203    char *fs;
01204    int res;
01205    int fd;
01206    time_t start;
01207 
01208    s = alloca(strlen(path) + 10);
01209    fs = alloca(strlen(path) + 20);
01210 
01211    if (!fs || !s) {
01212       ast_log(LOG_WARNING, "Out of memory!\n");
01213       return AST_LOCK_FAILURE;
01214    }
01215 
01216    snprintf(fs, strlen(path) + 19, "%s/.lock-%08x", path, rand());
01217    fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
01218    if (fd < 0) {
01219       ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
01220       return AST_LOCK_PATH_NOT_FOUND;
01221    }
01222    close(fd);
01223 
01224    snprintf(s, strlen(path) + 9, "%s/.lock", path);
01225    time(&start);
01226    while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
01227       usleep(1);
01228 
01229    unlink(fs);
01230 
01231    if (res) {
01232       ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
01233       return AST_LOCK_TIMEOUT;
01234    } else {
01235       ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
01236       return AST_LOCK_SUCCESS;
01237    }
01238 }

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 771 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_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().

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

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

References ast_play_and_record_full().

Referenced by ast_record_review(), and dial_exec_full().

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

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

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

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

char* ast_read_textfile ( const char *  file  ) 

Read a file into asterisk

Definition at line 1563 of file app.c.

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

Referenced by readfile_exec().

01564 {
01565    int fd;
01566    char *output=NULL;
01567    struct stat filesize;
01568    int count=0;
01569    int res;
01570    if(stat(filename,&filesize)== -1){
01571       ast_log(LOG_WARNING,"Error can't stat %s\n", filename);
01572       return NULL;
01573    }
01574    count=filesize.st_size + 1;
01575    fd = open(filename, O_RDONLY);
01576    if (fd < 0) {
01577       ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
01578       return NULL;
01579    }
01580    output=(char *)malloc(count);
01581    if (output) {
01582       res = read(fd, output, count - 1);
01583       if (res == count - 1) {
01584          output[res] = '\0';
01585       } else {
01586          ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count -  1, strerror(errno));
01587          free(output);
01588          output = NULL;
01589       }
01590    } else 
01591       ast_log(LOG_WARNING, "Out of memory!\n");
01592    close(fd);
01593    return output;
01594 }

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

01262 {
01263    int silencethreshold = 128; 
01264    int maxsilence=0;
01265    int res = 0;
01266    int cmd = 0;
01267    int max_attempts = 3;
01268    int attempts = 0;
01269    int recorded = 0;
01270    int message_exists = 0;
01271    /* Note that urgent and private are for flagging messages as such in the future */
01272 
01273    /* barf if no pointer passed to store duration in */
01274    if (duration == NULL) {
01275       ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
01276       return -1;
01277    }
01278 
01279    cmd = '3';   /* Want to start by recording */
01280 
01281    while ((cmd >= 0) && (cmd != 't')) {
01282       switch (cmd) {
01283       case '1':
01284          if (!message_exists) {
01285             /* In this case, 1 is to record a message */
01286             cmd = '3';
01287             break;
01288          } else {
01289             ast_streamfile(chan, "vm-msgsaved", chan->language);
01290             ast_waitstream(chan, "");
01291             cmd = 't';
01292             return res;
01293          }
01294       case '2':
01295          /* Review */
01296          ast_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n");
01297          ast_streamfile(chan, recordfile, chan->language);
01298          cmd = ast_waitstream(chan, AST_DIGIT_ANY);
01299          break;
01300       case '3':
01301          message_exists = 0;
01302          /* Record */
01303          if (recorded == 1)
01304             ast_verbose(VERBOSE_PREFIX_3 "Re-recording\n");
01305          else  
01306             ast_verbose(VERBOSE_PREFIX_3 "Recording\n");
01307          recorded = 1;
01308          cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path);
01309          if (cmd == -1) {
01310          /* User has hung up, no options to give */
01311             return cmd;
01312          }
01313          if (cmd == '0') {
01314             break;
01315          } else if (cmd == '*') {
01316             break;
01317          } 
01318          else {
01319             /* If all is well, a message exists */
01320             message_exists = 1;
01321             cmd = 0;
01322          }
01323          break;
01324       case '4':
01325       case '5':
01326       case '6':
01327       case '7':
01328       case '8':
01329       case '9':
01330       case '*':
01331       case '#':
01332          cmd = ast_play_and_wait(chan, "vm-sorry");
01333          break;
01334       default:
01335          if (message_exists) {
01336             cmd = ast_play_and_wait(chan, "vm-review");
01337          }
01338          else {
01339             cmd = ast_play_and_wait(chan, "vm-torerecord");
01340             if (!cmd)
01341                cmd = ast_waitfordigit(chan, 600);
01342          }
01343          
01344          if (!cmd)
01345             cmd = ast_waitfordigit(chan, 6000);
01346          if (!cmd) {
01347             attempts++;
01348          }
01349          if (attempts > max_attempts) {
01350             cmd = 't';
01351          }
01352       }
01353    }
01354    if (cmd == 't')
01355       cmd = 0;
01356    return cmd;
01357 }

void ast_uninstall_vm_functions ( void   ) 

Definition at line 242 of file app.c.

References ast_has_voicemail_func, and ast_messagecount_func.

Referenced by unload_module().

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

int ast_unlock_path ( const char *  path  ) 

Unlock a path

Definition at line 1240 of file app.c.

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

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

01241 {
01242    char *s;
01243    int res;
01244 
01245    s = alloca(strlen(path) + 10);
01246    if (!s) {
01247       ast_log(LOG_WARNING, "Out of memory!\n");
01248       return -1;
01249    }
01250 
01251    snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
01252 
01253    if ((res = unlink(s)))
01254       ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
01255    else
01256       ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
01257 
01258    return res;
01259 }

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

Definition at line 1365 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().

01366 {
01367    int res;
01368    int (*ivr_func)(struct ast_channel *, void *);
01369    char *c;
01370    char *n;
01371    
01372    switch(option->action) {
01373    case AST_ACTION_UPONE:
01374       return RES_UPONE;
01375    case AST_ACTION_EXIT:
01376       return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
01377    case AST_ACTION_REPEAT:
01378       return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
01379    case AST_ACTION_RESTART:
01380       return RES_RESTART ;
01381    case AST_ACTION_NOOP:
01382       return 0;
01383    case AST_ACTION_BACKGROUND:
01384       res = ast_streamfile(chan, (char *)option->adata, chan->language);
01385       if (!res) {
01386          res = ast_waitstream(chan, AST_DIGIT_ANY);
01387       } else {
01388          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01389          res = 0;
01390       }
01391       return res;
01392    case AST_ACTION_PLAYBACK:
01393       res = ast_streamfile(chan, (char *)option->adata, chan->language);
01394       if (!res) {
01395          res = ast_waitstream(chan, "");
01396       } else {
01397          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01398          res = 0;
01399       }
01400       return res;
01401    case AST_ACTION_MENU:
01402       res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata);
01403       /* Do not pass entry errors back up, treaat ast though ti was an "UPONE" */
01404       if (res == -2)
01405          res = 0;
01406       return res;
01407    case AST_ACTION_WAITOPTION:
01408       res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10));
01409       if (!res)
01410          return 't';
01411       return res;
01412    case AST_ACTION_CALLBACK:
01413       ivr_func = option->adata;
01414       res = ivr_func(chan, cbdata);
01415       return res;
01416    case AST_ACTION_TRANSFER:
01417       res = ast_parseable_goto(chan, option->adata);
01418       return 0;
01419    case AST_ACTION_PLAYLIST:
01420    case AST_ACTION_BACKLIST:
01421       res = 0;
01422       c = ast_strdupa(option->adata);
01423       if (c) {
01424          while((n = strsep(&c, ";")))
01425             if ((res = ast_streamfile(chan, n, chan->language)) || (res = ast_waitstream(chan, (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : "")))
01426                break;
01427          ast_stopstream(chan);
01428       }
01429       return res;
01430    default:
01431       ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
01432       return 0;
01433    };
01434    return -1;
01435 }

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

Definition at line 373 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.

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

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

Definition at line 346 of file app.c.

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame::data, ast_frame::datalen, linear_state::fd, ast_frame::frametype, LOG_WARNING, ast_frame::offset, ast_frame::samples, and ast_frame::subclass.

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

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

Definition at line 335 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.

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

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

Definition at line 1437 of file app.c.

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

Referenced by ast_ivr_menu_run_internal().

01438 {
01439    int x;
01440    for (x=0;menu->options[x].option;x++)
01441       if (!strcasecmp(menu->options[x].option, option))
01442          return x;
01443    return -1;
01444 }

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

Definition at line 1446 of file app.c.

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

Referenced by read_newoption().

01447 {
01448    int x;
01449    for (x=0;menu->options[x].option;x++)
01450       if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 
01451             (menu->options[x].option[strlen(option)]))
01452          return x;
01453    return -1;
01454 }

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

Definition at line 1456 of file app.c.

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

Referenced by ast_ivr_menu_run_internal().

01457 {
01458    int res=0;
01459    int ms;
01460    while(option_matchmore(menu, exten)) {
01461       ms = chan->pbx ? chan->pbx->dtimeout : 5000;
01462       if (strlen(exten) >= maxexten - 1) 
01463          break;
01464       res = ast_waitfordigit(chan, ms);
01465       if (res < 1)
01466          break;
01467       exten[strlen(exten) + 1] = '\0';
01468       exten[strlen(exten)] = res;
01469    }
01470    return res > 0 ? 0 : res;
01471 }


Variable Documentation

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]

Definition at line 763 of file app.c.

char default_canceldtmf[] = "0" [static]

Definition at line 764 of file app.c.

int global_maxsilence = 0 [static]

Definition at line 537 of file app.c.

int global_silence_threshold = 128 [static]

Definition at line 536 of file app.c.

struct ast_generator linearstream [static]

Definition at line 393 of file app.c.


Generated on Wed Oct 28 15:47:58 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6