Convenient Application Routines. More...
#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 | 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) |
struct 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) |
static | AST_LIST_HEAD_STATIC (groups, ast_group_info) |
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 |
Convenient Application Routines.
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. |
Note that we still want to use the number of seconds passed for the max message, otherwise we could get a situation where this stream is never closed (which would create a resource leak).
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_frame::frametype, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_channel::readformat, strsep(), ast_frame::subclass, 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::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(), and ast_streamfile().
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 | ) | [read] |
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, ast_group_info::group, 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(), do_monitor(), 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(), forkcdr_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) |
Note: if there are more arguments in the string than the array will hold, the last element of the array will contain the remaining arguments, not separated.
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(), 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 linear_state::allowoverride, ast_activate_generator(), ast_calloc, ast_config_AST_DATA_DIR, ast_copy_string(), ast_log(), ast_strlen_zero(), linear_state::autoclose, errno, linear_state::fd, 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 }
static AST_LIST_HEAD_STATIC | ( | groups | , | |
ast_group_info | ||||
) | [static] |
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(), and ast_waitstream().
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(), 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(), close_mailbox(), 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(), LOG_NOTICE, ast_channel::pbx, RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, ast_pbx::rtimeout, and strsep().
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, 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(), ast_frame::data, ast_frame::datalen, linear_state::fd, ast_frame::frametype, LOG_WARNING, ast_frame::offset, ast_frame::samples, and ast_frame::subclass.
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, 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().
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().
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] |
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] |
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] |
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] |