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