This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Data Structures | |
struct | ast_app_option |
A structure to hold the description of an application 'option'. More... | |
struct | ast_ivr_menu |
struct | ast_ivr_option |
Defines | |
#define | AST_APP_ARG(name) char *name |
Define an application argument. | |
#define | AST_APP_OPTION(option, flagno) [option] = { .flag = flagno } |
Declares an application option that does not accept an argument. | |
#define | AST_APP_OPTION_ARG(option, flagno, argno) [option] = { .flag = flagno, .arg_index = argno + 1 } |
Declares an application option that accepts an argument. | |
#define | AST_APP_OPTIONS(holder, options...) static const struct ast_app_option holder[128] = options |
Declares an array of options for an application. | |
#define | AST_DECLARE_APP_ARGS(name, arglist) |
Declare a structure to hold the application's arguments. | |
#define | AST_IVR_DECLARE_MENU(holder, title, flags, foo...) |
#define | AST_IVR_FLAG_AUTORESTART (1 << 0) |
#define | AST_STANDARD_APP_ARGS(args, parse) args.argc = ast_app_separate_args(parse, '|', args.argv, (sizeof(args) - sizeof(args.argc)) / sizeof(args.argv[0])) |
Performs the 'standard' argument separation process for an application. | |
#define | GROUP_CATEGORY_PREFIX "GROUP" |
Typedefs | |
typedef int(* | ast_ivr_callback )(struct ast_channel *chan, char *option, void *cbdata) |
Callback function for IVR. | |
Enumerations | |
enum | ast_ivr_action { AST_ACTION_UPONE, AST_ACTION_EXIT, AST_ACTION_CALLBACK, AST_ACTION_PLAYBACK, AST_ACTION_BACKGROUND, AST_ACTION_PLAYLIST, AST_ACTION_MENU, AST_ACTION_REPEAT, AST_ACTION_RESTART, AST_ACTION_TRANSFER, AST_ACTION_WAITOPTION, AST_ACTION_NOOP, AST_ACTION_BACKLIST } |
enum | AST_LOCK_RESULT { AST_LOCK_SUCCESS = 0, AST_LOCK_TIMEOUT = -1, AST_LOCK_PATH_NOT_FOUND = -2, AST_LOCK_FAILURE = -3 } |
Functions | |
int | ast_app_dtget (struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout) |
Present a dialtone and collect a certain length extension. | |
int | ast_app_getdata (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout) |
Plays a stream and gets DTMF data from a channel. | |
int | ast_app_getdata_full (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd) |
Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions. | |
int | ast_app_getvoice (struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec) |
int | ast_app_group_get_count (char *group, char *category) |
int | ast_app_group_match_get_count (char *groupmatch, char *category) |
int | ast_app_group_set_channel (struct ast_channel *chan, char *data) |
int | ast_app_group_split_group (char *data, char *group, int group_max, char *category, int category_max) |
int | ast_app_has_voicemail (const char *mailbox, const char *folder) |
int | ast_app_messagecount (const char *mailbox, int *newmsgs, int *oldmsgs) |
int | ast_app_parse_options (const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr) |
Parses a string containing application options and sets flags/arguments. | |
unsigned int | ast_app_separate_args (char *buf, char delim, char **array, int arraylen) |
Separate a string into arguments in an array. | |
int | ast_control_streamfile (struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms) |
int | ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, char *digits, int between) |
void | ast_install_vm_functions (int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs)) |
int | ast_ivr_menu_run (struct ast_channel *c, struct ast_ivr_menu *menu, void *cbdata) |
Runs an IVR menu. | |
int | ast_linear_stream (struct ast_channel *chan, const char *filename, int fd, int allowoverride) |
enum AST_LOCK_RESULT | ast_lock_path (const char *path) |
Lock a filesystem path. | |
int | ast_play_and_prepend (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence_ms) |
int | ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int silencethreshold, int maxsilence_ms, const char *path) |
int | ast_play_and_wait (struct ast_channel *chan, const char *fn) |
char * | ast_read_textfile (const char *file) |
int | ast_record_review (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path) |
int | ast_safe_system (const char *s) |
void | ast_uninstall_vm_functions (void) |
int | ast_unlock_path (const char *path) |
Definition in file app.h.
|
Define an application argument.
Definition at line 185 of file app.h. Referenced by __login_exec(), aqm_exec(), dial_exec_full(), disa_exec(), enumlookup_exec(), group_check_exec(), hasvoicemail_exec(), md5check_exec(), mixmonitor_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), transfer_exec(), txtcidname_exec(), upqm_exec(), and vm_box_exists(). |
|
Declares an application option that does not accept an argument.
|
|
Declares an application option that accepts an argument.
|
|
Declares an array of options for an application.
struct ast_option elements to hold the list of available options for an application. Each option must be declared using either the AST_APP_OPTION() or AST_APP_OPTION_ARG() macros.Example usage: enum { OPT_JUMP = (1 << 0), OPT_BLAH = (1 << 1), OPT_BLORT = (1 << 2), } my_app_option_flags; enum { OPT_ARG_BLAH = 0, OPT_ARG_BLORT, !! this entry tells how many possible arguments there are, and must be the last entry in the list OPT_ARG_ARRAY_SIZE, } my_app_option_args; AST_APP_OPTIONS(my_app_options, { AST_APP_OPTION('j', OPT_JUMP), AST_APP_OPTION_ARG('b', OPT_BLAH, OPT_ARG_BLAH), AST_APP_OPTION_BLORT('B', OPT_BLORT, OPT_ARG_BLORT), }); static int my_app_exec(struct ast_channel *chan, void *data) { char *options; struct ast_flags opts = { 0, }; char *opt_args[OPT_ARG_ARRAY_SIZE]; ... do any argument parsing here ... if (ast_parseoptions(my_app_options, &opts, opt_args, options)) { LOCAL_USER_REMOVE(u); return -1; } } |
|
Value: struct { \ unsigned int argc; \ char *argv[0]; \ arglist \ } name
Definition at line 202 of file app.h. Referenced by __login_exec(), aqm_exec(), dial_exec_full(), disa_exec(), enumlookup_exec(), group_check_exec(), hasvoicemail_exec(), md5check_exec(), mixmonitor_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), transfer_exec(), txtcidname_exec(), upqm_exec(), and vm_box_exists(). |
|
Value: static struct ast_ivr_option __options_##holder[] = foo;\ static struct ast_ivr_menu holder = { title, flags, __options_##holder } |
|
|
|
Performs the 'standard' argument separation process for an application.
Definition at line 218 of file app.h. Referenced by __login_exec(), aqm_exec(), dial_exec_full(), disa_exec(), enumlookup_exec(), group_check_exec(), hasvoicemail_exec(), md5check_exec(), mixmonitor_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), transfer_exec(), txtcidname_exec(), upqm_exec(), and vm_box_exists(). |
|
Definition at line 167 of file app.h. Referenced by ast_app_group_get_count(), ast_app_group_match_get_count(), ast_app_group_split_group(), clone_variables(), group_function_read(), group_list_function_read(), and group_show_channels(). |
|
Callback function for IVR.
|
|
Definition at line 37 of file app.h. 00037 { 00038 AST_ACTION_UPONE, /*!< adata is unused */ 00039 AST_ACTION_EXIT, /*!< adata is the return value for ast_ivr_menu_run if channel was not hungup */ 00040 AST_ACTION_CALLBACK, /*!< adata is an ast_ivr_callback */ 00041 AST_ACTION_PLAYBACK, /*!< adata is file to play */ 00042 AST_ACTION_BACKGROUND, /*!< adata is file to play */ 00043 AST_ACTION_PLAYLIST, /*!< adata is list of files, separated by ; to play */ 00044 AST_ACTION_MENU, /*!< adata is a pointer to an ast_ivr_menu */ 00045 AST_ACTION_REPEAT, /*!< adata is max # of repeats, cast to a pointer */ 00046 AST_ACTION_RESTART, /*!< adata is like repeat, but resets repeats to 0 */ 00047 AST_ACTION_TRANSFER, /*!< adata is a string with exten[@context] */ 00048 AST_ACTION_WAITOPTION, /*!< adata is a timeout, or 0 for defaults */ 00049 AST_ACTION_NOOP, /*!< adata is unused */ 00050 AST_ACTION_BACKLIST, /*!< adata is list of files separated by ; allows interruption */ 00051 } ast_ivr_action;
|
|
Definition at line 147 of file app.h. 00147 { 00148 AST_LOCK_SUCCESS = 0, 00149 AST_LOCK_TIMEOUT = -1, 00150 AST_LOCK_PATH_NOT_FOUND = -2, 00151 AST_LOCK_FAILURE = -3, 00152 };
|
|
Present a dialtone and collect a certain length extension.
Definition at line 62 of file app.c. References ast_get_indication_tone(), ast_ignore_pattern(), ast_log(), ast_matchmore_extension(), ast_playtones_start(), ast_playtones_stop(), ast_waitfordigit(), 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 }
|
|
Plays a stream and gets DTMF data from a channel.
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(), 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 }
|
|
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 }
|
|
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_FORMAT_SLINEAR, ast_log(), ast_set_read_format(), ast_streamfile(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::readformat, 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 }
|
|
Get the current channel count of the specified group and category. Definition at line 1044 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(). 01045 { 01046 struct ast_channel *chan; 01047 int count = 0; 01048 char *test; 01049 char cat[80]; 01050 char *s; 01051 01052 if (ast_strlen_zero(group)) 01053 return 0; 01054 01055 s = (!ast_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX; 01056 ast_copy_string(cat, s, sizeof(cat)); 01057 01058 chan = NULL; 01059 while ((chan = ast_channel_walk_locked(chan)) != NULL) { 01060 test = pbx_builtin_getvar_helper(chan, cat); 01061 if (test && !strcasecmp(test, group)) 01062 count++; 01063 ast_mutex_unlock(&chan->lock); 01064 } 01065 01066 return count; 01067 }
|
|
Get the current channel count of all groups that match the specified pattern and category. Definition at line 1069 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(). 01070 { 01071 regex_t regexbuf; 01072 struct ast_channel *chan; 01073 int count = 0; 01074 char *test; 01075 char cat[80]; 01076 char *s; 01077 01078 if (ast_strlen_zero(groupmatch)) 01079 return 0; 01080 01081 /* if regex compilation fails, return zero matches */ 01082 if (regcomp(®exbuf, groupmatch, REG_EXTENDED | REG_NOSUB)) 01083 return 0; 01084 01085 s = (!ast_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX; 01086 ast_copy_string(cat, s, sizeof(cat)); 01087 01088 chan = NULL; 01089 while ((chan = ast_channel_walk_locked(chan)) != NULL) { 01090 test = pbx_builtin_getvar_helper(chan, cat); 01091 if (test && !regexec(®exbuf, test, 0, NULL, 0)) 01092 count++; 01093 ast_mutex_unlock(&chan->lock); 01094 } 01095 01096 regfree(®exbuf); 01097 01098 return count; 01099 }
|
|
Set the group for a channel, splitting the provided data into group and category, if specified. Definition at line 1030 of file app.c. References ast_app_group_split_group(), group, and pbx_builtin_setvar_helper(). Referenced by group_function_write(), and group_set_exec(). 01031 { 01032 int res=0; 01033 char group[80] = ""; 01034 char category[80] = ""; 01035 01036 if (!ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) { 01037 pbx_builtin_setvar_helper(chan, category, group); 01038 } else 01039 res = -1; 01040 01041 return res; 01042 }
|
|
Split a group string into group and category, returning a default category if none is provided. Definition at line 1001 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(). 01002 { 01003 int res=0; 01004 char tmp[256]; 01005 char *grp=NULL, *cat=NULL; 01006 01007 if (!ast_strlen_zero(data)) { 01008 ast_copy_string(tmp, data, sizeof(tmp)); 01009 grp = tmp; 01010 cat = strchr(tmp, '@'); 01011 if (cat) { 01012 *cat = '\0'; 01013 cat++; 01014 } 01015 } 01016 01017 if (!ast_strlen_zero(grp)) 01018 ast_copy_string(group, grp, group_max); 01019 else 01020 res = -1; 01021 01022 if (cat) 01023 snprintf(category, category_max, "%s_%s", GROUP_CATEGORY_PREFIX, cat); 01024 else 01025 ast_copy_string(category, GROUP_CATEGORY_PREFIX, category_max); 01026 01027 return res; 01028 }
|
|
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(), 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 }
|
|
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 }
|
|
Parses a string containing application options and sets flags/arguments.
Definition at line 1519 of file app.c. References ast_app_option::arg_index, ast_clear_flag, AST_FLAGS_ALL, ast_log(), ast_set_flag, LOG_WARNING, and s. Referenced by chanspy_exec(), conf_exec(), dial_exec_full(), mixmonitor_exec(), page_exec(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_waitexten(), vm_exec(), and vm_execmain(). 01520 { 01521 char *s; 01522 int curarg; 01523 unsigned int argloc; 01524 char *arg; 01525 int res = 0; 01526 01527 ast_clear_flag(flags, AST_FLAGS_ALL); 01528 01529 if (!optstr) 01530 return 0; 01531 01532 s = optstr; 01533 while (*s) { 01534 curarg = *s++ & 0x7f; 01535 ast_set_flag(flags, options[curarg].flag); 01536 argloc = options[curarg].arg_index; 01537 if (*s == '(') { 01538 /* Has argument */ 01539 arg = ++s; 01540 while (*s && (*s != ')')) 01541 s++; 01542 if (*s) { 01543 if (argloc) 01544 args[argloc - 1] = arg; 01545 *s++ = '\0'; 01546 } else { 01547 ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg); 01548 res = -1; 01549 } 01550 } else if (argloc) { 01551 args[argloc - 1] = NULL; 01552 } 01553 } 01554 01555 return res; 01556 }
|
|
Separate a string into arguments in an array.
The array will be completely zeroed by this function before it populates any entries.
Definition at line 1101 of file app.c. Referenced by add_agent(), app_exec(), astman_get_variables(), builtin_function_cdr_read(), builtin_function_cdr_write(), builtin_function_checkmd5(), builtin_function_math(), chanspy_exec(), controlplayback_exec(), cut_internal(), dictate_exec(), function_db_exists(), function_db_read(), function_db_write(), pbx_builtin_background(), pbx_builtin_setvar(), pbx_builtin_waitexten(), read_exec(), vm_exec(), and vm_execmain(). 01102 { 01103 int argc; 01104 char *scan; 01105 int paren = 0; 01106 01107 if (!buf || !array || !arraylen) 01108 return 0; 01109 01110 memset(array, 0, arraylen * sizeof(*array)); 01111 01112 scan = buf; 01113 01114 for (argc = 0; *scan && (argc < arraylen - 1); argc++) { 01115 array[argc] = scan; 01116 for (; *scan; scan++) { 01117 if (*scan == '(') 01118 paren++; 01119 else if (*scan == ')') { 01120 if (paren) 01121 paren--; 01122 } else if ((*scan == delim) && !paren) { 01123 *scan++ = '\0'; 01124 break; 01125 } 01126 } 01127 } 01128 01129 if (*scan) 01130 array[argc++] = scan; 01131 01132 return argc; 01133 }
|
|
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 }
|
|
Send DTMF to chan (optionally entertain peer) Definition at line 281 of file app.c. References ast_autoservice_start(), AST_FRAME_DTMF, ast_log(), ast_safe_sleep(), ast_waitfor(), ast_write(), and LOG_WARNING. Referenced by ast_bridge_call(), 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 }
|
|
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 }
|
|
Runs an IVR menu.
Definition at line 1476 of file app.c. References ast_ivr_menu_run_internal(). Referenced by skel_exec(). 01477 { 01478 int res; 01479 res = ast_ivr_menu_run_internal(chan, menu, cbdata); 01480 /* Hide internal coding */ 01481 if (res > 0) 01482 res = 0; 01483 return res; 01484 }
|
|
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 }
|
|
Lock a filesystem path.
Definition at line 1135 of file app.c. References AST_LOCK_FAILURE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), LOG_WARNING, and s. Referenced by vm_lock_path(). 01136 { 01137 char *s; 01138 char *fs; 01139 int res; 01140 int fd; 01141 time_t start; 01142 01143 s = alloca(strlen(path) + 10); 01144 fs = alloca(strlen(path) + 20); 01145 01146 if (!fs || !s) { 01147 ast_log(LOG_WARNING, "Out of memory!\n"); 01148 return AST_LOCK_FAILURE; 01149 } 01150 01151 snprintf(fs, strlen(path) + 19, "%s/.lock-%08x", path, rand()); 01152 fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600); 01153 if (fd < 0) { 01154 fprintf(stderr, "Unable to create lock file '%s': %s\n", path, strerror(errno)); 01155 return AST_LOCK_PATH_NOT_FOUND; 01156 } 01157 close(fd); 01158 01159 snprintf(s, strlen(path) + 9, "%s/.lock", path); 01160 time(&start); 01161 while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) 01162 usleep(1); 01163 if (res) { 01164 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno)); 01165 return AST_LOCK_TIMEOUT; 01166 } else { 01167 unlink(fs); 01168 ast_log(LOG_DEBUG, "Locked path '%s'\n", path); 01169 return AST_LOCK_SUCCESS; 01170 } 01171 }
|
|
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 Definition at line 765 of file app.c. References ast_log(), ast_play_and_wait(), ast_strdupa, ast_streamfile(), ast_verbose(), ast_waitstream(), ast_writefile(), ast_channel::language, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, strsep(), ast_dsp::totalsilence, and VERBOSE_PREFIX_3. Referenced by vm_forwardoptions(). 00766 { 00767 int d = 0; 00768 char *fmts; 00769 char comment[256]; 00770 int x, fmtcnt=1, res=-1,outmsg=0; 00771 struct ast_frame *f; 00772 struct ast_filestream *others[MAX_OTHER_FORMATS]; 00773 struct ast_filestream *realfiles[MAX_OTHER_FORMATS]; 00774 char *sfmt[MAX_OTHER_FORMATS]; 00775 char *stringp=NULL; 00776 time_t start, end; 00777 struct ast_dsp *sildet; /* silence detector dsp */ 00778 int totalsilence = 0; 00779 int dspsilence = 0; 00780 int rfmt=0; 00781 char prependfile[80]; 00782 00783 if (silencethreshold < 0) 00784 silencethreshold = global_silence_threshold; 00785 00786 if (maxsilence < 0) 00787 maxsilence = global_maxsilence; 00788 00789 /* barf if no pointer passed to store duration in */ 00790 if (duration == NULL) { 00791 ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n"); 00792 return -1; 00793 } 00794 00795 ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); 00796 snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); 00797 00798 if (playfile || beep) { 00799 if (!beep) 00800 d = ast_play_and_wait(chan, playfile); 00801 if (d > -1) 00802 d = ast_streamfile(chan, "beep",chan->language); 00803 if (!d) 00804 d = ast_waitstream(chan,""); 00805 if (d < 0) 00806 return -1; 00807 } 00808 ast_copy_string(prependfile, recordfile, sizeof(prependfile)); 00809 strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); 00810 00811 fmts = ast_strdupa(fmt); 00812 00813 stringp=fmts; 00814 strsep(&stringp, "|"); 00815 ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); 00816 sfmt[0] = ast_strdupa(fmts); 00817 00818 while((fmt = strsep(&stringp, "|"))) { 00819 if (fmtcnt > MAX_OTHER_FORMATS - 1) { 00820 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n"); 00821 break; 00822 } 00823 sfmt[fmtcnt++] = ast_strdupa(fmt); 00824 } 00825 00826 time(&start); 00827 end=start; /* pre-initialize end to be same as start in case we never get into loop */ 00828 for (x=0;x<fmtcnt;x++) { 00829 others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700); 00830 ast_verbose( VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]); 00831 if (!others[x]) { 00832 break; 00833 } 00834 } 00835 00836 sildet = ast_dsp_new(); /* Create the silence detector */ 00837 if (!sildet) { 00838 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00839 return -1; 00840 } 00841 ast_dsp_set_threshold(sildet, silencethreshold); 00842 00843 if (maxsilence > 0) { 00844 rfmt = chan->readformat; 00845 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00846 if (res < 0) { 00847 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00848 ast_dsp_free(sildet); 00849 return -1; 00850 } 00851 } 00852 00853 if (x == fmtcnt) { 00854 /* Loop forever, writing the packets we read to the writer(s), until 00855 we read a # or get a hangup */ 00856 f = NULL; 00857 for(;;) { 00858 res = ast_waitfor(chan, 2000); 00859 if (!res) { 00860 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); 00861 /* Try one more time in case of masq */ 00862 res = ast_waitfor(chan, 2000); 00863 if (!res) { 00864 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); 00865 res = -1; 00866 } 00867 } 00868 00869 if (res < 0) { 00870 f = NULL; 00871 break; 00872 } 00873 f = ast_read(chan); 00874 if (!f) 00875 break; 00876 if (f->frametype == AST_FRAME_VOICE) { 00877 /* write each format */ 00878 for (x=0;x<fmtcnt;x++) { 00879 if (!others[x]) 00880 break; 00881 res = ast_writestream(others[x], f); 00882 } 00883 00884 /* Silence Detection */ 00885 if (maxsilence > 0) { 00886 dspsilence = 0; 00887 ast_dsp_silence(sildet, f, &dspsilence); 00888 if (dspsilence) 00889 totalsilence = dspsilence; 00890 else 00891 totalsilence = 0; 00892 00893 if (totalsilence > maxsilence) { 00894 /* Ended happily with silence */ 00895 if (option_verbose > 2) 00896 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); 00897 ast_frfree(f); 00898 res = 'S'; 00899 outmsg=2; 00900 break; 00901 } 00902 } 00903 /* Exit on any error */ 00904 if (res) { 00905 ast_log(LOG_WARNING, "Error writing frame\n"); 00906 ast_frfree(f); 00907 break; 00908 } 00909 } else if (f->frametype == AST_FRAME_VIDEO) { 00910 /* Write only once */ 00911 ast_writestream(others[0], f); 00912 } else if (f->frametype == AST_FRAME_DTMF) { 00913 /* stop recording with any digit */ 00914 if (option_verbose > 2) 00915 ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); 00916 res = 't'; 00917 outmsg = 2; 00918 ast_frfree(f); 00919 break; 00920 } 00921 if (maxtime) { 00922 time(&end); 00923 if (maxtime < (end - start)) { 00924 if (option_verbose > 2) 00925 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); 00926 res = 't'; 00927 outmsg=2; 00928 ast_frfree(f); 00929 break; 00930 } 00931 } 00932 ast_frfree(f); 00933 } 00934 if (end == start) time(&end); 00935 if (!f) { 00936 if (option_verbose > 2) 00937 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); 00938 res = -1; 00939 outmsg=1; 00940 #if 0 00941 /* delete all the prepend files */ 00942 for (x=0;x<fmtcnt;x++) { 00943 if (!others[x]) 00944 break; 00945 ast_closestream(others[x]); 00946 ast_filedelete(prependfile, sfmt[x]); 00947 } 00948 #endif 00949 } 00950 } else { 00951 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); 00952 } 00953 ast_dsp_free(sildet); 00954 *duration = end - start; 00955 #if 0 00956 if (outmsg > 1) { 00957 #else 00958 if (outmsg) { 00959 #endif 00960 struct ast_frame *fr; 00961 for (x=0;x<fmtcnt;x++) { 00962 snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); 00963 realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); 00964 if (!others[x] || !realfiles[x]) 00965 break; 00966 if (totalsilence) 00967 ast_stream_rewind(others[x], totalsilence-200); 00968 else 00969 ast_stream_rewind(others[x], 200); 00970 ast_truncstream(others[x]); 00971 /* add the original file too */ 00972 while ((fr = ast_readframe(realfiles[x]))) { 00973 ast_writestream(others[x],fr); 00974 } 00975 ast_closestream(others[x]); 00976 ast_closestream(realfiles[x]); 00977 ast_filerename(prependfile, recordfile, sfmt[x]); 00978 #if 0 00979 ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile); 00980 #endif 00981 ast_filedelete(prependfile, sfmt[x]); 00982 } 00983 } 00984 if (rfmt) { 00985 if (ast_set_read_format(chan, rfmt)) { 00986 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00987 } 00988 } 00989 if (outmsg) { 00990 if (outmsg > 1) { 00991 /* Let them know it worked */ 00992 ast_streamfile(chan, "auth-thankyou", chan->language); 00993 ast_waitstream(chan, ""); 00994 } 00995 } 00996 return res; 00997 }
|
|
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 Definition at line 540 of file app.c. References ast_log(), ast_play_and_wait(), ast_strdupa, ast_streamfile(), ast_verbose(), ast_waitstream(), ast_writefile(), ast_channel::language, LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, strsep(), ast_dsp::totalsilence, and VERBOSE_PREFIX_3. Referenced by ast_record_review(), dial_exec_full(), and play_record_review(). 00541 { 00542 int d; 00543 char *fmts; 00544 char comment[256]; 00545 int x, fmtcnt=1, res=-1,outmsg=0; 00546 struct ast_frame *f; 00547 struct ast_filestream *others[MAX_OTHER_FORMATS]; 00548 char *sfmt[MAX_OTHER_FORMATS]; 00549 char *stringp=NULL; 00550 time_t start, end; 00551 struct ast_dsp *sildet=NULL; /* silence detector dsp */ 00552 int totalsilence = 0; 00553 int dspsilence = 0; 00554 int 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 (f->subclass == '#') { 00692 if (option_verbose > 2) 00693 ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); 00694 res = '#'; 00695 outmsg = 2; 00696 ast_frfree(f); 00697 break; 00698 } 00699 if (f->subclass == '0') { 00700 /* Check for a '0' during message recording also, in case caller wants operator */ 00701 if (option_verbose > 2) 00702 ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass); 00703 res = '0'; 00704 outmsg = 0; 00705 ast_frfree(f); 00706 break; 00707 } 00708 } 00709 if (maxtime) { 00710 time(&end); 00711 if (maxtime < (end - start)) { 00712 if (option_verbose > 2) 00713 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); 00714 outmsg = 2; 00715 res = 't'; 00716 ast_frfree(f); 00717 break; 00718 } 00719 } 00720 ast_frfree(f); 00721 } 00722 if (end == start) time(&end); 00723 if (!f) { 00724 if (option_verbose > 2) 00725 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); 00726 res = -1; 00727 outmsg=1; 00728 } 00729 } else { 00730 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); 00731 } 00732 00733 if (silgen) 00734 ast_channel_stop_silence_generator(chan, silgen); 00735 00736 *duration = end - start; 00737 00738 for (x=0;x<fmtcnt;x++) { 00739 if (!others[x]) 00740 break; 00741 if (res > 0) { 00742 if (totalsilence) 00743 ast_stream_rewind(others[x], totalsilence-200); 00744 else 00745 ast_stream_rewind(others[x], 200); 00746 } 00747 ast_truncstream(others[x]); 00748 ast_closestream(others[x]); 00749 } 00750 if (rfmt) { 00751 if (ast_set_read_format(chan, rfmt)) { 00752 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00753 } 00754 } 00755 if (outmsg > 1) { 00756 /* Let them know recording is stopped */ 00757 if(!ast_streamfile(chan, "auth-thankyou", chan->language)) 00758 ast_waitstream(chan, ""); 00759 } 00760 if (sildet) 00761 ast_dsp_free(sildet); 00762 return res; 00763 }
|
|
|
Read a file into asterisk Definition at line 1486 of file app.c. References ast_log(), free, LOG_WARNING, and malloc. Referenced by readfile_exec(). 01487 { 01488 int fd; 01489 char *output=NULL; 01490 struct stat filesize; 01491 int count=0; 01492 int res; 01493 if(stat(filename,&filesize)== -1){ 01494 ast_log(LOG_WARNING,"Error can't stat %s\n", filename); 01495 return NULL; 01496 } 01497 count=filesize.st_size + 1; 01498 fd = open(filename, O_RDONLY); 01499 if (fd < 0) { 01500 ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno)); 01501 return NULL; 01502 } 01503 output=(char *)malloc(count); 01504 if (output) { 01505 res = read(fd, output, count - 1); 01506 if (res == count - 1) { 01507 output[res] = '\0'; 01508 } else { 01509 ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno)); 01510 free(output); 01511 output = NULL; 01512 } 01513 } else 01514 ast_log(LOG_WARNING, "Out of memory!\n"); 01515 close(fd); 01516 return output; 01517 }
|
|
Allow to record message and have a review option Definition at line 1184 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, maxsilence, silencethreshold, and VERBOSE_PREFIX_3. Referenced by conf_run(). 01185 { 01186 int silencethreshold = 128; 01187 int maxsilence=0; 01188 int res = 0; 01189 int cmd = 0; 01190 int max_attempts = 3; 01191 int attempts = 0; 01192 int recorded = 0; 01193 int message_exists = 0; 01194 /* Note that urgent and private are for flagging messages as such in the future */ 01195 01196 /* barf if no pointer passed to store duration in */ 01197 if (duration == NULL) { 01198 ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n"); 01199 return -1; 01200 } 01201 01202 cmd = '3'; /* Want to start by recording */ 01203 01204 while ((cmd >= 0) && (cmd != 't')) { 01205 switch (cmd) { 01206 case '1': 01207 if (!message_exists) { 01208 /* In this case, 1 is to record a message */ 01209 cmd = '3'; 01210 break; 01211 } else { 01212 ast_streamfile(chan, "vm-msgsaved", chan->language); 01213 ast_waitstream(chan, ""); 01214 cmd = 't'; 01215 return res; 01216 } 01217 case '2': 01218 /* Review */ 01219 ast_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n"); 01220 ast_streamfile(chan, recordfile, chan->language); 01221 cmd = ast_waitstream(chan, AST_DIGIT_ANY); 01222 break; 01223 case '3': 01224 message_exists = 0; 01225 /* Record */ 01226 if (recorded == 1) 01227 ast_verbose(VERBOSE_PREFIX_3 "Re-recording\n"); 01228 else 01229 ast_verbose(VERBOSE_PREFIX_3 "Recording\n"); 01230 recorded = 1; 01231 cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path); 01232 if (cmd == -1) { 01233 /* User has hung up, no options to give */ 01234 return cmd; 01235 } 01236 if (cmd == '0') { 01237 break; 01238 } else if (cmd == '*') { 01239 break; 01240 } 01241 else { 01242 /* If all is well, a message exists */ 01243 message_exists = 1; 01244 cmd = 0; 01245 } 01246 break; 01247 case '4': 01248 case '5': 01249 case '6': 01250 case '7': 01251 case '8': 01252 case '9': 01253 case '*': 01254 case '#': 01255 cmd = ast_play_and_wait(chan, "vm-sorry"); 01256 break; 01257 default: 01258 if (message_exists) { 01259 cmd = ast_play_and_wait(chan, "vm-review"); 01260 } 01261 else { 01262 cmd = ast_play_and_wait(chan, "vm-torerecord"); 01263 if (!cmd) 01264 cmd = ast_waitfordigit(chan, 600); 01265 } 01266 01267 if (!cmd) 01268 cmd = ast_waitfordigit(chan, 6000); 01269 if (!cmd) { 01270 attempts++; 01271 } 01272 if (attempts > max_attempts) { 01273 cmd = 't'; 01274 } 01275 } 01276 } 01277 if (cmd == 't') 01278 cmd = 0; 01279 return cmd; 01280 }
|
|
Safely spawn an external program while closing file descriptors
Definition at line 424 of file asterisk.c. References ast_mutex_lock(), ast_mutex_unlock(), and null_sig_handler(). Referenced by alarmreceiver_exec(), ast_closestream(), ast_monitor_change_fname(), ast_monitor_start(), ast_monitor_stop(), consolehandler(), forward_message(), process_text_line(), remoteconsolehandler(), run_externnotify(), sendmail(), sendpage(), system_exec_helper(), and vm_change_password_shell(). 00425 { 00426 pid_t pid; 00427 int x; 00428 int res; 00429 struct rusage rusage; 00430 int status; 00431 unsigned int level; 00432 00433 /* keep track of how many ast_safe_system() functions 00434 are running at this moment 00435 */ 00436 ast_mutex_lock(&safe_system_lock); 00437 level = safe_system_level++; 00438 00439 /* only replace the handler if it has not already been done */ 00440 if (level == 0) 00441 safe_system_prev_handler = signal(SIGCHLD, null_sig_handler); 00442 00443 ast_mutex_unlock(&safe_system_lock); 00444 00445 pid = fork(); 00446 00447 if (pid == 0) { 00448 /* Close file descriptors and launch system command */ 00449 for (x = STDERR_FILENO + 1; x < 4096; x++) 00450 close(x); 00451 execl("/bin/sh", "/bin/sh", "-c", s, NULL); 00452 exit(1); 00453 } else if (pid > 0) { 00454 for(;;) { 00455 res = wait4(pid, &status, 0, &rusage); 00456 if (res > -1) { 00457 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1; 00458 break; 00459 } else if (errno != EINTR) 00460 break; 00461 } 00462 } else { 00463 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno)); 00464 res = -1; 00465 } 00466 00467 ast_mutex_lock(&safe_system_lock); 00468 level = --safe_system_level; 00469 00470 /* only restore the handler if we are the last one */ 00471 if (level == 0) 00472 signal(SIGCHLD, safe_system_prev_handler); 00473 00474 ast_mutex_unlock(&safe_system_lock); 00475 00476 return res; 00477 }
|
|
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 }
|
|
Unlock a path Definition at line 1173 of file app.c. Referenced by copy_message(), count_messages(), and leave_voicemail(). 01174 { 01175 char *s; 01176 s = alloca(strlen(path) + 10); 01177 if (!s) 01178 return -1; 01179 snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock"); 01180 ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path); 01181 return unlink(s); 01182 }
|