#include "asterisk.h"
#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/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/indications.h"
#include "asterisk/linkedlists.h"
Go to the source code of this file.
Data Structures | |
struct | groups |
struct | linear_state |
Defines | |
#define | AST_MAX_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 | |
static int | __ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf) |
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_group_discard (struct ast_channel *chan) |
int | ast_app_group_get_count (const char *group, const char *category) |
ast_group_info * | ast_app_group_list_head (void) |
int | ast_app_group_list_lock (void) |
int | ast_app_group_list_unlock (void) |
int | ast_app_group_match_get_count (const char *groupmatch, const char *category) |
int | ast_app_group_set_channel (struct ast_channel *chan, const char *data) |
int | ast_app_group_split_group (const char *data, char *group, int group_max, char *category, int category_max) |
int | ast_app_group_update (struct ast_channel *old, struct ast_channel *new) |
int | ast_app_has_voicemail (const char *mailbox, const char *folder) |
int | ast_app_inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs) |
int | ast_app_messagecount (const char *context, const char *mailbox, const char *folder) |
void | ast_app_options2str (const struct ast_app_option *options, struct ast_flags *flags, char *buf, size_t len) |
Given a list of options array, return an option string based on passed flags. | |
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, const char *digits, int between) |
Send DTMF to a channel. | |
void | ast_install_vm_functions (int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs), int(*messagecount_func)(const char *context, const char *mailbox, const char *folder)) |
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_inboxcount_func (const char *mailbox, int *newmsgs, int *oldmsgs) = NULL |
static int(*) | ast_messagecount_func (const char *context, const char *mailbox, const char *folder) = NULL |
static char | default_acceptdtmf [] = "#" |
static char | default_canceldtmf [] = "" |
static int | global_maxsilence = 0 |
static int | global_silence_threshold = 128 |
static struct ast_generator | linearstream |
Definition in file app.c.
#define AST_MAX_FORMATS 10 |
Definition at line 54 of file app.c.
Referenced by __ast_play_and_record(), and ast_format_str_reduce().
#define RES_EXIT (1 << 17) |
Definition at line 1176 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
#define RES_REPEAT (1 << 18) |
Definition at line 1177 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
#define RES_RESTART ((1 << 19) | RES_REPEAT) |
Definition at line 1178 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
#define RES_UPONE (1 << 16) |
Definition at line 1175 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
static int __ast_play_and_record | ( | struct ast_channel * | chan, | |
const char * | playfile, | |||
const char * | recordfile, | |||
int | maxtime, | |||
const char * | fmt, | |||
int * | duration, | |||
int | beep, | |||
int | silencethreshold, | |||
int | maxsilence, | |||
const char * | path, | |||
int | prepend, | |||
const char * | acceptdtmf, | |||
const char * | canceldtmf | |||
) | [static] |
Optionally play a sound file or a beep, then record audio and video from the channel.
chan | Channel to playback to/record from. | |
playfile | Filename of sound to play before recording begins. | |
recordfile | Filename to record to. | |
maxtime | Maximum length of recording (in milliseconds). | |
fmt | Format(s) to record message in. Multiple formats may be specified by separating them with a '|'. | |
duration | Where to store actual length of the recorded message (in milliseconds). | |
beep | Whether to play a beep before starting to record. | |
silencethreshold | ||
maxsilence | Length of silence that will end a recording (in milliseconds). | |
path | Optional filesystem path to unlock. | |
prepend | If true, prepend the recorded audio to an existing file. | |
acceptdtmf | DTMF digits that will end the recording. | |
canceldtmf | DTMF digits that will cancel the recording. |
Same logic as above.
Definition at line 504 of file app.c.
References ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_copy_string(), 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_indicate(), ast_log(), AST_MAX_FORMATS, ast_opt_transmit_silence, ast_play_and_wait(), ast_read(), ast_readfile(), ast_readframe(), ast_set_read_format(), ast_strdupa, ast_stream_and_wait(), ast_stream_rewind(), ast_tellstream(), ast_truncstream(), ast_unlock_path(), ast_verbose(), ast_waitfor(), ast_writefile(), ast_writestream(), f, ast_channel::language, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_debug, option_verbose, ast_channel::readformat, ast_dsp::totalsilence, VERBOSE_PREFIX_3, and VERBOSE_PREFIX_4.
Referenced by ast_play_and_prepend(), ast_play_and_record(), and ast_play_and_record_full().
00505 { 00506 int d = 0; 00507 char *fmts; 00508 char comment[256]; 00509 int x, fmtcnt = 1, res = -1, outmsg = 0; 00510 struct ast_filestream *others[AST_MAX_FORMATS]; 00511 char *sfmt[AST_MAX_FORMATS]; 00512 char *stringp = NULL; 00513 time_t start, end; 00514 struct ast_dsp *sildet = NULL; /* silence detector dsp */ 00515 int totalsilence = 0; 00516 int rfmt = 0; 00517 struct ast_silence_generator *silgen = NULL; 00518 char prependfile[80]; 00519 00520 if (silencethreshold < 0) 00521 silencethreshold = global_silence_threshold; 00522 00523 if (maxsilence < 0) 00524 maxsilence = global_maxsilence; 00525 00526 /* barf if no pointer passed to store duration in */ 00527 if (duration == NULL) { 00528 ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n"); 00529 return -1; 00530 } 00531 00532 if (option_debug) 00533 ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); 00534 snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); 00535 00536 if (playfile || beep) { 00537 if (!beep) 00538 d = ast_play_and_wait(chan, playfile); 00539 if (d > -1) 00540 d = ast_stream_and_wait(chan, "beep", chan->language, ""); 00541 if (d < 0) 00542 return -1; 00543 } 00544 00545 if (prepend) { 00546 ast_copy_string(prependfile, recordfile, sizeof(prependfile)); 00547 strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); 00548 } 00549 00550 fmts = ast_strdupa(fmt); 00551 00552 stringp = fmts; 00553 strsep(&stringp, "|"); 00554 if (option_debug) 00555 ast_log(LOG_DEBUG, "Recording Formats: sfmts=%s\n", fmts); 00556 sfmt[0] = ast_strdupa(fmts); 00557 00558 while ((fmt = strsep(&stringp, "|"))) { 00559 if (fmtcnt > AST_MAX_FORMATS - 1) { 00560 ast_log(LOG_WARNING, "Please increase AST_MAX_FORMATS in file.h\n"); 00561 break; 00562 } 00563 sfmt[fmtcnt++] = ast_strdupa(fmt); 00564 } 00565 00566 end = start = time(NULL); /* pre-initialize end to be same as start in case we never get into loop */ 00567 for (x = 0; x < fmtcnt; x++) { 00568 others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, O_TRUNC, 0, 0777); 00569 if (option_verbose > 2) 00570 ast_verbose(VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]); 00571 00572 if (!others[x]) 00573 break; 00574 } 00575 00576 if (path) 00577 ast_unlock_path(path); 00578 00579 if (maxsilence > 0) { 00580 sildet = ast_dsp_new(); /* Create the silence detector */ 00581 if (!sildet) { 00582 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00583 return -1; 00584 } 00585 ast_dsp_set_threshold(sildet, silencethreshold); 00586 rfmt = chan->readformat; 00587 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00588 if (res < 0) { 00589 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00590 ast_dsp_free(sildet); 00591 return -1; 00592 } 00593 } 00594 00595 if (!prepend) { 00596 /* Request a video update */ 00597 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 00598 00599 if (ast_opt_transmit_silence) 00600 silgen = ast_channel_start_silence_generator(chan); 00601 } 00602 00603 if (x == fmtcnt) { 00604 /* Loop forever, writing the packets we read to the writer(s), until 00605 we read a digit or get a hangup */ 00606 struct ast_frame *f; 00607 for (;;) { 00608 res = ast_waitfor(chan, 2000); 00609 if (!res) { 00610 if (option_debug) 00611 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); 00612 /* Try one more time in case of masq */ 00613 res = ast_waitfor(chan, 2000); 00614 if (!res) { 00615 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); 00616 res = -1; 00617 } 00618 } 00619 00620 if (res < 0) { 00621 f = NULL; 00622 break; 00623 } 00624 f = ast_read(chan); 00625 if (!f) 00626 break; 00627 if (f->frametype == AST_FRAME_VOICE) { 00628 /* write each format */ 00629 for (x = 0; x < fmtcnt; x++) { 00630 if (prepend && !others[x]) 00631 break; 00632 res = ast_writestream(others[x], f); 00633 } 00634 00635 /* Silence Detection */ 00636 if (maxsilence > 0) { 00637 int dspsilence = 0; 00638 ast_dsp_silence(sildet, f, &dspsilence); 00639 if (dspsilence) 00640 totalsilence = dspsilence; 00641 else 00642 totalsilence = 0; 00643 00644 if (totalsilence > maxsilence) { 00645 /* Ended happily with silence */ 00646 if (option_verbose > 2) 00647 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); 00648 res = 'S'; 00649 outmsg = 2; 00650 break; 00651 } 00652 } 00653 /* Exit on any error */ 00654 if (res) { 00655 ast_log(LOG_WARNING, "Error writing frame\n"); 00656 break; 00657 } 00658 } else if (f->frametype == AST_FRAME_VIDEO) { 00659 /* Write only once */ 00660 ast_writestream(others[0], f); 00661 } else if (f->frametype == AST_FRAME_DTMF) { 00662 if (prepend) { 00663 /* stop recording with any digit */ 00664 if (option_verbose > 2) 00665 ast_verbose(VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); 00666 res = 't'; 00667 outmsg = 2; 00668 break; 00669 } 00670 if (strchr(acceptdtmf, f->subclass)) { 00671 if (option_verbose > 2) 00672 ast_verbose(VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); 00673 res = f->subclass; 00674 outmsg = 2; 00675 break; 00676 } 00677 if (strchr(canceldtmf, f->subclass)) { 00678 if (option_verbose > 2) 00679 ast_verbose(VERBOSE_PREFIX_3 "User cancelled message by pressing %c\n", f->subclass); 00680 res = f->subclass; 00681 outmsg = 0; 00682 break; 00683 } 00684 } 00685 if (maxtime) { 00686 end = time(NULL); 00687 if (maxtime < (end - start)) { 00688 if (option_verbose > 2) 00689 ast_verbose(VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); 00690 res = 't'; 00691 outmsg = 2; 00692 break; 00693 } 00694 } 00695 ast_frfree(f); 00696 } 00697 if (!f) { 00698 if (option_verbose > 2) 00699 ast_verbose(VERBOSE_PREFIX_3 "User hung up\n"); 00700 res = -1; 00701 outmsg = 1; 00702 } else { 00703 ast_frfree(f); 00704 } 00705 } else { 00706 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); 00707 } 00708 00709 if (!prepend) { 00710 if (silgen) 00711 ast_channel_stop_silence_generator(chan, silgen); 00712 } 00713 00714 /*!\note 00715 * Instead of asking how much time passed (end - start), calculate the number 00716 * of seconds of audio which actually went into the file. This fixes a 00717 * problem where audio is stopped up on the network and never gets to us. 00718 * 00719 * Note that we still want to use the number of seconds passed for the max 00720 * message, otherwise we could get a situation where this stream is never 00721 * closed (which would create a resource leak). 00722 */ 00723 *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0; 00724 00725 if (!prepend) { 00726 for (x = 0; x < fmtcnt; x++) { 00727 if (!others[x]) 00728 break; 00729 /*!\note 00730 * If we ended with silence, trim all but the first 200ms of silence 00731 * off the recording. However, if we ended with '#', we don't want 00732 * to trim ANY part of the recording. 00733 */ 00734 if (res > 0 && totalsilence) { 00735 ast_stream_rewind(others[x], totalsilence - 200); 00736 /* Reduce duration by a corresponding amount */ 00737 if (x == 0 && *duration) { 00738 *duration -= (totalsilence - 200) / 1000; 00739 if (*duration < 0) { 00740 *duration = 0; 00741 } 00742 } 00743 } 00744 ast_truncstream(others[x]); 00745 ast_closestream(others[x]); 00746 } 00747 } 00748 00749 if (prepend && outmsg) { 00750 struct ast_filestream *realfiles[AST_MAX_FORMATS]; 00751 struct ast_frame *fr; 00752 00753 for (x = 0; x < fmtcnt; x++) { 00754 snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); 00755 realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); 00756 if (!others[x] || !realfiles[x]) 00757 break; 00758 /*!\note Same logic as above. */ 00759 if (totalsilence) 00760 ast_stream_rewind(others[x], totalsilence - 200); 00761 ast_truncstream(others[x]); 00762 /* add the original file too */ 00763 while ((fr = ast_readframe(realfiles[x]))) { 00764 ast_writestream(others[x], fr); 00765 ast_frfree(fr); 00766 } 00767 ast_closestream(others[x]); 00768 ast_closestream(realfiles[x]); 00769 ast_filerename(prependfile, recordfile, sfmt[x]); 00770 if (option_verbose > 3) 00771 ast_verbose(VERBOSE_PREFIX_4 "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile); 00772 ast_filedelete(prependfile, sfmt[x]); 00773 } 00774 } 00775 if (rfmt && ast_set_read_format(chan, rfmt)) { 00776 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00777 } 00778 if (outmsg == 2) { 00779 ast_stream_and_wait(chan, "auth-thankyou", chan->language, ""); 00780 } 00781 if (sildet) 00782 ast_dsp_free(sildet); 00783 return res; 00784 }
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.
Definition at line 65 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().
00066 { 00067 struct tone_zone_sound *ts; 00068 int res=0, x=0; 00069 00070 if (maxlen > size) 00071 maxlen = size; 00072 00073 if (!timeout && chan->pbx) 00074 timeout = chan->pbx->dtimeout; 00075 else if (!timeout) 00076 timeout = 5; 00077 00078 ts = ast_get_indication_tone(chan->zone,"dial"); 00079 if (ts && ts->data[0]) 00080 res = ast_playtones_start(chan, 0, ts->data, 0); 00081 else 00082 ast_log(LOG_NOTICE,"Huh....? no dial for indications?\n"); 00083 00084 for (x = strlen(collect); x < maxlen; ) { 00085 res = ast_waitfordigit(chan, timeout); 00086 if (!ast_ignore_pattern(context, collect)) 00087 ast_playtones_stop(chan); 00088 if (res < 1) 00089 break; 00090 if (res == '#') 00091 break; 00092 collect[x++] = res; 00093 if (!ast_matchmore_extension(chan, context, collect, 1, chan->cid.cid_num)) 00094 break; 00095 } 00096 if (res >= 0) 00097 res = ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num) ? 1 : 0; 00098 return res; 00099 }
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.
c | The channel to read from | |
prompt | The file to stream to the channel | |
s | The string to read in to. Must be at least the size of your length | |
maxlen | How many digits to read (maximum) | |
timeout | set timeout to 0 for "standard" timeouts. Set timeout to -1 for "ludicrous time" (essentially never times out) |
Definition at line 107 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(), exec(), find_conf(), read_exec(), testclient_exec(), testserver_exec(), and vm_exec().
00108 { 00109 int res,to,fto; 00110 /* XXX Merge with full version? XXX */ 00111 if (maxlen) 00112 s[0] = '\0'; 00113 if (prompt) { 00114 res = ast_streamfile(c, prompt, c->language); 00115 if (res < 0) 00116 return res; 00117 } 00118 fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000; 00119 to = c->pbx ? c->pbx->dtimeout * 1000 : 2000; 00120 00121 if (timeout > 0) 00122 fto = to = timeout; 00123 if (timeout < 0) 00124 fto = to = 1000000000; 00125 res = ast_readstring(c, s, maxlen, to, fto, "#"); 00126 return res; 00127 }
int ast_app_getdata_full | ( | struct ast_channel * | c, | |
char * | prompt, | |||
char * | s, | |||
int | maxlen, | |||
int | timeout, | |||
int | audiofd, | |||
int | ctrlfd | |||
) |
Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions.
Definition at line 130 of file app.c.
References ast_readstring_full(), ast_streamfile(), and ast_channel::language.
Referenced by handle_getdata().
00131 { 00132 int res, to, fto; 00133 if (prompt) { 00134 res = ast_streamfile(c, prompt, c->language); 00135 if (res < 0) 00136 return res; 00137 } 00138 fto = 6000; 00139 to = 2000; 00140 if (timeout > 0) 00141 fto = to = timeout; 00142 if (timeout < 0) 00143 fto = to = 1000000000; 00144 res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd); 00145 return res; 00146 }
int ast_app_group_discard | ( | struct ast_channel * | chan | ) |
Discard all group counting for a channel
Definition at line 940 of file app.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_group_info::chan, and free.
Referenced by ast_channel_free().
00941 { 00942 struct ast_group_info *gi = NULL; 00943 00944 AST_LIST_LOCK(&groups); 00945 AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) { 00946 if (gi->chan == chan) { 00947 AST_LIST_REMOVE_CURRENT(&groups, list); 00948 free(gi); 00949 } 00950 } 00951 AST_LIST_TRAVERSE_SAFE_END 00952 AST_LIST_UNLOCK(&groups); 00953 00954 return 0; 00955 }
int ast_app_group_get_count | ( | const char * | group, | |
const char * | category | |||
) |
Get the current channel count of the specified group and category.
Definition at line 878 of file app.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, and ast_group_info::group.
Referenced by group_count_function_read().
00879 { 00880 struct ast_group_info *gi = NULL; 00881 int count = 0; 00882 00883 if (ast_strlen_zero(group)) 00884 return 0; 00885 00886 AST_LIST_LOCK(&groups); 00887 AST_LIST_TRAVERSE(&groups, gi, list) { 00888 if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) 00889 count++; 00890 } 00891 AST_LIST_UNLOCK(&groups); 00892 00893 return count; 00894 }
struct ast_group_info* ast_app_group_list_head | ( | void | ) |
Get the head of the group count list
Definition at line 962 of file app.c.
References AST_LIST_FIRST.
Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().
00963 { 00964 return AST_LIST_FIRST(&groups); 00965 }
int ast_app_group_list_lock | ( | void | ) |
Lock the group count list
Definition at line 957 of file app.c.
References AST_LIST_LOCK.
Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().
00958 { 00959 return AST_LIST_LOCK(&groups); 00960 }
int ast_app_group_list_unlock | ( | void | ) |
Unlock the group count list
Definition at line 967 of file app.c.
References AST_LIST_UNLOCK.
Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().
00968 { 00969 return AST_LIST_UNLOCK(&groups); 00970 }
int ast_app_group_match_get_count | ( | const char * | groupmatch, | |
const char * | category | |||
) |
Get the current channel count of all groups that match the specified pattern and category.
Definition at line 896 of file app.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, and ast_group_info::group.
Referenced by group_match_count_function_read().
00897 { 00898 struct ast_group_info *gi = NULL; 00899 regex_t regexbuf; 00900 int count = 0; 00901 00902 if (ast_strlen_zero(groupmatch)) 00903 return 0; 00904 00905 /* if regex compilation fails, return zero matches */ 00906 if (regcomp(®exbuf, groupmatch, REG_EXTENDED | REG_NOSUB)) 00907 return 0; 00908 00909 AST_LIST_LOCK(&groups); 00910 AST_LIST_TRAVERSE(&groups, gi, list) { 00911 if (!regexec(®exbuf, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) 00912 count++; 00913 } 00914 AST_LIST_UNLOCK(&groups); 00915 00916 regfree(®exbuf); 00917 00918 return count; 00919 }
int ast_app_group_set_channel | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Set the group for a channel, splitting the provided data into group and category, if specified.
Definition at line 833 of file app.c.
References ast_app_group_split_group(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_strlen_zero(), calloc, ast_group_info::category, ast_group_info::chan, free, group, ast_group_info::group, and len().
Referenced by group_function_write().
00834 { 00835 int res = 0; 00836 char group[80] = "", category[80] = ""; 00837 struct ast_group_info *gi = NULL; 00838 size_t len = 0; 00839 00840 if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) 00841 return -1; 00842 00843 /* Calculate memory we will need if this is new */ 00844 len = sizeof(*gi) + strlen(group) + 1; 00845 if (!ast_strlen_zero(category)) 00846 len += strlen(category) + 1; 00847 00848 AST_LIST_LOCK(&groups); 00849 AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) { 00850 if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) { 00851 AST_LIST_REMOVE_CURRENT(&groups, list); 00852 free(gi); 00853 break; 00854 } 00855 } 00856 AST_LIST_TRAVERSE_SAFE_END 00857 00858 if (ast_strlen_zero(group)) { 00859 /* Enable unsetting the group */ 00860 } else if ((gi = calloc(1, len))) { 00861 gi->chan = chan; 00862 gi->group = (char *) gi + sizeof(*gi); 00863 strcpy(gi->group, group); 00864 if (!ast_strlen_zero(category)) { 00865 gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1; 00866 strcpy(gi->category, category); 00867 } 00868 AST_LIST_INSERT_TAIL(&groups, gi, list); 00869 } else { 00870 res = -1; 00871 } 00872 00873 AST_LIST_UNLOCK(&groups); 00874 00875 return res; 00876 }
int ast_app_group_split_group | ( | const char * | data, | |
char * | group, | |||
int | group_max, | |||
char * | category, | |||
int | category_max | |||
) |
Split a group string into group and category, returning a default category if none is provided.
Definition at line 806 of file app.c.
References ast_copy_string(), and ast_strlen_zero().
Referenced by ast_app_group_set_channel(), group_count_function_read(), and group_match_count_function_read().
00807 { 00808 int res=0; 00809 char tmp[256]; 00810 char *grp=NULL, *cat=NULL; 00811 00812 if (!ast_strlen_zero(data)) { 00813 ast_copy_string(tmp, data, sizeof(tmp)); 00814 grp = tmp; 00815 cat = strchr(tmp, '@'); 00816 if (cat) { 00817 *cat = '\0'; 00818 cat++; 00819 } 00820 } 00821 00822 if (!ast_strlen_zero(grp)) 00823 ast_copy_string(group, grp, group_max); 00824 else 00825 *group = '\0'; 00826 00827 if (!ast_strlen_zero(cat)) 00828 ast_copy_string(category, cat, category_max); 00829 00830 return res; 00831 }
int ast_app_group_update | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) |
Update all group counting for a channel to a new one
Definition at line 921 of file app.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_group_info::chan, and free.
Referenced by ast_do_masquerade(), and check_bridge().
00922 { 00923 struct ast_group_info *gi = NULL; 00924 00925 AST_LIST_LOCK(&groups); 00926 AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) { 00927 if (gi->chan == old) { 00928 gi->chan = new; 00929 } else if (gi->chan == new) { 00930 AST_LIST_REMOVE_CURRENT(&groups, list); 00931 free(gi); 00932 } 00933 } 00934 AST_LIST_TRAVERSE_SAFE_END 00935 AST_LIST_UNLOCK(&groups); 00936 00937 return 0; 00938 }
int ast_app_has_voicemail | ( | const char * | mailbox, | |
const char * | folder | |||
) |
Determine if a given mailbox has any voicemail
Definition at line 168 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(), poll_mailbox(), and run_externnotify().
00169 { 00170 static int warned = 0; 00171 if (ast_has_voicemail_func) 00172 return ast_has_voicemail_func(mailbox, folder); 00173 00174 if ((option_verbose > 2) && !warned) { 00175 ast_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX"); 00176 warned++; 00177 } 00178 return 0; 00179 }
int ast_app_inboxcount | ( | const char * | mailbox, | |
int * | newmsgs, | |||
int * | oldmsgs | |||
) |
Determine number of new/old messages in a mailbox
Definition at line 182 of file app.c.
References ast_inboxcount_func, ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.
Referenced by action_mailboxcount(), notify_new_message(), sip_send_mwi_to_peer(), and update_registry().
00183 { 00184 static int warned = 0; 00185 if (newmsgs) 00186 *newmsgs = 0; 00187 if (oldmsgs) 00188 *oldmsgs = 0; 00189 if (ast_inboxcount_func) 00190 return ast_inboxcount_func(mailbox, newmsgs, oldmsgs); 00191 00192 if (!warned && (option_verbose > 2)) { 00193 warned++; 00194 ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox); 00195 } 00196 00197 return 0; 00198 }
int ast_app_messagecount | ( | const char * | context, | |
const char * | mailbox, | |||
const char * | folder | |||
) |
Determine number of messages in a given mailbox and folder
Definition at line 200 of file app.c.
References ast_messagecount_func, ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.
Referenced by acf_vmcount_exec(), and hasvoicemail_exec().
00201 { 00202 static int warned = 0; 00203 if (ast_messagecount_func) 00204 return ast_messagecount_func(context, mailbox, folder); 00205 00206 if (!warned && (option_verbose > 2)) { 00207 warned++; 00208 ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s@%s/%s but voicemail not loaded.\n", mailbox, context, folder); 00209 } 00210 00211 return 0; 00212 }
void ast_app_options2str | ( | const struct ast_app_option * | options, | |
struct ast_flags * | flags, | |||
char * | buf, | |||
size_t | len | |||
) |
Given a list of options array, return an option string based on passed flags.
options | The array of possible options declared with AST_APP_OPTIONS | |
flags | The flags of the options that you wish to populate the buffer with | |
buf | The buffer to fill with the string of options | |
len | The maximum length of buf |
Definition at line 1411 of file app.c.
References ast_test_flag.
01412 { 01413 unsigned int i, found = 0; 01414 01415 for (i = 32; i < 128 && found < len;i++) { 01416 if (ast_test_flag(flags, options[i].flag)) { 01417 buf[found++] = i; 01418 } 01419 } 01420 buf[found] = '\0'; 01421 }
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.
options | The array of possible options declared with AST_APP_OPTIONS | |
flags | The flag structure to have option flags set | |
args | The array of argument pointers to hold arguments found | |
optstr | The string containing the options to be parsed |
Definition at line 1423 of file app.c.
References ast_app_option::arg_index, ast_clear_flag, ast_copy_string(), AST_FLAGS_ALL, ast_log(), ast_set_flag, LOG_WARNING, quote(), and s.
Referenced by app_exec(), auth_exec(), cdr_read(), cdr_write(), chanspy_exec(), conf_exec(), extenspy_exec(), mixmonitor_exec(), page_exec(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_waitexten(), read_exec(), smdi_msg_retrieve_read(), vm_exec(), and vm_execmain().
01424 { 01425 char *s; 01426 int curarg; 01427 unsigned int argloc; 01428 char *arg; 01429 int res = 0; 01430 01431 ast_clear_flag(flags, AST_FLAGS_ALL); 01432 01433 if (!optstr) 01434 return 0; 01435 01436 s = optstr; 01437 while (*s) { 01438 curarg = *s++ & 0x7f; /* the array (in app.h) has 128 entries */ 01439 argloc = options[curarg].arg_index; 01440 if (*s == '(') { 01441 int paren = 1, quote = 0; 01442 int parsequotes = (s[1] == '"') ? 1 : 0; 01443 01444 /* Has argument */ 01445 arg = ++s; 01446 for (; *s; s++) { 01447 if (*s == '(' && !quote) { 01448 paren++; 01449 } else if (*s == ')' && !quote) { 01450 /* Count parentheses, unless they're within quotes (or backslashed, below) */ 01451 paren--; 01452 } else if (*s == '"' && parsequotes) { 01453 /* Leave embedded quotes alone, unless they are the first character */ 01454 quote = quote ? 0 : 1; 01455 ast_copy_string(s, s + 1, INT_MAX); 01456 s--; 01457 } else if (*s == '\\') { 01458 if (!quote) { 01459 /* If a backslash is found outside of quotes, remove it */ 01460 ast_copy_string(s, s + 1, INT_MAX); 01461 } else if (quote && s[1] == '"') { 01462 /* Backslash for a quote character within quotes, remove the backslash */ 01463 ast_copy_string(s, s + 1, INT_MAX); 01464 } else { 01465 /* Backslash within quotes, keep both characters */ 01466 s++; 01467 } 01468 } 01469 01470 if (paren == 0) { 01471 break; 01472 } 01473 } 01474 /* This will find the closing paren we found above, or none, if the string ended before we found one. */ 01475 if ((s = strchr(s, ')'))) { 01476 if (argloc) 01477 args[argloc - 1] = arg; 01478 *s++ = '\0'; 01479 } else { 01480 ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg); 01481 res = -1; 01482 break; 01483 } 01484 } else if (argloc) { 01485 args[argloc - 1] = ""; 01486 } 01487 ast_set_flag(flags, options[curarg].flag); 01488 } 01489 01490 return res; 01491 }
unsigned int ast_app_separate_args | ( | char * | buf, | |
char | delim, | |||
char ** | array, | |||
int | arraylen | |||
) |
Separate a string into arguments in an array.
buf | The string to be parsed (this must be a writable copy, as it will be modified) | |
delim | The character to be used to delimit arguments | |
array | An array of 'char *' to be filled in with pointers to the found arguments | |
arraylen | The number of elements in the array (i.e. the number of arguments you will accept) |
The array will be completely zeroed by this function before it populates any entries.
Definition at line 972 of file app.c.
References quote().
Referenced by app_exec(), chanspy_exec(), common_exec(), controlplayback_exec(), extenspy_exec(), pbx_builtin_setvar(), speech_background(), and speech_load().
00973 { 00974 int argc; 00975 char *scan, *wasdelim = NULL; 00976 int paren = 0, quote = 0; 00977 00978 if (!buf || !array || !arraylen) 00979 return 0; 00980 00981 memset(array, 0, arraylen * sizeof(*array)); 00982 00983 scan = buf; 00984 00985 for (argc = 0; *scan && (argc < arraylen - 1); argc++) { 00986 array[argc] = scan; 00987 for (; *scan; scan++) { 00988 if (*scan == '(') 00989 paren++; 00990 else if (*scan == ')') { 00991 if (paren) 00992 paren--; 00993 } else if (*scan == '"' && delim != '"') { 00994 quote = quote ? 0 : 1; 00995 /* Remove quote character from argument */ 00996 memmove(scan, scan + 1, strlen(scan)); 00997 scan--; 00998 } else if (*scan == '\\') { 00999 /* Literal character, don't parse */ 01000 memmove(scan, scan + 1, strlen(scan)); 01001 } else if ((*scan == delim) && !paren && !quote) { 01002 wasdelim = scan; 01003 *scan++ = '\0'; 01004 break; 01005 } 01006 } 01007 } 01008 01009 /* If the last character in the original string was the delimiter, then 01010 * there is one additional argument. */ 01011 if (*scan || (scan > buf && (scan - 1) == wasdelim)) { 01012 array[argc++] = scan; 01013 } 01014 01015 return argc; 01016 }
int ast_control_streamfile | ( | struct ast_channel * | chan, | |
const char * | file, | |||
const char * | fwd, | |||
const char * | rev, | |||
const char * | stop, | |||
const char * | pause, | |||
const char * | restart, | |||
int | skipms | |||
) |
Stream a file with fast forward, pause, reverse, restart.
Definition at line 375 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, option_debug, and ast_channel::stream.
Referenced by controlplayback_exec(), handle_controlstreamfile(), and wait_file().
00379 { 00380 char *breaks = NULL; 00381 char *end = NULL; 00382 int blen = 2; 00383 int res; 00384 long pause_restart_point = 0; 00385 00386 if (stop) 00387 blen += strlen(stop); 00388 if (pause) 00389 blen += strlen(pause); 00390 if (restart) 00391 blen += strlen(restart); 00392 00393 if (blen > 2) { 00394 breaks = alloca(blen + 1); 00395 breaks[0] = '\0'; 00396 if (stop) 00397 strcat(breaks, stop); 00398 if (pause) 00399 strcat(breaks, pause); 00400 if (restart) 00401 strcat(breaks, restart); 00402 } 00403 if (chan->_state != AST_STATE_UP) 00404 res = ast_answer(chan); 00405 00406 if (file) { 00407 if ((end = strchr(file,':'))) { 00408 if (!strcasecmp(end, ":end")) { 00409 *end = '\0'; 00410 end++; 00411 } 00412 } 00413 } 00414 00415 for (;;) { 00416 ast_stopstream(chan); 00417 res = ast_streamfile(chan, file, chan->language); 00418 if (!res) { 00419 if (pause_restart_point) { 00420 ast_seekstream(chan->stream, pause_restart_point, SEEK_SET); 00421 pause_restart_point = 0; 00422 } 00423 else if (end) { 00424 ast_seekstream(chan->stream, 0, SEEK_END); 00425 end = NULL; 00426 }; 00427 res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms); 00428 } 00429 00430 if (res < 1) 00431 break; 00432 00433 /* We go at next loop if we got the restart char */ 00434 if (restart && strchr(restart, res)) { 00435 if (option_debug) 00436 ast_log(LOG_DEBUG, "we'll restart the stream here at next loop\n"); 00437 pause_restart_point = 0; 00438 continue; 00439 } 00440 00441 if (pause && strchr(pause, res)) { 00442 pause_restart_point = ast_tellstream(chan->stream); 00443 for (;;) { 00444 ast_stopstream(chan); 00445 res = ast_waitfordigit(chan, 1000); 00446 if (!res) 00447 continue; 00448 else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res))) 00449 break; 00450 } 00451 if (res == *pause) { 00452 res = 0; 00453 continue; 00454 } 00455 } 00456 00457 if (res == -1) 00458 break; 00459 00460 /* if we get one of our stop chars, return it to the calling function */ 00461 if (stop && strchr(stop, res)) 00462 break; 00463 } 00464 00465 /* If we are returning a digit cast it as char */ 00466 if (res > 0 || chan->stream) 00467 res = (char)res; 00468 00469 ast_stopstream(chan); 00470 00471 return res; 00472 }
int ast_dtmf_stream | ( | struct ast_channel * | chan, | |
struct ast_channel * | peer, | |||
const char * | digits, | |||
int | between | |||
) |
Send DTMF to a channel.
chan | The channel that will receive the DTMF frames | |
peer | (optional) Peer channel that will be autoserviced while the primary channel is receiving DTMF | |
digits | This is a string of characters representing the DTMF digits to be sent to the channel. Valid characters are "0123456789*#abcdABCD". Note: You can pass arguments 'f' or 'F', if you want to Flash the channel (if supported by the channel), or 'w' to add a 500 millisecond pause to the DTMF sequence. | |
between | This is the number of milliseconds to wait in between each DTMF digit. If zero milliseconds is specified, then the default value of 100 will be used. |
Definition at line 214 of file app.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), AST_CONTROL_FLASH, ast_indicate(), ast_log(), ast_opt_transmit_silence, ast_safe_sleep(), ast_senddigit(), ast_waitfor(), and LOG_WARNING.
Referenced by ast_bridge_call(), misdn_send_digit(), senddtmf_exec(), testclient_exec(), and testserver_exec().
00215 { 00216 const char *ptr; 00217 int res = 0; 00218 struct ast_silence_generator *silgen = NULL; 00219 00220 if (!between) 00221 between = 100; 00222 00223 if (peer) 00224 res = ast_autoservice_start(peer); 00225 00226 if (!res) 00227 res = ast_waitfor(chan, 100); 00228 00229 /* ast_waitfor will return the number of remaining ms on success */ 00230 if (res < 0) { 00231 if (peer) { 00232 ast_autoservice_stop(peer); 00233 } 00234 return res; 00235 } 00236 00237 if (ast_opt_transmit_silence) { 00238 silgen = ast_channel_start_silence_generator(chan); 00239 } 00240 00241 for (ptr = digits; *ptr; ptr++) { 00242 if (*ptr == 'w') { 00243 /* 'w' -- wait half a second */ 00244 if ((res = ast_safe_sleep(chan, 500))) 00245 break; 00246 } else if (strchr("0123456789*#abcdfABCDF", *ptr)) { 00247 /* Character represents valid DTMF */ 00248 if (*ptr == 'f' || *ptr == 'F') { 00249 /* ignore return values if not supported by channel */ 00250 ast_indicate(chan, AST_CONTROL_FLASH); 00251 } else 00252 ast_senddigit(chan, *ptr); 00253 /* pause between digits */ 00254 if ((res = ast_safe_sleep(chan, between))) 00255 break; 00256 } else 00257 ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr); 00258 } 00259 00260 if (peer) { 00261 /* Stop autoservice on the peer channel, but don't overwrite any error condition 00262 that has occurred previously while acting on the primary channel */ 00263 if (ast_autoservice_stop(peer) && !res) 00264 res = -1; 00265 } 00266 00267 if (silgen) { 00268 ast_channel_stop_silence_generator(chan, silgen); 00269 } 00270 00271 return res; 00272 }
void ast_install_vm_functions | ( | int(*)(const char *mailbox, const char *folder) | has_voicemail_func, | |
int(*)(const char *mailbox, int *newmsgs, int *oldmsgs) | inboxcount_func, | |||
int(*)(const char *context, const char *mailbox, const char *folder) | messagecount_func | |||
) |
Definition at line 152 of file app.c.
References ast_has_voicemail_func, ast_inboxcount_func, and ast_messagecount_func.
Referenced by load_module().
00155 { 00156 ast_has_voicemail_func = has_voicemail_func; 00157 ast_inboxcount_func = inboxcount_func; 00158 ast_messagecount_func = messagecount_func; 00159 }
int ast_ivr_menu_run | ( | struct ast_channel * | c, | |
struct ast_ivr_menu * | menu, | |||
void * | cbdata | |||
) |
Runs an IVR menu.
Definition at line 1373 of file app.c.
References ast_ivr_menu_run_internal().
Referenced by skel_exec().
01374 { 01375 int res = ast_ivr_menu_run_internal(chan, menu, cbdata); 01376 /* Hide internal coding */ 01377 return res > 0 ? 0 : res; 01378 }
static int ast_ivr_menu_run_internal | ( | struct ast_channel * | chan, | |
struct ast_ivr_menu * | menu, | |||
void * | cbdata | |||
) | [static] |
Definition at line 1286 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_debug, 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().
01287 { 01288 /* Execute an IVR menu structure */ 01289 int res=0; 01290 int pos = 0; 01291 int retries = 0; 01292 char exten[AST_MAX_EXTENSION] = "s"; 01293 if (option_exists(menu, "s") < 0) { 01294 strcpy(exten, "g"); 01295 if (option_exists(menu, "g") < 0) { 01296 ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title); 01297 return -1; 01298 } 01299 } 01300 while(!res) { 01301 while(menu->options[pos].option) { 01302 if (!strcasecmp(menu->options[pos].option, exten)) { 01303 res = ivr_dispatch(chan, menu->options + pos, exten, cbdata); 01304 if (option_debug) 01305 ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res); 01306 if (res < 0) 01307 break; 01308 else if (res & RES_UPONE) 01309 return 0; 01310 else if (res & RES_EXIT) 01311 return res; 01312 else if (res & RES_REPEAT) { 01313 int maxretries = res & 0xffff; 01314 if ((res & RES_RESTART) == RES_RESTART) { 01315 retries = 0; 01316 } else 01317 retries++; 01318 if (!maxretries) 01319 maxretries = 3; 01320 if ((maxretries > 0) && (retries >= maxretries)) { 01321 if (option_debug) 01322 ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries); 01323 return -2; 01324 } else { 01325 if (option_exists(menu, "g") > -1) 01326 strcpy(exten, "g"); 01327 else if (option_exists(menu, "s") > -1) 01328 strcpy(exten, "s"); 01329 } 01330 pos = 0; 01331 continue; 01332 } else if (res && strchr(AST_DIGIT_ANY, res)) { 01333 if (option_debug) 01334 ast_log(LOG_DEBUG, "Got start of extension, %c\n", res); 01335 exten[1] = '\0'; 01336 exten[0] = res; 01337 if ((res = read_newoption(chan, menu, exten, sizeof(exten)))) 01338 break; 01339 if (option_exists(menu, exten) < 0) { 01340 if (option_exists(menu, "i")) { 01341 if (option_debug) 01342 ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n"); 01343 strcpy(exten, "i"); 01344 pos = 0; 01345 continue; 01346 } else { 01347 if (option_debug) 01348 ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n"); 01349 res = -2; 01350 break; 01351 } 01352 } else { 01353 if (option_debug) 01354 ast_log(LOG_DEBUG, "New existing extension: %s\n", exten); 01355 pos = 0; 01356 continue; 01357 } 01358 } 01359 } 01360 pos++; 01361 } 01362 if (option_debug) 01363 ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res); 01364 pos = 0; 01365 if (!strcasecmp(exten, "s")) 01366 strcpy(exten, "g"); 01367 else 01368 break; 01369 } 01370 return res; 01371 }
int ast_linear_stream | ( | struct ast_channel * | chan, | |
const char * | filename, | |||
int | fd, | |||
int | allowoverride | |||
) |
Stream a filename (or file descriptor) as a generator.
Definition at line 346 of file app.c.
References ast_activate_generator(), ast_calloc, ast_config_AST_DATA_DIR, ast_copy_string(), ast_log(), ast_strlen_zero(), linear_state::autoclose, errno, linearstream, and LOG_WARNING.
00347 { 00348 struct linear_state *lin; 00349 char tmpf[256]; 00350 int res = -1; 00351 int autoclose = 0; 00352 if (fd < 0) { 00353 if (ast_strlen_zero(filename)) 00354 return -1; 00355 autoclose = 1; 00356 if (filename[0] == '/') 00357 ast_copy_string(tmpf, filename, sizeof(tmpf)); 00358 else 00359 snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_DATA_DIR, "sounds", filename); 00360 fd = open(tmpf, O_RDONLY); 00361 if (fd < 0){ 00362 ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno)); 00363 return -1; 00364 } 00365 } 00366 if ((lin = ast_calloc(1, sizeof(*lin)))) { 00367 lin->fd = fd; 00368 lin->allowoverride = allowoverride; 00369 lin->autoclose = autoclose; 00370 res = ast_activate_generator(chan, &linearstream, lin); 00371 } 00372 return res; 00373 }
enum AST_LOCK_RESULT ast_lock_path | ( | const char * | path | ) |
Lock a filesystem path.
path | the path to be locked |
Definition at line 1018 of file app.c.
References AST_LOCK_FAILURE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), ast_random(), errno, LOG_DEBUG, LOG_ERROR, LOG_WARNING, option_debug, and s.
Referenced by vm_lock_path().
01019 { 01020 char *s; 01021 char *fs; 01022 int res; 01023 int fd; 01024 int lp = strlen(path); 01025 time_t start; 01026 01027 if (!(s = alloca(lp + 10)) || !(fs = alloca(lp + 20))) { 01028 ast_log(LOG_WARNING, "Out of memory!\n"); 01029 return AST_LOCK_FAILURE; 01030 } 01031 01032 snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, ast_random()); 01033 fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600); 01034 if (fd < 0) { 01035 ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno)); 01036 return AST_LOCK_PATH_NOT_FOUND; 01037 } 01038 close(fd); 01039 01040 snprintf(s, strlen(path) + 9, "%s/.lock", path); 01041 start = time(NULL); 01042 while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) 01043 usleep(1); 01044 01045 unlink(fs); 01046 01047 if (res) { 01048 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno)); 01049 return AST_LOCK_TIMEOUT; 01050 } else { 01051 if (option_debug) 01052 ast_log(LOG_DEBUG, "Locked path '%s'\n", path); 01053 return AST_LOCK_SUCCESS; 01054 } 01055 }
int ast_play_and_prepend | ( | struct ast_channel * | chan, | |
char * | playfile, | |||
char * | recordfile, | |||
int | maxtime_sec, | |||
char * | fmt, | |||
int * | duration, | |||
int | beep, | |||
int | silencethreshold, | |||
int | maxsilence_ms | |||
) |
Record a message and prepend the message to the given record file after playing the optional playfile (or a beep), storing the duration in 'duration' and with a maximum
permitted silence time in milliseconds of 'maxsilence' under 'silencethreshold' or use '-1' for either or both parameters for defaults.
Definition at line 799 of file app.c.
References __ast_play_and_record().
Referenced by vm_forwardoptions().
00800 { 00801 return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf); 00802 }
int ast_play_and_record | ( | struct ast_channel * | chan, | |
const char * | playfile, | |||
const char * | recordfile, | |||
int | maxtime_sec, | |||
const char * | fmt, | |||
int * | duration, | |||
int | silencethreshold, | |||
int | maxsilence_ms, | |||
const char * | path | |||
) |
Record a file for a max amount of time (in seconds), in a given list of formats separated by '|', outputting the duration of the recording, and with a maximum
permitted silence time in milliseconds of 'maxsilence' under 'silencethreshold' or use '-1' for either or both parameters for defaults. calls ast_unlock_path() on 'path' if passed
Definition at line 794 of file app.c.
References __ast_play_and_record().
Referenced by app_exec(), ast_record_review(), and conf_run().
00795 { 00796 return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf); 00797 }
int ast_play_and_record_full | ( | struct ast_channel * | chan, | |
const char * | playfile, | |||
const char * | recordfile, | |||
int | maxtime, | |||
const char * | fmt, | |||
int * | duration, | |||
int | silencethreshold, | |||
int | maxsilence, | |||
const char * | path, | |||
const char * | acceptdtmf, | |||
const char * | canceldtmf | |||
) |
Definition at line 789 of file app.c.
References __ast_play_and_record(), and S_OR.
Referenced by play_record_review().
00790 { 00791 return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, default_acceptdtmf), S_OR(canceldtmf, default_canceldtmf)); 00792 }
int ast_play_and_wait | ( | struct ast_channel * | chan, | |
const char * | fn | |||
) |
Play a stream and wait for a digit, returning the digit that was pressed
Definition at line 474 of file app.c.
References AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), ast_waitstream(), and ast_channel::language.
Referenced by __ast_play_and_record(), advanced_options(), ast_record_review(), ast_say_counted_adjective(), ast_say_counted_noun(), dialout(), forward_message(), get_folder(), get_folder2(), leave_voicemail(), play_message_category(), play_message_duration(), play_record_review(), vm_authenticate(), vm_browse_messages_en(), vm_browse_messages_he(), vm_browse_messages_latin(), vm_exec(), vm_execmain(), vm_forwardoptions(), vm_instructions(), vm_intro(), vm_intro_cs(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_gr(), vm_intro_he(), vm_intro_it(), vm_intro_multilang(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_pt(), vm_intro_pt_BR(), vm_intro_se(), vm_newuser(), vm_options(), vm_play_folder_name(), vm_play_folder_name_gr(), vm_play_folder_name_pl(), vm_play_folder_name_ua(), vm_tempgreeting(), and vmauthenticate().
00475 { 00476 int d; 00477 d = ast_streamfile(chan, fn, chan->language); 00478 if (d) 00479 return d; 00480 d = ast_waitstream(chan, AST_DIGIT_ANY); 00481 ast_stopstream(chan); 00482 return d; 00483 }
char* ast_read_textfile | ( | const char * | file | ) |
Read a file into asterisk
Definition at line 1380 of file app.c.
References ast_log(), ast_malloc, errno, free, and LOG_WARNING.
Referenced by readfile_exec().
01381 { 01382 int fd; 01383 char *output = NULL; 01384 struct stat filesize; 01385 int count = 0; 01386 int res; 01387 if (stat(filename, &filesize) == -1) { 01388 ast_log(LOG_WARNING, "Error can't stat %s\n", filename); 01389 return NULL; 01390 } 01391 count = filesize.st_size + 1; 01392 fd = open(filename, O_RDONLY); 01393 if (fd < 0) { 01394 ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno)); 01395 return NULL; 01396 } 01397 if ((output = ast_malloc(count))) { 01398 res = read(fd, output, count - 1); 01399 if (res == count - 1) { 01400 output[res] = '\0'; 01401 } else { 01402 ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno)); 01403 free(output); 01404 output = NULL; 01405 } 01406 } 01407 close(fd); 01408 return output; 01409 }
int ast_record_review | ( | struct ast_channel * | chan, | |
const char * | playfile, | |||
const char * | recordfile, | |||
int | maxtime, | |||
const char * | fmt, | |||
int * | duration, | |||
const char * | path | |||
) |
Allow to record message and have a review option
Definition at line 1079 of file app.c.
References AST_DIGIT_ANY, ast_log(), ast_play_and_record(), ast_play_and_wait(), ast_stream_and_wait(), ast_verbose(), ast_waitfordigit(), ast_group_info::chan, ast_channel::language, LOG_WARNING, maxsilence, silencethreshold, and VERBOSE_PREFIX_3.
Referenced by conf_run().
01080 { 01081 int silencethreshold = 128; 01082 int maxsilence=0; 01083 int res = 0; 01084 int cmd = 0; 01085 int max_attempts = 3; 01086 int attempts = 0; 01087 int recorded = 0; 01088 int message_exists = 0; 01089 /* Note that urgent and private are for flagging messages as such in the future */ 01090 01091 /* barf if no pointer passed to store duration in */ 01092 if (duration == NULL) { 01093 ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n"); 01094 return -1; 01095 } 01096 01097 cmd = '3'; /* Want to start by recording */ 01098 01099 while ((cmd >= 0) && (cmd != 't')) { 01100 switch (cmd) { 01101 case '1': 01102 if (!message_exists) { 01103 /* In this case, 1 is to record a message */ 01104 cmd = '3'; 01105 break; 01106 } else { 01107 ast_stream_and_wait(chan, "vm-msgsaved", chan->language, ""); 01108 cmd = 't'; 01109 return res; 01110 } 01111 case '2': 01112 /* Review */ 01113 ast_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n"); 01114 cmd = ast_stream_and_wait(chan, recordfile, chan->language, AST_DIGIT_ANY); 01115 break; 01116 case '3': 01117 message_exists = 0; 01118 /* Record */ 01119 if (recorded == 1) 01120 ast_verbose(VERBOSE_PREFIX_3 "Re-recording\n"); 01121 else 01122 ast_verbose(VERBOSE_PREFIX_3 "Recording\n"); 01123 recorded = 1; 01124 cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path); 01125 if (cmd == -1) { 01126 /* User has hung up, no options to give */ 01127 return cmd; 01128 } 01129 if (cmd == '0') { 01130 break; 01131 } else if (cmd == '*') { 01132 break; 01133 } 01134 else { 01135 /* If all is well, a message exists */ 01136 message_exists = 1; 01137 cmd = 0; 01138 } 01139 break; 01140 case '4': 01141 case '5': 01142 case '6': 01143 case '7': 01144 case '8': 01145 case '9': 01146 case '*': 01147 case '#': 01148 cmd = ast_play_and_wait(chan, "vm-sorry"); 01149 break; 01150 default: 01151 if (message_exists) { 01152 cmd = ast_play_and_wait(chan, "vm-review"); 01153 } 01154 else { 01155 cmd = ast_play_and_wait(chan, "vm-torerecord"); 01156 if (!cmd) 01157 cmd = ast_waitfordigit(chan, 600); 01158 } 01159 01160 if (!cmd) 01161 cmd = ast_waitfordigit(chan, 6000); 01162 if (!cmd) { 01163 attempts++; 01164 } 01165 if (attempts > max_attempts) { 01166 cmd = 't'; 01167 } 01168 } 01169 } 01170 if (cmd == 't') 01171 cmd = 0; 01172 return cmd; 01173 }
void ast_uninstall_vm_functions | ( | void | ) |
Definition at line 161 of file app.c.
References ast_has_voicemail_func, ast_inboxcount_func, and ast_messagecount_func.
Referenced by unload_module().
00162 { 00163 ast_has_voicemail_func = NULL; 00164 ast_inboxcount_func = NULL; 00165 ast_messagecount_func = NULL; 00166 }
int ast_unlock_path | ( | const char * | path | ) |
Unlock a path
Definition at line 1057 of file app.c.
References ast_log(), errno, LOG_DEBUG, LOG_ERROR, LOG_WARNING, option_debug, and s.
Referenced by __ast_play_and_record(), copy_message(), count_messages(), leave_voicemail(), resequence_mailbox(), and save_to_folder().
01058 { 01059 char *s; 01060 int res; 01061 01062 if (!(s = alloca(strlen(path) + 10))) { 01063 ast_log(LOG_WARNING, "Out of memory!\n"); 01064 return -1; 01065 } 01066 01067 snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock"); 01068 01069 if ((res = unlink(s))) 01070 ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno)); 01071 else { 01072 if (option_debug) 01073 ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path); 01074 } 01075 01076 return res; 01077 }
static int ivr_dispatch | ( | struct ast_channel * | chan, | |
struct ast_ivr_option * | option, | |||
char * | exten, | |||
void * | cbdata | |||
) | [static] |
Definition at line 1182 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_stream_and_wait(), ast_waitfordigit(), ast_channel::language, LOG_NOTICE, ast_channel::pbx, RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, and ast_pbx::rtimeout.
Referenced by ast_ivr_menu_run_internal().
01183 { 01184 int res; 01185 int (*ivr_func)(struct ast_channel *, void *); 01186 char *c; 01187 char *n; 01188 01189 switch(option->action) { 01190 case AST_ACTION_UPONE: 01191 return RES_UPONE; 01192 case AST_ACTION_EXIT: 01193 return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff); 01194 case AST_ACTION_REPEAT: 01195 return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff); 01196 case AST_ACTION_RESTART: 01197 return RES_RESTART ; 01198 case AST_ACTION_NOOP: 01199 return 0; 01200 case AST_ACTION_BACKGROUND: 01201 res = ast_stream_and_wait(chan, (char *)option->adata, chan->language, AST_DIGIT_ANY); 01202 if (res < 0) { 01203 ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata); 01204 res = 0; 01205 } 01206 return res; 01207 case AST_ACTION_PLAYBACK: 01208 res = ast_stream_and_wait(chan, (char *)option->adata, chan->language, ""); 01209 if (res < 0) { 01210 ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata); 01211 res = 0; 01212 } 01213 return res; 01214 case AST_ACTION_MENU: 01215 res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata); 01216 /* Do not pass entry errors back up, treaat ast though ti was an "UPONE" */ 01217 if (res == -2) 01218 res = 0; 01219 return res; 01220 case AST_ACTION_WAITOPTION: 01221 res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10)); 01222 if (!res) 01223 return 't'; 01224 return res; 01225 case AST_ACTION_CALLBACK: 01226 ivr_func = option->adata; 01227 res = ivr_func(chan, cbdata); 01228 return res; 01229 case AST_ACTION_TRANSFER: 01230 res = ast_parseable_goto(chan, option->adata); 01231 return 0; 01232 case AST_ACTION_PLAYLIST: 01233 case AST_ACTION_BACKLIST: 01234 res = 0; 01235 c = ast_strdupa(option->adata); 01236 while ((n = strsep(&c, ";"))) { 01237 if ((res = ast_stream_and_wait(chan, n, chan->language, 01238 (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : ""))) 01239 break; 01240 } 01241 ast_stopstream(chan); 01242 return res; 01243 default: 01244 ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action); 01245 return 0; 01246 }; 01247 return -1; 01248 }
static void* linear_alloc | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 319 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.
00320 { 00321 struct linear_state *ls; 00322 /* In this case, params is already malloc'd */ 00323 if (params) { 00324 ls = params; 00325 if (ls->allowoverride) 00326 ast_set_flag(chan, AST_FLAG_WRITE_INT); 00327 else 00328 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 00329 ls->origwfmt = chan->writeformat; 00330 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 00331 ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name); 00332 free(ls); 00333 ls = params = NULL; 00334 } 00335 } 00336 return params; 00337 }
static int linear_generator | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 292 of file app.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), f, linear_state::fd, and LOG_WARNING.
00293 { 00294 struct ast_frame f; 00295 short buf[2048 + AST_FRIENDLY_OFFSET / 2]; 00296 struct linear_state *ls = data; 00297 int res; 00298 len = samples * 2; 00299 if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) { 00300 ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len); 00301 len = sizeof(buf) - AST_FRIENDLY_OFFSET; 00302 } 00303 memset(&f, 0, sizeof(f)); 00304 res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len); 00305 if (res > 0) { 00306 f.frametype = AST_FRAME_VOICE; 00307 f.subclass = AST_FORMAT_SLINEAR; 00308 f.data = buf + AST_FRIENDLY_OFFSET/2; 00309 f.datalen = res; 00310 f.samples = res / 2; 00311 f.offset = AST_FRIENDLY_OFFSET; 00312 ast_write(chan, &f); 00313 if (res == len) 00314 return 0; 00315 } 00316 return -1; 00317 }
static void linear_release | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 281 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.
00282 { 00283 struct linear_state *ls = params; 00284 if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) { 00285 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt); 00286 } 00287 if (ls->autoclose) 00288 close(ls->fd); 00289 free(params); 00290 }
static int option_exists | ( | struct ast_ivr_menu * | menu, | |
char * | option | |||
) | [static] |
Definition at line 1250 of file app.c.
References ast_ivr_option::option, and ast_ivr_menu::options.
Referenced by ast_ivr_menu_run_internal().
01251 { 01252 int x; 01253 for (x = 0; menu->options[x].option; x++) 01254 if (!strcasecmp(menu->options[x].option, option)) 01255 return x; 01256 return -1; 01257 }
static int option_matchmore | ( | struct ast_ivr_menu * | menu, | |
char * | option | |||
) | [static] |
Definition at line 1259 of file app.c.
References ast_ivr_option::option, and ast_ivr_menu::options.
Referenced by read_newoption().
01260 { 01261 int x; 01262 for (x = 0; menu->options[x].option; x++) 01263 if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 01264 (menu->options[x].option[strlen(option)])) 01265 return x; 01266 return -1; 01267 }
static int read_newoption | ( | struct ast_channel * | chan, | |
struct ast_ivr_menu * | menu, | |||
char * | exten, | |||
int | maxexten | |||
) | [static] |
Definition at line 1269 of file app.c.
References ast_waitfordigit(), ast_pbx::dtimeout, option_matchmore(), and ast_channel::pbx.
Referenced by ast_ivr_menu_run_internal().
01270 { 01271 int res=0; 01272 int ms; 01273 while (option_matchmore(menu, exten)) { 01274 ms = chan->pbx ? chan->pbx->dtimeout : 5000; 01275 if (strlen(exten) >= maxexten - 1) 01276 break; 01277 res = ast_waitfordigit(chan, ms); 01278 if (res < 1) 01279 break; 01280 exten[strlen(exten) + 1] = '\0'; 01281 exten[strlen(exten)] = res; 01282 } 01283 return res > 0 ? 0 : res; 01284 }
int(*) ast_has_voicemail_func(const char *mailbox, const char *folder) = NULL [static] |
Definition at line 148 of file app.c.
Referenced by ast_app_has_voicemail(), ast_install_vm_functions(), and ast_uninstall_vm_functions().
int(*) ast_inboxcount_func(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL [static] |
Definition at line 149 of file app.c.
Referenced by ast_app_inboxcount(), ast_install_vm_functions(), and ast_uninstall_vm_functions().
int(*) ast_messagecount_func(const char *context, const char *mailbox, const char *folder) = NULL [static] |
Definition at line 150 of file app.c.
Referenced by ast_app_messagecount(), ast_install_vm_functions(), and ast_uninstall_vm_functions().
char default_acceptdtmf[] = "#" [static] |
char default_canceldtmf[] = "" [static] |
int global_maxsilence = 0 [static] |
int global_silence_threshold = 128 [static] |
struct ast_generator linearstream [static] |