#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/indications.h"
Go to the source code of this file.
Data Structures | |
struct | linear_state |
Defines | |
#define | MAX_OTHER_FORMATS 10 |
#define | RES_EXIT (1 << 17) |
#define | RES_REPEAT (1 << 18) |
#define | RES_RESTART ((1 << 19) | RES_REPEAT) |
#define | RES_UPONE (1 << 16) |
Functions | |
int | ast_app_dtget (struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout) |
Present a dialtone and collect a certain length extension. | |
int | ast_app_getdata (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout) |
Plays a stream and gets DTMF data from a channel. | |
int | ast_app_getdata_full (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd) |
Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions. | |
int | ast_app_getvoice (struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec) |
int | ast_app_group_get_count (char *group, char *category) |
int | ast_app_group_match_get_count (char *groupmatch, char *category) |
int | ast_app_group_set_channel (struct ast_channel *chan, char *data) |
int | ast_app_group_split_group (char *data, char *group, int group_max, char *category, int category_max) |
int | ast_app_has_voicemail (const char *mailbox, const char *folder) |
int | ast_app_messagecount (const char *mailbox, int *newmsgs, int *oldmsgs) |
int | ast_app_parse_options (const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr) |
Parses a string containing application options and sets flags/arguments. | |
unsigned int | ast_app_separate_args (char *buf, char delim, char **array, int arraylen) |
Separate a string into arguments in an array. | |
int | ast_control_streamfile (struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms) |
int | ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, char *digits, int between) |
void | ast_install_vm_functions (int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs)) |
int | ast_ivr_menu_run (struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata) |
Runs an IVR menu. | |
int | ast_ivr_menu_run_internal (struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata) |
int | ast_linear_stream (struct ast_channel *chan, const char *filename, int fd, int allowoverride) |
enum AST_LOCK_RESULT | ast_lock_path (const char *path) |
Lock a filesystem path. | |
int | ast_play_and_prepend (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence) |
int | ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path) |
int | ast_play_and_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) |
int | ivr_dispatch (struct ast_channel *chan, struct ast_ivr_option *option, char *exten, void *cbdata) |
void * | linear_alloc (struct ast_channel *chan, void *params) |
int | linear_generator (struct ast_channel *chan, void *data, int len, int samples) |
void | linear_release (struct ast_channel *chan, void *params) |
int | option_exists (struct ast_ivr_menu *menu, char *option) |
int | option_matchmore (struct ast_ivr_menu *menu, char *option) |
int | read_newoption (struct ast_channel *chan, struct ast_ivr_menu *menu, char *exten, int maxexten) |
Variables | |
int(* | ast_has_voicemail_func )(const char *mailbox, const char *folder) = NULL |
int(* | ast_messagecount_func )(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL |
int | global_maxsilence = 0 |
int | global_silence_threshold = 128 |
ast_generator | linearstream |
Definition in file app.c.
|
Definition at line 52 of file app.c. Referenced by ast_play_and_prepend(), and ast_play_and_record(). |
|
Definition at line 1285 of file app.c. Referenced by ivr_dispatch(). |
|
Definition at line 1286 of file app.c. Referenced by ivr_dispatch(). |
|
|
|
|
|
Present a dialtone and collect a certain length extension.
Definition at line 62 of file app.c. References ast_exists_extension(), ast_get_indication_tone(), ast_ignore_pattern(), ast_log(), ast_matchmore_extension(), ast_playtones_start(), ast_playtones_stop(), ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, tone_zone_sound::data, ast_pbx::dtimeout, LOG_NOTICE, ast_channel::pbx, and ast_channel::zone. Referenced by builtin_atxfer(), and builtin_blindtransfer(). 00063 { 00064 struct tone_zone_sound *ts; 00065 int res=0, x=0; 00066 00067 if(maxlen > size) 00068 maxlen = size; 00069 00070 if(!timeout && chan->pbx) 00071 timeout = chan->pbx->dtimeout; 00072 else if(!timeout) 00073 timeout = 5; 00074 00075 ts = ast_get_indication_tone(chan->zone,"dial"); 00076 if (ts && ts->data[0]) 00077 res = ast_playtones_start(chan, 0, ts->data, 0); 00078 else 00079 ast_log(LOG_NOTICE,"Huh....? no dial for indications?\n"); 00080 00081 for (x = strlen(collect); strlen(collect) < maxlen; ) { 00082 res = ast_waitfordigit(chan, timeout); 00083 if (!ast_ignore_pattern(context, collect)) 00084 ast_playtones_stop(chan); 00085 if (res < 1) 00086 break; 00087 collect[x++] = res; 00088 if (!ast_matchmore_extension(chan, context, collect, 1, chan->cid.cid_num)) { 00089 if (collect[x-1] == '#') { 00090 /* Not a valid extension, ending in #, assume the # was to finish dialing */ 00091 collect[x-1] = '\0'; 00092 } 00093 break; 00094 } 00095 } 00096 if (res >= 0) { 00097 if (ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num)) 00098 res = 1; 00099 else 00100 res = 0; 00101 } 00102 return res; 00103 }
|
|
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, ast_pbx::rtimeout, and s. Referenced by __login_exec(), auth_exec(), conf_exec(), dictate_exec(), find_conf(), read_exec(), testclient_exec(), testserver_exec(), and vm_exec(). 00110 { 00111 int res,to,fto; 00112 /* XXX Merge with full version? XXX */ 00113 if (maxlen) 00114 s[0] = '\0'; 00115 if (prompt) { 00116 res = ast_streamfile(c, prompt, c->language); 00117 if (res < 0) 00118 return res; 00119 } 00120 fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000; 00121 to = c->pbx ? c->pbx->dtimeout * 1000 : 2000; 00122 00123 if (timeout > 0) 00124 fto = to = timeout; 00125 if (timeout < 0) 00126 fto = to = 1000000000; 00127 res = ast_readstring(c, s, maxlen, to, fto, "#"); 00128 return res; 00129 }
|
|
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(), ast_channel::language, and s. 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_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, 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, and ast_frame::subclass. 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 1046 of file app.c. References ast_channel_walk_locked(), ast_mutex_unlock(), ast_strlen_zero(), ast_channel::lock, pbx_builtin_getvar_helper(), and s. Referenced by group_check_exec(), group_count_exec(), and group_count_function_read(). 01047 { 01048 struct ast_channel *chan; 01049 int count = 0; 01050 char *test; 01051 char cat[80]; 01052 char *s; 01053 01054 if (ast_strlen_zero(group)) 01055 return 0; 01056 01057 s = (!ast_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX; 01058 ast_copy_string(cat, s, sizeof(cat)); 01059 01060 chan = NULL; 01061 while ((chan = ast_channel_walk_locked(chan)) != NULL) { 01062 test = pbx_builtin_getvar_helper(chan, cat); 01063 if (test && !strcasecmp(test, group)) 01064 count++; 01065 ast_mutex_unlock(&chan->lock); 01066 } 01067 01068 return count; 01069 }
|
|
Get the current channel count of all groups that match the specified pattern and category. Definition at line 1071 of file app.c. References ast_channel_walk_locked(), ast_mutex_unlock(), ast_strlen_zero(), ast_channel::lock, pbx_builtin_getvar_helper(), and s. Referenced by group_match_count_exec(), and group_match_count_function_read(). 01072 { 01073 regex_t regexbuf; 01074 struct ast_channel *chan; 01075 int count = 0; 01076 char *test; 01077 char cat[80]; 01078 char *s; 01079 01080 if (ast_strlen_zero(groupmatch)) 01081 return 0; 01082 01083 /* if regex compilation fails, return zero matches */ 01084 if (regcomp(®exbuf, groupmatch, REG_EXTENDED | REG_NOSUB)) 01085 return 0; 01086 01087 s = (!ast_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX; 01088 ast_copy_string(cat, s, sizeof(cat)); 01089 01090 chan = NULL; 01091 while ((chan = ast_channel_walk_locked(chan)) != NULL) { 01092 test = pbx_builtin_getvar_helper(chan, cat); 01093 if (test && !regexec(®exbuf, test, 0, NULL, 0)) 01094 count++; 01095 ast_mutex_unlock(&chan->lock); 01096 } 01097 01098 regfree(®exbuf); 01099 01100 return count; 01101 }
|
|
Set the group for a channel, splitting the provided data into group and category, if specified. Definition at line 1032 of file app.c. References ast_app_group_split_group(), and pbx_builtin_setvar_helper(). Referenced by dial_exec_full(), group_function_write(), and group_set_exec(). 01033 { 01034 int res=0; 01035 char group[80] = ""; 01036 char category[80] = ""; 01037 01038 if (!ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) { 01039 pbx_builtin_setvar_helper(chan, category, group); 01040 } else 01041 res = -1; 01042 01043 return res; 01044 }
|
|
Split a group string into group and category, returning a default category if none is provided. Definition at line 1003 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(). 01004 { 01005 int res=0; 01006 char tmp[256]; 01007 char *grp=NULL, *cat=NULL; 01008 01009 if (!ast_strlen_zero(data)) { 01010 ast_copy_string(tmp, data, sizeof(tmp)); 01011 grp = tmp; 01012 cat = strchr(tmp, '@'); 01013 if (cat) { 01014 *cat = '\0'; 01015 cat++; 01016 } 01017 } 01018 01019 if (!ast_strlen_zero(grp)) 01020 ast_copy_string(group, grp, group_max); 01021 else 01022 res = -1; 01023 01024 if (cat) 01025 snprintf(category, category_max, "%s_%s", GROUP_CATEGORY_PREFIX, cat); 01026 else 01027 ast_copy_string(category, GROUP_CATEGORY_PREFIX, category_max); 01028 01029 return res; 01030 }
|
|
Determine if a given mailbox has any voicemail Definition at line 249 of file app.c. References ast_has_voicemail_func, ast_verbose(), option_verbose, and VERBOSE_PREFIX_3. Referenced by action_mailboxstatus(), do_monitor(), has_voicemail(), notify_new_message(), play_dialtone(), and update_registry(). 00250 { 00251 static int warned = 0; 00252 if (ast_has_voicemail_func) 00253 return ast_has_voicemail_func(mailbox, folder); 00254 00255 if ((option_verbose > 2) && !warned) { 00256 ast_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX"); 00257 warned++; 00258 } 00259 return 0; 00260 }
|
|
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 1521 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(). 01522 { 01523 char *s; 01524 int curarg; 01525 unsigned int argloc; 01526 char *arg; 01527 int res = 0; 01528 01529 ast_clear_flag(flags, AST_FLAGS_ALL); 01530 01531 if (!optstr) 01532 return 0; 01533 01534 s = optstr; 01535 while (*s) { 01536 curarg = *s++ & 0x7f; 01537 ast_set_flag(flags, options[curarg].flag); 01538 argloc = options[curarg].arg_index; 01539 if (*s == '(') { 01540 /* Has argument */ 01541 arg = ++s; 01542 while (*s && (*s != ')')) 01543 s++; 01544 if (*s) { 01545 if (argloc) 01546 args[argloc - 1] = arg; 01547 *s++ = '\0'; 01548 } else { 01549 ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg); 01550 res = -1; 01551 } 01552 } else if (argloc) { 01553 args[argloc - 1] = NULL; 01554 } 01555 } 01556 01557 return res; 01558 }
|
|
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 1103 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(). 01104 { 01105 int argc; 01106 char *scan; 01107 int paren = 0; 01108 01109 if (!buf || !array || !arraylen) 01110 return 0; 01111 01112 memset(array, 0, arraylen * sizeof(*array)); 01113 01114 scan = buf; 01115 01116 for (argc = 0; *scan && (argc < arraylen - 1); argc++) { 01117 array[argc] = scan; 01118 for (; *scan; scan++) { 01119 if (*scan == '(') 01120 paren++; 01121 else if (*scan == ')') { 01122 if (paren) 01123 paren--; 01124 } else if ((*scan == delim) && !paren) { 01125 *scan++ = '\0'; 01126 break; 01127 } 01128 } 01129 } 01130 01131 if (*scan) 01132 array[argc++] = scan; 01133 01134 return argc; 01135 }
|
|
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_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_autoservice_stop(), 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(). 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 1478 of file app.c. References ast_ivr_menu_run_internal(). Referenced by skel_exec(). 01479 { 01480 int res; 01481 res = ast_ivr_menu_run_internal(chan, menu, cbdata); 01482 /* Hide internal coding */ 01483 if (res > 0) 01484 res = 0; 01485 return res; 01486 }
|
|
Definition at line 1398 of file app.c. References AST_DIGIT_ANY, ast_log(), ivr_dispatch(), LOG_DEBUG, LOG_WARNING, ast_ivr_option::option, option_exists(), ast_ivr_menu::options, read_newoption(), and ast_ivr_menu::title. Referenced by ast_ivr_menu_run(), and ivr_dispatch(). 01399 { 01400 /* Execute an IVR menu structure */ 01401 int res=0; 01402 int pos = 0; 01403 int retries = 0; 01404 char exten[AST_MAX_EXTENSION] = "s"; 01405 if (option_exists(menu, "s") < 0) { 01406 strcpy(exten, "g"); 01407 if (option_exists(menu, "g") < 0) { 01408 ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title); 01409 return -1; 01410 } 01411 } 01412 while(!res) { 01413 while(menu->options[pos].option) { 01414 if (!strcasecmp(menu->options[pos].option, exten)) { 01415 res = ivr_dispatch(chan, menu->options + pos, exten, cbdata); 01416 ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res); 01417 if (res < 0) 01418 break; 01419 else if (res & RES_UPONE) 01420 return 0; 01421 else if (res & RES_EXIT) 01422 return res; 01423 else if (res & RES_REPEAT) { 01424 int maxretries = res & 0xffff; 01425 if ((res & RES_RESTART) == RES_RESTART) { 01426 retries = 0; 01427 } else 01428 retries++; 01429 if (!maxretries) 01430 maxretries = 3; 01431 if ((maxretries > 0) && (retries >= maxretries)) { 01432 ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries); 01433 return -2; 01434 } else { 01435 if (option_exists(menu, "g") > -1) 01436 strcpy(exten, "g"); 01437 else if (option_exists(menu, "s") > -1) 01438 strcpy(exten, "s"); 01439 } 01440 pos=0; 01441 continue; 01442 } else if (res && strchr(AST_DIGIT_ANY, res)) { 01443 ast_log(LOG_DEBUG, "Got start of extension, %c\n", res); 01444 exten[1] = '\0'; 01445 exten[0] = res; 01446 if ((res = read_newoption(chan, menu, exten, sizeof(exten)))) 01447 break; 01448 if (option_exists(menu, exten) < 0) { 01449 if (option_exists(menu, "i")) { 01450 ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n"); 01451 strcpy(exten, "i"); 01452 pos = 0; 01453 continue; 01454 } else { 01455 ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n"); 01456 res = -2; 01457 break; 01458 } 01459 } else { 01460 ast_log(LOG_DEBUG, "New existing extension: %s\n", exten); 01461 pos = 0; 01462 continue; 01463 } 01464 } 01465 } 01466 pos++; 01467 } 01468 ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res); 01469 pos = 0; 01470 if (!strcasecmp(exten, "s")) 01471 strcpy(exten, "g"); 01472 else 01473 break; 01474 } 01475 return res; 01476 }
|
|
Stream a filename (or file descriptor) as a generator. Definition at line 401 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, 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 1137 of file app.c. References AST_LOCK_RESULT, ast_log(), LOG_DEBUG, LOG_WARNING, and s. Referenced by vm_lock_path(). 01138 { 01139 char *s; 01140 char *fs; 01141 int res; 01142 int fd; 01143 time_t start; 01144 01145 s = alloca(strlen(path) + 10); 01146 fs = alloca(strlen(path) + 20); 01147 01148 if (!fs || !s) { 01149 ast_log(LOG_WARNING, "Out of memory!\n"); 01150 return AST_LOCK_FAILURE; 01151 } 01152 01153 snprintf(fs, strlen(path) + 19, "%s/.lock-%08x", path, rand()); 01154 fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600); 01155 if (fd < 0) { 01156 fprintf(stderr, "Unable to create lock file '%s': %s\n", path, strerror(errno)); 01157 return AST_LOCK_PATH_NOT_FOUND; 01158 } 01159 close(fd); 01160 01161 snprintf(s, strlen(path) + 9, "%s/.lock", path); 01162 time(&start); 01163 while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) 01164 usleep(1); 01165 if (res) { 01166 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno)); 01167 return AST_LOCK_TIMEOUT; 01168 } else { 01169 unlink(fs); 01170 ast_log(LOG_DEBUG, "Locked path '%s'\n", path); 01171 return AST_LOCK_SUCCESS; 01172 } 01173 }
|
|
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 766 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_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(), fmt, 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, and VERBOSE_PREFIX_3. Referenced by vm_forwardoptions(). 00767 { 00768 int d = 0; 00769 char *fmts; 00770 char comment[256]; 00771 int x, fmtcnt=1, res=-1,outmsg=0; 00772 struct ast_frame *f; 00773 struct ast_filestream *others[MAX_OTHER_FORMATS]; 00774 struct ast_filestream *realfiles[MAX_OTHER_FORMATS]; 00775 char *sfmt[MAX_OTHER_FORMATS]; 00776 char *stringp=NULL; 00777 time_t start, end; 00778 struct ast_dsp *sildet; /* silence detector dsp */ 00779 int totalsilence = 0; 00780 int dspsilence = 0; 00781 int gotsilence = 0; /* did we timeout for silence? */ 00782 int rfmt=0; 00783 char prependfile[80]; 00784 00785 if (silencethreshold < 0) 00786 silencethreshold = global_silence_threshold; 00787 00788 if (maxsilence < 0) 00789 maxsilence = global_maxsilence; 00790 00791 /* barf if no pointer passed to store duration in */ 00792 if (duration == NULL) { 00793 ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n"); 00794 return -1; 00795 } 00796 00797 ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); 00798 snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); 00799 00800 if (playfile || beep) { 00801 if (!beep) 00802 d = ast_play_and_wait(chan, playfile); 00803 if (d > -1) 00804 d = ast_streamfile(chan, "beep",chan->language); 00805 if (!d) 00806 d = ast_waitstream(chan,""); 00807 if (d < 0) 00808 return -1; 00809 } 00810 ast_copy_string(prependfile, recordfile, sizeof(prependfile)); 00811 strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); 00812 00813 fmts = ast_strdupa(fmt); 00814 00815 stringp=fmts; 00816 strsep(&stringp, "|"); 00817 ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); 00818 sfmt[0] = ast_strdupa(fmts); 00819 00820 while((fmt = strsep(&stringp, "|"))) { 00821 if (fmtcnt > MAX_OTHER_FORMATS - 1) { 00822 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n"); 00823 break; 00824 } 00825 sfmt[fmtcnt++] = ast_strdupa(fmt); 00826 } 00827 00828 time(&start); 00829 end=start; /* pre-initialize end to be same as start in case we never get into loop */ 00830 for (x=0;x<fmtcnt;x++) { 00831 others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700); 00832 ast_verbose( VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]); 00833 if (!others[x]) { 00834 break; 00835 } 00836 } 00837 00838 sildet = ast_dsp_new(); /* Create the silence detector */ 00839 if (!sildet) { 00840 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00841 return -1; 00842 } 00843 ast_dsp_set_threshold(sildet, silencethreshold); 00844 00845 if (maxsilence > 0) { 00846 rfmt = chan->readformat; 00847 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00848 if (res < 0) { 00849 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00850 ast_dsp_free(sildet); 00851 return -1; 00852 } 00853 } 00854 00855 if (x == fmtcnt) { 00856 /* Loop forever, writing the packets we read to the writer(s), until 00857 we read a # or get a hangup */ 00858 f = NULL; 00859 for(;;) { 00860 res = ast_waitfor(chan, 2000); 00861 if (!res) { 00862 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); 00863 /* Try one more time in case of masq */ 00864 res = ast_waitfor(chan, 2000); 00865 if (!res) { 00866 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); 00867 res = -1; 00868 } 00869 } 00870 00871 if (res < 0) { 00872 f = NULL; 00873 break; 00874 } 00875 f = ast_read(chan); 00876 if (!f) 00877 break; 00878 if (f->frametype == AST_FRAME_VOICE) { 00879 /* write each format */ 00880 for (x=0;x<fmtcnt;x++) { 00881 if (!others[x]) 00882 break; 00883 res = ast_writestream(others[x], f); 00884 } 00885 00886 /* Silence Detection */ 00887 if (maxsilence > 0) { 00888 dspsilence = 0; 00889 ast_dsp_silence(sildet, f, &dspsilence); 00890 if (dspsilence) 00891 totalsilence = dspsilence; 00892 else 00893 totalsilence = 0; 00894 00895 if (totalsilence > maxsilence) { 00896 /* Ended happily with silence */ 00897 if (option_verbose > 2) 00898 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); 00899 ast_frfree(f); 00900 gotsilence = 1; 00901 outmsg=2; 00902 break; 00903 } 00904 } 00905 /* Exit on any error */ 00906 if (res) { 00907 ast_log(LOG_WARNING, "Error writing frame\n"); 00908 ast_frfree(f); 00909 break; 00910 } 00911 } else if (f->frametype == AST_FRAME_VIDEO) { 00912 /* Write only once */ 00913 ast_writestream(others[0], f); 00914 } else if (f->frametype == AST_FRAME_DTMF) { 00915 /* stop recording with any digit */ 00916 if (option_verbose > 2) 00917 ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); 00918 res = 't'; 00919 outmsg = 2; 00920 ast_frfree(f); 00921 break; 00922 } 00923 if (maxtime) { 00924 time(&end); 00925 if (maxtime < (end - start)) { 00926 if (option_verbose > 2) 00927 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); 00928 res = 't'; 00929 outmsg=2; 00930 ast_frfree(f); 00931 break; 00932 } 00933 } 00934 ast_frfree(f); 00935 } 00936 if (end == start) time(&end); 00937 if (!f) { 00938 if (option_verbose > 2) 00939 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); 00940 res = -1; 00941 outmsg=1; 00942 #if 0 00943 /* delete all the prepend files */ 00944 for (x=0;x<fmtcnt;x++) { 00945 if (!others[x]) 00946 break; 00947 ast_closestream(others[x]); 00948 ast_filedelete(prependfile, sfmt[x]); 00949 } 00950 #endif 00951 } 00952 } else { 00953 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); 00954 } 00955 ast_dsp_free(sildet); 00956 *duration = end - start; 00957 #if 0 00958 if (outmsg > 1) { 00959 #else 00960 if (outmsg) { 00961 #endif 00962 struct ast_frame *fr; 00963 for (x=0;x<fmtcnt;x++) { 00964 snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); 00965 realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); 00966 if (!others[x] || !realfiles[x]) 00967 break; 00968 if (totalsilence) 00969 ast_stream_rewind(others[x], totalsilence-200); 00970 else 00971 ast_stream_rewind(others[x], 200); 00972 ast_truncstream(others[x]); 00973 /* add the original file too */ 00974 while ((fr = ast_readframe(realfiles[x]))) { 00975 ast_writestream(others[x],fr); 00976 } 00977 ast_closestream(others[x]); 00978 ast_closestream(realfiles[x]); 00979 ast_filerename(prependfile, recordfile, sfmt[x]); 00980 #if 0 00981 ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile); 00982 #endif 00983 ast_filedelete(prependfile, sfmt[x]); 00984 } 00985 } 00986 if (rfmt) { 00987 if (ast_set_read_format(chan, rfmt)) { 00988 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00989 } 00990 } 00991 if (outmsg) { 00992 if (outmsg > 1) { 00993 /* Let them know it worked */ 00994 ast_streamfile(chan, "auth-thankyou", chan->language); 00995 ast_waitstream(chan, ""); 00996 } 00997 } 00998 return res; 00999 }
|
|
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_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_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(), fmt, 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, 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 gotsilence = 0; /* did we timeout for silence? */ 00555 int rfmt=0; 00556 struct ast_silence_generator *silgen = NULL; 00557 00558 if (silencethreshold < 0) 00559 silencethreshold = global_silence_threshold; 00560 00561 if (maxsilence < 0) 00562 maxsilence = global_maxsilence; 00563 00564 /* barf if no pointer passed to store duration in */ 00565 if (duration == NULL) { 00566 ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n"); 00567 return -1; 00568 } 00569 00570 ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); 00571 snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); 00572 00573 if (playfile) { 00574 d = ast_play_and_wait(chan, playfile); 00575 if (d > -1) 00576 d = ast_streamfile(chan, "beep",chan->language); 00577 if (!d) 00578 d = ast_waitstream(chan,""); 00579 if (d < 0) 00580 return -1; 00581 } 00582 00583 fmts = ast_strdupa(fmt); 00584 00585 stringp=fmts; 00586 strsep(&stringp, "|"); 00587 ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); 00588 sfmt[0] = ast_strdupa(fmts); 00589 00590 while((fmt = strsep(&stringp, "|"))) { 00591 if (fmtcnt > MAX_OTHER_FORMATS - 1) { 00592 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n"); 00593 break; 00594 } 00595 sfmt[fmtcnt++] = ast_strdupa(fmt); 00596 } 00597 00598 time(&start); 00599 end=start; /* pre-initialize end to be same as start in case we never get into loop */ 00600 for (x=0;x<fmtcnt;x++) { 00601 others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700); 00602 ast_verbose( VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]); 00603 00604 if (!others[x]) { 00605 break; 00606 } 00607 } 00608 00609 if (path) 00610 ast_unlock_path(path); 00611 00612 if (maxsilence > 0) { 00613 sildet = ast_dsp_new(); /* Create the silence detector */ 00614 if (!sildet) { 00615 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00616 return -1; 00617 } 00618 ast_dsp_set_threshold(sildet, silencethreshold); 00619 rfmt = chan->readformat; 00620 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00621 if (res < 0) { 00622 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00623 ast_dsp_free(sildet); 00624 return -1; 00625 } 00626 } 00627 00628 /* Request a video update */ 00629 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 00630 00631 if (option_transmit_silence_during_record) 00632 silgen = ast_channel_start_silence_generator(chan); 00633 00634 if (x == fmtcnt) { 00635 /* Loop forever, writing the packets we read to the writer(s), until 00636 we read a # or get a hangup */ 00637 f = NULL; 00638 for(;;) { 00639 res = ast_waitfor(chan, 2000); 00640 if (!res) { 00641 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); 00642 /* Try one more time in case of masq */ 00643 res = ast_waitfor(chan, 2000); 00644 if (!res) { 00645 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); 00646 res = -1; 00647 } 00648 } 00649 00650 if (res < 0) { 00651 f = NULL; 00652 break; 00653 } 00654 f = ast_read(chan); 00655 if (!f) 00656 break; 00657 if (f->frametype == AST_FRAME_VOICE) { 00658 /* write each format */ 00659 for (x=0;x<fmtcnt;x++) { 00660 res = ast_writestream(others[x], f); 00661 } 00662 00663 /* Silence Detection */ 00664 if (maxsilence > 0) { 00665 dspsilence = 0; 00666 ast_dsp_silence(sildet, f, &dspsilence); 00667 if (dspsilence) 00668 totalsilence = dspsilence; 00669 else 00670 totalsilence = 0; 00671 00672 if (totalsilence > maxsilence) { 00673 /* Ended happily with silence */ 00674 if (option_verbose > 2) 00675 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); 00676 ast_frfree(f); 00677 gotsilence = 1; 00678 outmsg=2; 00679 break; 00680 } 00681 } 00682 /* Exit on any error */ 00683 if (res) { 00684 ast_log(LOG_WARNING, "Error writing frame\n"); 00685 ast_frfree(f); 00686 break; 00687 } 00688 } else if (f->frametype == AST_FRAME_VIDEO) { 00689 /* Write only once */ 00690 ast_writestream(others[0], f); 00691 } else if (f->frametype == AST_FRAME_DTMF) { 00692 if (f->subclass == '#') { 00693 if (option_verbose > 2) 00694 ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); 00695 res = '#'; 00696 outmsg = 2; 00697 ast_frfree(f); 00698 break; 00699 } 00700 if (f->subclass == '0') { 00701 /* Check for a '0' during message recording also, in case caller wants operator */ 00702 if (option_verbose > 2) 00703 ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass); 00704 res = '0'; 00705 outmsg = 0; 00706 ast_frfree(f); 00707 break; 00708 } 00709 } 00710 if (maxtime) { 00711 time(&end); 00712 if (maxtime < (end - start)) { 00713 if (option_verbose > 2) 00714 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); 00715 outmsg = 2; 00716 res = 't'; 00717 ast_frfree(f); 00718 break; 00719 } 00720 } 00721 ast_frfree(f); 00722 } 00723 if (end == start) time(&end); 00724 if (!f) { 00725 if (option_verbose > 2) 00726 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); 00727 res = -1; 00728 outmsg=1; 00729 } 00730 } else { 00731 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); 00732 } 00733 00734 if (silgen) 00735 ast_channel_stop_silence_generator(chan, silgen); 00736 00737 *duration = end - start; 00738 00739 for (x=0;x<fmtcnt;x++) { 00740 if (!others[x]) 00741 break; 00742 if (res > 0) { 00743 if (totalsilence) 00744 ast_stream_rewind(others[x], totalsilence-200); 00745 else 00746 ast_stream_rewind(others[x], 200); 00747 } 00748 ast_truncstream(others[x]); 00749 ast_closestream(others[x]); 00750 } 00751 if (rfmt) { 00752 if (ast_set_read_format(chan, rfmt)) { 00753 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00754 } 00755 } 00756 if (outmsg > 1) { 00757 /* Let them know recording is stopped */ 00758 if(!ast_streamfile(chan, "auth-thankyou", chan->language)) 00759 ast_waitstream(chan, ""); 00760 } 00761 if (sildet) 00762 ast_dsp_free(sildet); 00763 return res; 00764 }
|
|
|
Read a file into asterisk Definition at line 1488 of file app.c. References ast_log(), free, LOG_WARNING, and malloc. Referenced by readfile_exec(). 01489 { 01490 int fd; 01491 char *output=NULL; 01492 struct stat filesize; 01493 int count=0; 01494 int res; 01495 if(stat(filename,&filesize)== -1){ 01496 ast_log(LOG_WARNING,"Error can't stat %s\n", filename); 01497 return NULL; 01498 } 01499 count=filesize.st_size + 1; 01500 fd = open(filename, O_RDONLY); 01501 if (fd < 0) { 01502 ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno)); 01503 return NULL; 01504 } 01505 output=(char *)malloc(count); 01506 if (output) { 01507 res = read(fd, output, count - 1); 01508 if (res == count - 1) { 01509 output[res] = '\0'; 01510 } else { 01511 ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno)); 01512 free(output); 01513 output = NULL; 01514 } 01515 } else 01516 ast_log(LOG_WARNING, "Out of memory!\n"); 01517 close(fd); 01518 return output; 01519 }
|
|
Allow to record message and have a review option Definition at line 1186 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(), fmt, ast_channel::language, LOG_WARNING, and VERBOSE_PREFIX_3. Referenced by conf_run(). 01187 { 01188 int silencethreshold = 128; 01189 int maxsilence=0; 01190 int res = 0; 01191 int cmd = 0; 01192 int max_attempts = 3; 01193 int attempts = 0; 01194 int recorded = 0; 01195 int message_exists = 0; 01196 /* Note that urgent and private are for flagging messages as such in the future */ 01197 01198 /* barf if no pointer passed to store duration in */ 01199 if (duration == NULL) { 01200 ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n"); 01201 return -1; 01202 } 01203 01204 cmd = '3'; /* Want to start by recording */ 01205 01206 while ((cmd >= 0) && (cmd != 't')) { 01207 switch (cmd) { 01208 case '1': 01209 if (!message_exists) { 01210 /* In this case, 1 is to record a message */ 01211 cmd = '3'; 01212 break; 01213 } else { 01214 ast_streamfile(chan, "vm-msgsaved", chan->language); 01215 ast_waitstream(chan, ""); 01216 cmd = 't'; 01217 return res; 01218 } 01219 case '2': 01220 /* Review */ 01221 ast_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n"); 01222 ast_streamfile(chan, recordfile, chan->language); 01223 cmd = ast_waitstream(chan, AST_DIGIT_ANY); 01224 break; 01225 case '3': 01226 message_exists = 0; 01227 /* Record */ 01228 if (recorded == 1) 01229 ast_verbose(VERBOSE_PREFIX_3 "Re-recording\n"); 01230 else 01231 ast_verbose(VERBOSE_PREFIX_3 "Recording\n"); 01232 recorded = 1; 01233 cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path); 01234 if (cmd == -1) { 01235 /* User has hung up, no options to give */ 01236 return cmd; 01237 } 01238 if (cmd == '0') { 01239 break; 01240 } else if (cmd == '*') { 01241 break; 01242 } 01243 else { 01244 /* If all is well, a message exists */ 01245 message_exists = 1; 01246 cmd = 0; 01247 } 01248 break; 01249 case '4': 01250 case '5': 01251 case '6': 01252 case '7': 01253 case '8': 01254 case '9': 01255 case '*': 01256 case '#': 01257 cmd = ast_play_and_wait(chan, "vm-sorry"); 01258 break; 01259 default: 01260 if (message_exists) { 01261 cmd = ast_play_and_wait(chan, "vm-review"); 01262 } 01263 else { 01264 cmd = ast_play_and_wait(chan, "vm-torerecord"); 01265 if (!cmd) 01266 cmd = ast_waitfordigit(chan, 600); 01267 } 01268 01269 if (!cmd) 01270 cmd = ast_waitfordigit(chan, 6000); 01271 if (!cmd) { 01272 attempts++; 01273 } 01274 if (attempts > max_attempts) { 01275 cmd = 't'; 01276 } 01277 } 01278 } 01279 if (cmd == 't') 01280 cmd = 0; 01281 return cmd; 01282 }
|
|
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 1175 of file app.c. References ast_log(), LOG_DEBUG, and s. Referenced by ast_play_and_record(), close_mailbox(), copy_message(), count_messages(), last_message_index(), leave_voicemail(), resequence_mailbox(), and save_to_folder(). 01176 { 01177 char *s; 01178 s = alloca(strlen(path) + 10); 01179 if (!s) 01180 return -1; 01181 snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock"); 01182 ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path); 01183 return unlink(s); 01184 }
|
|
Definition at line 1290 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, ast_channel::pbx, RES_EXIT, RES_REPEAT, ast_pbx::rtimeout, and strsep(). Referenced by ast_ivr_menu_run_internal(). 01291 { 01292 int res; 01293 int (*ivr_func)(struct ast_channel *, void *); 01294 char *c; 01295 char *n; 01296 01297 switch(option->action) { 01298 case AST_ACTION_UPONE: 01299 return RES_UPONE; 01300 case AST_ACTION_EXIT: 01301 return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff); 01302 case AST_ACTION_REPEAT: 01303 return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff); 01304 case AST_ACTION_RESTART: 01305 return RES_RESTART ; 01306 case AST_ACTION_NOOP: 01307 return 0; 01308 case AST_ACTION_BACKGROUND: 01309 res = ast_streamfile(chan, (char *)option->adata, chan->language); 01310 if (!res) { 01311 res = ast_waitstream(chan, AST_DIGIT_ANY); 01312 } else { 01313 ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata); 01314 res = 0; 01315 } 01316 return res; 01317 case AST_ACTION_PLAYBACK: 01318 res = ast_streamfile(chan, (char *)option->adata, chan->language); 01319 if (!res) { 01320 res = ast_waitstream(chan, ""); 01321 } else { 01322 ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata); 01323 res = 0; 01324 } 01325 return res; 01326 case AST_ACTION_MENU: 01327 res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata); 01328 /* Do not pass entry errors back up, treaat ast though ti was an "UPONE" */ 01329 if (res == -2) 01330 res = 0; 01331 return res; 01332 case AST_ACTION_WAITOPTION: 01333 res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10)); 01334 if (!res) 01335 return 't'; 01336 return res; 01337 case AST_ACTION_CALLBACK: 01338 ivr_func = option->adata; 01339 res = ivr_func(chan, cbdata); 01340 return res; 01341 case AST_ACTION_TRANSFER: 01342 res = ast_parseable_goto(chan, option->adata); 01343 return 0; 01344 case AST_ACTION_PLAYLIST: 01345 case AST_ACTION_BACKLIST: 01346 res = 0; 01347 c = ast_strdupa(option->adata); 01348 if (c) { 01349 while((n = strsep(&c, ";"))) 01350 if ((res = ast_streamfile(chan, n, chan->language)) || (res = ast_waitstream(chan, (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : ""))) 01351 break; 01352 ast_stopstream(chan); 01353 } 01354 return res; 01355 default: 01356 ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action); 01357 return 0; 01358 }; 01359 return -1; 01360 }
|
|
Definition at line 374 of file app.c. References linear_state::allowoverride, ast_clear_flag, AST_FLAG_WRITE_INT, AST_FORMAT_SLINEAR, ast_log(), ast_set_flag, ast_set_write_format(), free, LOG_WARNING, ast_channel::name, linear_state::origwfmt, and ast_channel::writeformat. 00375 { 00376 struct linear_state *ls; 00377 /* In this case, params is already malloc'd */ 00378 if (params) { 00379 ls = params; 00380 if (ls->allowoverride) 00381 ast_set_flag(chan, AST_FLAG_WRITE_INT); 00382 else 00383 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 00384 ls->origwfmt = chan->writeformat; 00385 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 00386 ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name); 00387 free(ls); 00388 ls = params = NULL; 00389 } 00390 } 00391 return params; 00392 }
|
|
Definition at line 347 of file app.c. References 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. 00348 { 00349 struct ast_frame f; 00350 short buf[2048 + AST_FRIENDLY_OFFSET / 2]; 00351 struct linear_state *ls = data; 00352 int res; 00353 len = samples * 2; 00354 if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) { 00355 ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len); 00356 len = sizeof(buf) - AST_FRIENDLY_OFFSET; 00357 } 00358 memset(&f, 0, sizeof(f)); 00359 res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len); 00360 if (res > 0) { 00361 f.frametype = AST_FRAME_VOICE; 00362 f.subclass = AST_FORMAT_SLINEAR; 00363 f.data = buf + AST_FRIENDLY_OFFSET/2; 00364 f.datalen = res; 00365 f.samples = res / 2; 00366 f.offset = AST_FRIENDLY_OFFSET; 00367 ast_write(chan, &f); 00368 if (res == len) 00369 return 0; 00370 } 00371 return -1; 00372 }
|
|
Definition at line 336 of file app.c. References ast_log(), ast_set_write_format(), linear_state::autoclose, linear_state::fd, free, LOG_WARNING, ast_channel::name, and linear_state::origwfmt. 00337 { 00338 struct linear_state *ls = params; 00339 if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) { 00340 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt); 00341 } 00342 if (ls->autoclose) 00343 close(ls->fd); 00344 free(params); 00345 }
|
|
Definition at line 1362 of file app.c. References ast_ivr_option::option, and ast_ivr_menu::options. Referenced by ast_ivr_menu_run_internal(). 01363 { 01364 int x; 01365 for (x=0;menu->options[x].option;x++) 01366 if (!strcasecmp(menu->options[x].option, option)) 01367 return x; 01368 return -1; 01369 }
|
|
Definition at line 1371 of file app.c. References ast_ivr_option::option, and ast_ivr_menu::options. Referenced by read_newoption(). 01372 { 01373 int x; 01374 for (x=0;menu->options[x].option;x++) 01375 if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 01376 (menu->options[x].option[strlen(option)])) 01377 return x; 01378 return -1; 01379 }
|
|
Definition at line 1381 of file app.c. References ast_waitfordigit(), ast_pbx::dtimeout, option_matchmore(), and ast_channel::pbx. Referenced by ast_ivr_menu_run_internal(). 01382 { 01383 int res=0; 01384 int ms; 01385 while(option_matchmore(menu, exten)) { 01386 ms = chan->pbx ? chan->pbx->dtimeout : 5000; 01387 if (strlen(exten) >= maxexten - 1) 01388 break; 01389 res = ast_waitfordigit(chan, ms); 01390 if (res < 1) 01391 break; 01392 exten[strlen(exten) + 1] = '\0'; 01393 exten[strlen(exten)] = res; 01394 } 01395 return res > 0 ? 0 : res; 01396 }
|
|
Definition at line 233 of file app.c. Referenced by ast_app_has_voicemail(), ast_install_vm_functions(), and ast_uninstall_vm_functions(). |
|
Definition at line 234 of file app.c. Referenced by ast_app_messagecount(), ast_install_vm_functions(), and ast_uninstall_vm_functions(). |
|
|
|
|
|
Definition at line 394 of file app.c. Referenced by ast_linear_stream(). |