#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/indications.h"
Include dependency graph for app.c:

Go to the source code of this file.
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_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, and ast_pbx::rtimeout. Referenced by __login_exec(), auth_exec(), conf_exec(), dictate_exec(), find_conf(), read_exec(), testclient_exec(), testserver_exec(), and vm_exec(). 00110 {
00111 int res,to,fto;
00112 /* XXX Merge with full version? XXX */
00113 if (maxlen)
00114 s[0] = '\0';
00115 if (prompt) {
00116 res = ast_streamfile(c, prompt, c->language);
00117 if (res < 0)
00118 return res;
00119 }
00120 fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
00121 to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
00122
00123 if (timeout > 0)
00124 fto = to = timeout;
00125 if (timeout < 0)
00126 fto = to = 1000000000;
00127 res = ast_readstring(c, s, maxlen, to, fto, "#");
00128 return res;
00129 }
|
|
||||||||||||||||||||||||||||||||
|
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_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_set_read_format(), ast_streamfile(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_frame::frametype, ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::name, ast_channel::readformat, ast_frame::samples, ast_frame::subclass, and total. 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, 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, 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 dial_exec_full(), group_function_write(), and group_set_exec(). 01038 {
01039 int res=0;
01040 char group[80] = "";
01041 char category[80] = "";
01042
01043 if (!ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) {
01044 pbx_builtin_setvar_helper(chan, category, group);
01045 } else
01046 res = -1;
01047
01048 return res;
01049 }
|
|
||||||||||||||||||||||||
|
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(), 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 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(), 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(), and LOG_DEBUG. 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_FRAME_DTMF, ast_log(), ast_safe_sleep(), ast_waitfor(), ast_write(), and LOG_WARNING. Referenced by ast_bridge_call(), dial_exec_full(), misdn_send_digit(), senddtmf_exec(), testclient_exec(), and testserver_exec(). 00282 {
00283 char *ptr;
00284 int res = 0;
00285 struct ast_frame f;
00286 if (!between)
00287 between = 100;
00288
00289 if (peer)
00290 res = ast_autoservice_start(peer);
00291
00292 if (!res) {
00293 res = ast_waitfor(chan,100);
00294 if (res > -1) {
00295 for (ptr=digits; *ptr; ptr++) {
00296 if (*ptr == 'w') {
00297 res = ast_safe_sleep(chan, 500);
00298 if (res)
00299 break;
00300 continue;
00301 }
00302 memset(&f, 0, sizeof(f));
00303 f.frametype = AST_FRAME_DTMF;
00304 f.subclass = *ptr;
00305 f.src = "ast_dtmf_stream";
00306 if (strchr("0123456789*#abcdABCD",*ptr)==NULL) {
00307 ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
00308 } else {
00309 res = ast_write(chan, &f);
00310 if (res)
00311 break;
00312 /* pause between digits */
00313 res = ast_safe_sleep(chan,between);
00314 if (res)
00315 break;
00316 }
00317 }
00318 }
00319 if (peer) {
00320 /* Stop autoservice on the peer channel, but don't overwrite any error condition
00321 that has occurred previously while acting on the primary channel */
00322 if (ast_autoservice_stop(peer) && !res)
00323 res = -1;
00324 }
00325 }
00326 return res;
00327 }
|
|
||||||||||||
|
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_DEBUG, LOG_WARNING, maxretries, ast_ivr_option::option, option_exists(), ast_ivr_menu::options, read_newoption(), RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, and ast_ivr_menu::title. Referenced by ast_ivr_menu_run(), and ivr_dispatch(). 01416 {
01417 /* Execute an IVR menu structure */
01418 int res=0;
01419 int pos = 0;
01420 int retries = 0;
01421 char exten[AST_MAX_EXTENSION] = "s";
01422 if (option_exists(menu, "s") < 0) {
01423 strcpy(exten, "g");
01424 if (option_exists(menu, "g") < 0) {
01425 ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
01426 return -1;
01427 }
01428 }
01429 while(!res) {
01430 while(menu->options[pos].option) {
01431 if (!strcasecmp(menu->options[pos].option, exten)) {
01432 res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
01433 ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
01434 if (res < 0)
01435 break;
01436 else if (res & RES_UPONE)
01437 return 0;
01438 else if (res & RES_EXIT)
01439 return res;
01440 else if (res & RES_REPEAT) {
01441 int maxretries = res & 0xffff;
01442 if ((res & RES_RESTART) == RES_RESTART) {
01443 retries = 0;
01444 } else
01445 retries++;
01446 if (!maxretries)
01447 maxretries = 3;
01448 if ((maxretries > 0) && (retries >= maxretries)) {
01449 ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries);
01450 return -2;
01451 } else {
01452 if (option_exists(menu, "g") > -1)
01453 strcpy(exten, "g");
01454 else if (option_exists(menu, "s") > -1)
01455 strcpy(exten, "s");
01456 }
01457 pos=0;
01458 continue;
01459 } else if (res && strchr(AST_DIGIT_ANY, res)) {
01460 ast_log(LOG_DEBUG, "Got start of extension, %c\n", res);
01461 exten[1] = '\0';
01462 exten[0] = res;
01463 if ((res = read_newoption(chan, menu, exten, sizeof(exten))))
01464 break;
01465 if (option_exists(menu, exten) < 0) {
01466 if (option_exists(menu, "i")) {
01467 ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n");
01468 strcpy(exten, "i");
01469 pos = 0;
01470 continue;
01471 } else {
01472 ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n");
01473 res = -2;
01474 break;
01475 }
01476 } else {
01477 ast_log(LOG_DEBUG, "New existing extension: %s\n", exten);
01478 pos = 0;
01479 continue;
01480 }
01481 }
01482 }
01483 pos++;
01484 }
01485 ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res);
01486 pos = 0;
01487 if (!strcasecmp(exten, "s"))
01488 strcpy(exten, "g");
01489 else
01490 break;
01491 }
01492 return res;
01493 }
|
|
||||||||||||||||||||
|
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, 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_DEBUG, LOG_ERROR, LOG_WARNING, and s. Referenced by vm_lock_path(). 01143 {
01144 char *s;
01145 char *fs;
01146 int res;
01147 int fd;
01148 time_t start;
01149
01150 s = alloca(strlen(path) + 10);
01151 fs = alloca(strlen(path) + 20);
01152
01153 if (!fs || !s) {
01154 ast_log(LOG_WARNING, "Out of memory!\n");
01155 return AST_LOCK_FAILURE;
01156 }
01157
01158 snprintf(fs, strlen(path) + 19, "%s/.lock-%08x", path, rand());
01159 fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
01160 if (fd < 0) {
01161 ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
01162 return AST_LOCK_PATH_NOT_FOUND;
01163 }
01164 close(fd);
01165
01166 snprintf(s, strlen(path) + 9, "%s/.lock", path);
01167 time(&start);
01168 while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
01169 usleep(1);
01170
01171 unlink(fs);
01172
01173 if (res) {
01174 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
01175 return AST_LOCK_TIMEOUT;
01176 } else {
01177 ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
01178 return AST_LOCK_SUCCESS;
01179 }
01180 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
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_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), ast_filedelete(), ast_filerename(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), ast_play_and_wait(), ast_read(), ast_readfile(), ast_readframe(), ast_set_read_format(), ast_strdupa, ast_stream_rewind(), ast_streamfile(), ast_truncstream(), ast_verbose(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_frame::frametype, ast_channel::language, LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, option_verbose, ast_channel::readformat, strsep(), ast_frame::subclass, ast_dsp::totalsilence, and VERBOSE_PREFIX_3. Referenced by vm_forwardoptions(). 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_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_indicate(), ast_log(), ast_play_and_wait(), ast_read(), ast_set_read_format(), ast_strdupa, ast_stream_rewind(), ast_streamfile(), ast_truncstream(), ast_unlock_path(), ast_verbose(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_frame::frametype, LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, option_transmit_silence_during_record, option_verbose, ast_channel::readformat, strsep(), ast_frame::subclass, ast_dsp::totalsilence, and VERBOSE_PREFIX_3. Referenced by ast_play_and_record(), and play_record_review(). 00541 {
00542 int d;
00543 char *fmts;
00544 char comment[256];
00545 int x, fmtcnt=1, res=-1,outmsg=0;
00546 struct ast_frame *f;
00547 struct ast_filestream *others[MAX_OTHER_FORMATS];
00548 char *sfmt[MAX_OTHER_FORMATS];
00549 char *stringp=NULL;
00550 time_t start, end;
00551 struct ast_dsp *sildet=NULL; /* silence detector dsp */
00552 int totalsilence = 0;
00553 int dspsilence = 0;
00554 int rfmt=0;
00555 struct ast_silence_generator *silgen = NULL;
00556
00557 if (silencethreshold < 0)
00558 silencethreshold = global_silence_threshold;
00559
00560 if (maxsilence < 0)
00561 maxsilence = global_maxsilence;
00562
00563 /* barf if no pointer passed to store duration in */
00564 if (duration == NULL) {
00565 ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
00566 return -1;
00567 }
00568
00569 ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
00570 snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
00571
00572 if (playfile) {
00573 d = ast_play_and_wait(chan, playfile);
00574 if (d > -1)
00575 d = ast_streamfile(chan, "beep",chan->language);
00576 if (!d)
00577 d = ast_waitstream(chan,"");
00578 if (d < 0)
00579 return -1;
00580 }
00581
00582 fmts = ast_strdupa(fmt);
00583
00584 stringp=fmts;
00585 strsep(&stringp, "|");
00586 ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
00587 sfmt[0] = ast_strdupa(fmts);
00588
00589 while((fmt = strsep(&stringp, "|"))) {
00590 if (fmtcnt > MAX_OTHER_FORMATS - 1) {
00591 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n");
00592 break;
00593 }
00594 sfmt[fmtcnt++] = ast_strdupa(fmt);
00595 }
00596
00597 time(&start);
00598 end=start; /* pre-initialize end to be same as start in case we never get into loop */
00599 for (x=0;x<fmtcnt;x++) {
00600 others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
00601 ast_verbose( VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);
00602
00603 if (!others[x]) {
00604 break;
00605 }
00606 }
00607
00608 if (path)
00609 ast_unlock_path(path);
00610
00611 if (maxsilence > 0) {
00612 sildet = ast_dsp_new(); /* Create the silence detector */
00613 if (!sildet) {
00614 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00615 return -1;
00616 }
00617 ast_dsp_set_threshold(sildet, silencethreshold);
00618 rfmt = chan->readformat;
00619 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00620 if (res < 0) {
00621 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00622 ast_dsp_free(sildet);
00623 return -1;
00624 }
00625 }
00626
00627 /* Request a video update */
00628 ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00629
00630 if (option_transmit_silence_during_record)
00631 silgen = ast_channel_start_silence_generator(chan);
00632
00633 if (x == fmtcnt) {
00634 /* Loop forever, writing the packets we read to the writer(s), until
00635 we read a # or get a hangup */
00636 f = NULL;
00637 for(;;) {
00638 res = ast_waitfor(chan, 2000);
00639 if (!res) {
00640 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
00641 /* Try one more time in case of masq */
00642 res = ast_waitfor(chan, 2000);
00643 if (!res) {
00644 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
00645 res = -1;
00646 }
00647 }
00648
00649 if (res < 0) {
00650 f = NULL;
00651 break;
00652 }
00653 f = ast_read(chan);
00654 if (!f)
00655 break;
00656 if (f->frametype == AST_FRAME_VOICE) {
00657 /* write each format */
00658 for (x=0;x<fmtcnt;x++) {
00659 res = ast_writestream(others[x], f);
00660 }
00661
00662 /* Silence Detection */
00663 if (maxsilence > 0) {
00664 dspsilence = 0;
00665 ast_dsp_silence(sildet, f, &dspsilence);
00666 if (dspsilence)
00667 totalsilence = dspsilence;
00668 else
00669 totalsilence = 0;
00670
00671 if (totalsilence > maxsilence) {
00672 /* Ended happily with silence */
00673 if (option_verbose > 2)
00674 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
00675 ast_frfree(f);
00676 res = 'S';
00677 outmsg=2;
00678 break;
00679 }
00680 }
00681 /* Exit on any error */
00682 if (res) {
00683 ast_log(LOG_WARNING, "Error writing frame\n");
00684 ast_frfree(f);
00685 break;
00686 }
00687 } else if (f->frametype == AST_FRAME_VIDEO) {
00688 /* Write only once */
00689 ast_writestream(others[0], f);
00690 } else if (f->frametype == AST_FRAME_DTMF) {
00691 if (strchr(acceptdtmf, f->subclass)) {
00692 if (option_verbose > 2)
00693 ast_verbose(VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
00694 res = f->subclass;
00695 outmsg = 2;
00696 ast_frfree(f);
00697 break;
00698 }
00699 if (strchr(canceldtmf, f->subclass)) {
00700 if (option_verbose > 2)
00701 ast_verbose(VERBOSE_PREFIX_3 "User cancelled message by pressing %c\n", f->subclass);
00702 res = f->subclass;
00703 outmsg = 0;
00704 ast_frfree(f);
00705 break;
00706 }
00707 }
00708 if (maxtime) {
00709 time(&end);
00710 if (maxtime < (end - start)) {
00711 if (option_verbose > 2)
00712 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
00713 outmsg = 2;
00714 res = 't';
00715 ast_frfree(f);
00716 break;
00717 }
00718 }
00719 ast_frfree(f);
00720 }
00721 if (end == start) time(&end);
00722 if (!f) {
00723 if (option_verbose > 2)
00724 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
00725 res = -1;
00726 outmsg=1;
00727 }
00728 } else {
00729 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
00730 }
00731
00732 if (silgen)
00733 ast_channel_stop_silence_generator(chan, silgen);
00734
00735 *duration = end - start;
00736
00737 for (x=0;x<fmtcnt;x++) {
00738 if (!others[x])
00739 break;
00740 if (res > 0) {
00741 if (totalsilence)
00742 ast_stream_rewind(others[x], totalsilence-200);
00743 else
00744 ast_stream_rewind(others[x], 200);
00745 }
00746 ast_truncstream(others[x]);
00747 ast_closestream(others[x]);
00748 }
00749 if (rfmt) {
00750 if (ast_set_read_format(chan, rfmt)) {
00751 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00752 }
00753 }
00754 if (outmsg > 1) {
00755 /* Let them know recording is stopped */
00756 if(!ast_streamfile(chan, "auth-thankyou", chan->language))
00757 ast_waitstream(chan, "");
00758 }
00759 if (sildet)
00760 ast_dsp_free(sildet);
00761 return res;
00762 }
|
|
||||||||||||
|
|
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, 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_DEBUG, LOG_ERROR, LOG_WARNING, and s. Referenced by ast_play_and_record_full(), close_mailbox(), copy_message(), count_messages(), last_message_index(), leave_voicemail(), resequence_mailbox(), and save_to_folder(). 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, and linear_state::origwfmt. 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, 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. 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(), and option_matchmore(). 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(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.4.2