#include "asterisk.h"
#include <regex.h>
#include <sys/file.h>
#include "asterisk/paths.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/indications.h"
#include "asterisk/linkedlists.h"
#include "asterisk/strings.h"

Go to the source code of this file.
Data Structures | |
| struct | groups |
| struct | linear_state |
| struct | path_lock |
| struct | path_lock_list |
Defines | |
| #define | MAX_OTHER_FORMATS 10 |
| #define | RES_EXIT (1 << 17) |
| #define | RES_REPEAT (1 << 18) |
| #define | RES_RESTART ((1 << 19) | RES_REPEAT) |
| #define | RES_UPONE (1 << 16) |
Functions | |
| unsigned int | __ast_app_separate_args (char *buf, char delim, int remove_chars, char **array, int arraylen) |
| Separate a string into arguments in an array. | |
| 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 void | __fini_groups (void) |
| static void | __init_groups (void) |
| int | ast_app_dtget (struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout) |
| This function presents a dialtone and reads an extension into 'collect' which must be a pointer to a **pre-initialized** array of char having a size of 'size' suitable for writing to. It will collect no more than the smaller of 'maxlen' or 'size' minus the original strlen() of collect digits. | |
| enum ast_getdata_result | ast_app_getdata (struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout) |
| ast_app_getdata | |
| 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) |
| Discard all group counting for a channel. | |
| int | ast_app_group_get_count (const char *group, const char *category) |
| Get the current channel count of the specified group and category. | |
| struct ast_group_info * | ast_app_group_list_head (void) |
| Get the head of the group count list. | |
| int | ast_app_group_list_rdlock (void) |
| Read Lock the group count list. | |
| int | ast_app_group_list_unlock (void) |
| Unlock the group count list. | |
| int | ast_app_group_list_wrlock (void) |
| Write Lock the group count list. | |
| 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. | |
| 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. | |
| 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. | |
| int | ast_app_group_update (struct ast_channel *old, struct ast_channel *new) |
| Update all group counting for a channel to a new one. | |
| int | ast_app_has_voicemail (const char *mailbox, const char *folder) |
| Determine if a given mailbox has any voicemail. | |
| int | ast_app_inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs) |
| Determine number of new/old messages in a mailbox. | |
| int | ast_app_messagecount (const char *context, const char *mailbox, const char *folder) |
| Determine number of messages in a given mailbox and folder. | |
| void | ast_app_options2str64 (const struct ast_app_option *options, struct ast_flags64 *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. | |
| int | ast_app_parse_options64 (const struct ast_app_option *options, struct ast_flags64 *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) |
| 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, long *offsetms) |
| Stream a file with fast forward, pause, reverse, restart. | |
| int | ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration) |
| Send DTMF to a channel. | |
| int | ast_get_encoded_char (const char *stream, char *result, size_t *consumed) |
| Decode an encoded control or extended ASCII character. | |
| int | ast_get_encoded_str (const char *stream, char *result, size_t result_size) |
| Decode a string which may contain multiple encoded control or extended ASCII characters. | |
| 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) |
| Stream a filename (or file descriptor) as a generator. | |
| enum AST_LOCK_RESULT | ast_lock_path (const char *path) |
| Lock a filesystem path. | |
| static enum AST_LOCK_RESULT | ast_lock_path_flock (const char *path) |
| static enum AST_LOCK_RESULT | ast_lock_path_lockfile (const char *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) |
| 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. | |
| 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) |
| 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. | |
| 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) |
| Play a stream and wait for a digit, returning the digit that was pressed. | |
| char * | ast_read_textfile (const char *filename) |
| Read a file into asterisk. | |
| 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. | |
| void | ast_set_lock_type (enum AST_LOCK_TYPE type) |
| Set the type of locks used by ast_lock_path(). | |
| int | ast_str_get_encoded_str (struct ast_str **str, int maxlen, const char *stream) |
| Decode a stream of encoded control or extended ASCII characters. | |
| void | ast_uninstall_vm_functions (void) |
| int | ast_unlock_path (const char *path) |
| Unlock a path. | |
| static int | ast_unlock_path_flock (const char *path) |
| static int | ast_unlock_path_lockfile (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 void | path_lock_destroy (struct path_lock *obj) |
| 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 enum AST_LOCK_TYPE | ast_lock_type = AST_LOCK_TYPE_LOCKFILE |
| 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 MAX_OTHER_FORMATS 10 |
| #define RES_EXIT (1 << 17) |
Definition at line 1416 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
| #define RES_REPEAT (1 << 18) |
Definition at line 1417 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
| #define RES_RESTART ((1 << 19) | RES_REPEAT) |
Definition at line 1418 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
| #define RES_UPONE (1 << 16) |
Definition at line 1415 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
| unsigned int __ast_app_separate_args | ( | char * | buf, | |
| char | delim, | |||
| int | remove_chars, | |||
| 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 | |
| remove_chars | Remove backslashes and quote characters, while parsing | |
| 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 1037 of file app.c.
References quote().
Referenced by ast_app_separate_args().
01038 { 01039 int argc; 01040 char *scan, *wasdelim = NULL; 01041 int paren = 0, quote = 0; 01042 01043 if (!buf || !array || !arraylen) 01044 return 0; 01045 01046 memset(array, 0, arraylen * sizeof(*array)); 01047 01048 scan = buf; 01049 01050 for (argc = 0; *scan && (argc < arraylen - 1); argc++) { 01051 array[argc] = scan; 01052 for (; *scan; scan++) { 01053 if (*scan == '(') 01054 paren++; 01055 else if (*scan == ')') { 01056 if (paren) 01057 paren--; 01058 } else if (*scan == '"' && delim != '"') { 01059 quote = quote ? 0 : 1; 01060 if (remove_chars) { 01061 /* Remove quote character from argument */ 01062 memmove(scan, scan + 1, strlen(scan)); 01063 scan--; 01064 } 01065 } else if (*scan == '\\') { 01066 if (remove_chars) { 01067 /* Literal character, don't parse */ 01068 memmove(scan, scan + 1, strlen(scan)); 01069 } else { 01070 scan++; 01071 } 01072 } else if ((*scan == delim) && !paren && !quote) { 01073 wasdelim = scan; 01074 *scan++ = '\0'; 01075 break; 01076 } 01077 } 01078 } 01079 01080 /* If the last character in the original string was the delimiter, then 01081 * there is one additional argument. */ 01082 if (*scan || (scan > buf && (scan - 1) == wasdelim)) { 01083 array[argc++] = scan; 01084 } 01085 01086 return argc; 01087 }
| 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 572 of file app.c.
References ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_copy_string(), ast_debug, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FILE_MODE, 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_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_verb, ast_waitfor(), ast_writefile(), ast_writestream(), f, ast_frame::frametype, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, ast_channel::readformat, strsep(), ast_frame::subclass, and ast_dsp::totalsilence.
Referenced by ast_play_and_prepend(), ast_play_and_record(), and ast_play_and_record_full().
00573 { 00574 int d = 0; 00575 char *fmts; 00576 char comment[256]; 00577 int x, fmtcnt = 1, res = -1, outmsg = 0; 00578 struct ast_filestream *others[MAX_OTHER_FORMATS]; 00579 char *sfmt[MAX_OTHER_FORMATS]; 00580 char *stringp = NULL; 00581 time_t start, end; 00582 struct ast_dsp *sildet = NULL; /* silence detector dsp */ 00583 int totalsilence = 0; 00584 int rfmt = 0; 00585 struct ast_silence_generator *silgen = NULL; 00586 char prependfile[80]; 00587 00588 if (silencethreshold < 0) 00589 silencethreshold = global_silence_threshold; 00590 00591 if (maxsilence < 0) 00592 maxsilence = global_maxsilence; 00593 00594 /* barf if no pointer passed to store duration in */ 00595 if (!duration) { 00596 ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n"); 00597 return -1; 00598 } 00599 00600 ast_debug(1, "play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); 00601 snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); 00602 00603 if (playfile || beep) { 00604 if (!beep) 00605 d = ast_play_and_wait(chan, playfile); 00606 if (d > -1) 00607 d = ast_stream_and_wait(chan, "beep", ""); 00608 if (d < 0) 00609 return -1; 00610 } 00611 00612 if (prepend) { 00613 ast_copy_string(prependfile, recordfile, sizeof(prependfile)); 00614 strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); 00615 } 00616 00617 fmts = ast_strdupa(fmt); 00618 00619 stringp = fmts; 00620 strsep(&stringp, "|"); 00621 ast_debug(1, "Recording Formats: sfmts=%s\n", fmts); 00622 sfmt[0] = ast_strdupa(fmts); 00623 00624 while ((fmt = strsep(&stringp, "|"))) { 00625 if (fmtcnt > MAX_OTHER_FORMATS - 1) { 00626 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n"); 00627 break; 00628 } 00629 sfmt[fmtcnt++] = ast_strdupa(fmt); 00630 } 00631 00632 end = start = time(NULL); /* pre-initialize end to be same as start in case we never get into loop */ 00633 for (x = 0; x < fmtcnt; x++) { 00634 others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, O_TRUNC, 0, AST_FILE_MODE); 00635 ast_verb(3, "x=%d, open writing: %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]); 00636 00637 if (!others[x]) 00638 break; 00639 } 00640 00641 if (path) 00642 ast_unlock_path(path); 00643 00644 if (maxsilence > 0) { 00645 sildet = ast_dsp_new(); /* Create the silence detector */ 00646 if (!sildet) { 00647 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00648 return -1; 00649 } 00650 ast_dsp_set_threshold(sildet, silencethreshold); 00651 rfmt = chan->readformat; 00652 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00653 if (res < 0) { 00654 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00655 ast_dsp_free(sildet); 00656 return -1; 00657 } 00658 } 00659 00660 if (!prepend) { 00661 /* Request a video update */ 00662 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 00663 00664 if (ast_opt_transmit_silence) 00665 silgen = ast_channel_start_silence_generator(chan); 00666 } 00667 00668 if (x == fmtcnt) { 00669 /* Loop forever, writing the packets we read to the writer(s), until 00670 we read a digit or get a hangup */ 00671 struct ast_frame *f; 00672 for (;;) { 00673 res = ast_waitfor(chan, 2000); 00674 if (!res) { 00675 ast_debug(1, "One waitfor failed, trying another\n"); 00676 /* Try one more time in case of masq */ 00677 res = ast_waitfor(chan, 2000); 00678 if (!res) { 00679 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); 00680 res = -1; 00681 } 00682 } 00683 00684 if (res < 0) { 00685 f = NULL; 00686 break; 00687 } 00688 f = ast_read(chan); 00689 if (!f) 00690 break; 00691 if (f->frametype == AST_FRAME_VOICE) { 00692 /* write each format */ 00693 for (x = 0; x < fmtcnt; x++) { 00694 if (prepend && !others[x]) 00695 break; 00696 res = ast_writestream(others[x], f); 00697 } 00698 00699 /* Silence Detection */ 00700 if (maxsilence > 0) { 00701 int dspsilence = 0; 00702 ast_dsp_silence(sildet, f, &dspsilence); 00703 if (dspsilence) 00704 totalsilence = dspsilence; 00705 else 00706 totalsilence = 0; 00707 00708 if (totalsilence > maxsilence) { 00709 /* Ended happily with silence */ 00710 ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); 00711 res = 'S'; 00712 outmsg = 2; 00713 break; 00714 } 00715 } 00716 /* Exit on any error */ 00717 if (res) { 00718 ast_log(LOG_WARNING, "Error writing frame\n"); 00719 break; 00720 } 00721 } else if (f->frametype == AST_FRAME_VIDEO) { 00722 /* Write only once */ 00723 ast_writestream(others[0], f); 00724 } else if (f->frametype == AST_FRAME_DTMF) { 00725 if (prepend) { 00726 /* stop recording with any digit */ 00727 ast_verb(3, "User ended message by pressing %c\n", f->subclass); 00728 res = 't'; 00729 outmsg = 2; 00730 break; 00731 } 00732 if (strchr(acceptdtmf, f->subclass)) { 00733 ast_verb(3, "User ended message by pressing %c\n", f->subclass); 00734 res = f->subclass; 00735 outmsg = 2; 00736 break; 00737 } 00738 if (strchr(canceldtmf, f->subclass)) { 00739 ast_verb(3, "User cancelled message by pressing %c\n", f->subclass); 00740 res = f->subclass; 00741 outmsg = 0; 00742 break; 00743 } 00744 } 00745 if (maxtime) { 00746 end = time(NULL); 00747 if (maxtime < (end - start)) { 00748 ast_verb(3, "Took too long, cutting it short...\n"); 00749 res = 't'; 00750 outmsg = 2; 00751 break; 00752 } 00753 } 00754 ast_frfree(f); 00755 } 00756 if (!f) { 00757 ast_verb(3, "User hung up\n"); 00758 res = -1; 00759 outmsg = 1; 00760 } else { 00761 ast_frfree(f); 00762 } 00763 } else { 00764 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); 00765 } 00766 00767 if (!prepend) { 00768 if (silgen) 00769 ast_channel_stop_silence_generator(chan, silgen); 00770 } 00771 00772 /*!\note 00773 * Instead of asking how much time passed (end - start), calculate the number 00774 * of seconds of audio which actually went into the file. This fixes a 00775 * problem where audio is stopped up on the network and never gets to us. 00776 * 00777 * Note that we still want to use the number of seconds passed for the max 00778 * message, otherwise we could get a situation where this stream is never 00779 * closed (which would create a resource leak). 00780 */ 00781 *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0; 00782 00783 if (!prepend) { 00784 for (x = 0; x < fmtcnt; x++) { 00785 if (!others[x]) 00786 break; 00787 /*!\note 00788 * If we ended with silence, trim all but the first 200ms of silence 00789 * off the recording. However, if we ended with '#', we don't want 00790 * to trim ANY part of the recording. 00791 */ 00792 if (res > 0 && totalsilence) { 00793 ast_stream_rewind(others[x], totalsilence - 200); 00794 /* Reduce duration by a corresponding amount */ 00795 if (x == 0 && *duration) { 00796 *duration -= (totalsilence - 200) / 1000; 00797 if (*duration < 0) { 00798 *duration = 0; 00799 } 00800 } 00801 } 00802 ast_truncstream(others[x]); 00803 ast_closestream(others[x]); 00804 } 00805 } 00806 00807 if (prepend && outmsg) { 00808 struct ast_filestream *realfiles[MAX_OTHER_FORMATS]; 00809 struct ast_frame *fr; 00810 00811 for (x = 0; x < fmtcnt; x++) { 00812 snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); 00813 realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); 00814 if (!others[x] || !realfiles[x]) 00815 break; 00816 /*!\note Same logic as above. */ 00817 if (totalsilence) 00818 ast_stream_rewind(others[x], totalsilence - 200); 00819 ast_truncstream(others[x]); 00820 /* add the original file too */ 00821 while ((fr = ast_readframe(realfiles[x]))) { 00822 ast_writestream(others[x], fr); 00823 ast_frfree(fr); 00824 } 00825 ast_closestream(others[x]); 00826 ast_closestream(realfiles[x]); 00827 ast_filerename(prependfile, recordfile, sfmt[x]); 00828 ast_verb(4, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile); 00829 ast_filedelete(prependfile, sfmt[x]); 00830 } 00831 } 00832 if (rfmt && ast_set_read_format(chan, rfmt)) { 00833 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00834 } 00835 if (outmsg == 2) { 00836 ast_stream_and_wait(chan, "auth-thankyou", ""); 00837 } 00838 if (sildet) 00839 ast_dsp_free(sildet); 00840 return res; 00841 }
| int ast_app_dtget | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| char * | collect, | |||
| size_t | size, | |||
| int | maxlen, | |||
| int | timeout | |||
| ) |
This function presents a dialtone and reads an extension into 'collect' which must be a pointer to a **pre-initialized** array of char having a size of 'size' suitable for writing to. It will collect no more than the smaller of 'maxlen' or 'size' minus the original strlen() of collect digits.
Present a dialtone and collect a certain length extension.
| chan | struct. | |
| context | ||
| collect | ||
| size | ||
| maxlen | ||
| timeout | timeout in seconds |
Definition at line 66 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().
00067 { 00068 struct tone_zone_sound *ts; 00069 int res = 0, x = 0; 00070 00071 if (maxlen > size) 00072 maxlen = size; 00073 00074 if (!timeout && chan->pbx) 00075 timeout = chan->pbx->dtimeout; 00076 else if (!timeout) 00077 timeout = 5; 00078 00079 if ((ts = ast_get_indication_tone(chan->zone, "dial")) && 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 00097 if (res >= 0) 00098 res = ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num) ? 1 : 0; 00099 00100 return res; 00101 }
| enum ast_getdata_result ast_app_getdata | ( | struct ast_channel * | c, | |
| const char * | prompt, | |||
| char * | s, | |||
| int | maxlen, | |||
| int | timeout | |||
| ) |
ast_app_getdata
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 111 of file app.c.
References AST_GETDATA_EMPTY_END_TERMINATED, ast_readstring(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_pbx::dtimeout, ast_channel::language, ast_channel::pbx, ast_pbx::rtimeout, and strsep().
Referenced by auth_exec(), conf_exec(), dictate_exec(), find_conf(), login_exec(), read_exec(), testclient_exec(), testserver_exec(), and vm_exec().
00112 { 00113 int res = 0, to, fto; 00114 char *front, *filename; 00115 00116 /* XXX Merge with full version? XXX */ 00117 00118 if (maxlen) 00119 s[0] = '\0'; 00120 00121 if (!prompt) 00122 prompt = ""; 00123 00124 filename = ast_strdupa(prompt); 00125 while ((front = strsep(&filename, "&"))) { 00126 if (!ast_strlen_zero(front)) { 00127 res = ast_streamfile(c, front, c->language); 00128 if (res) 00129 continue; 00130 } 00131 if (ast_strlen_zero(filename)) { 00132 /* set timeouts for the last prompt */ 00133 fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000; 00134 to = c->pbx ? c->pbx->dtimeout * 1000 : 2000; 00135 00136 if (timeout > 0) 00137 fto = to = timeout; 00138 if (timeout < 0) 00139 fto = to = 1000000000; 00140 } else { 00141 /* there is more than one prompt, so 00142 get rid of the long timeout between 00143 prompts, and make it 50ms */ 00144 fto = 50; 00145 to = c->pbx ? c->pbx->dtimeout * 1000 : 2000; 00146 } 00147 res = ast_readstring(c, s, maxlen, to, fto, "#"); 00148 if (res == AST_GETDATA_EMPTY_END_TERMINATED) { 00149 return res; 00150 } 00151 if (!ast_strlen_zero(s)) { 00152 return res; 00153 } 00154 } 00155 00156 return res; 00157 }
| 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 162 of file app.c.
References ast_readstring_full(), ast_streamfile(), ast_strlen_zero(), and ast_channel::language.
Referenced by handle_getdata().
00163 { 00164 int res, to = 2000, fto = 6000; 00165 00166 if (!ast_strlen_zero(prompt)) { 00167 res = ast_streamfile(c, prompt, c->language); 00168 if (res < 0) 00169 return res; 00170 } 00171 00172 if (timeout > 0) 00173 fto = to = timeout; 00174 if (timeout < 0) 00175 fto = to = 1000000000; 00176 00177 res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd); 00178 00179 return res; 00180 }
| int ast_app_group_discard | ( | struct ast_channel * | chan | ) |
Discard all group counting for a channel.
Definition at line 997 of file app.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_group_info::chan, and ast_group_info::group_list.
Referenced by ast_channel_free().
00998 { 00999 struct ast_group_info *gi = NULL; 01000 01001 AST_RWLIST_WRLOCK(&groups); 01002 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) { 01003 if (gi->chan == chan) { 01004 AST_RWLIST_REMOVE_CURRENT(group_list); 01005 ast_free(gi); 01006 } 01007 } 01008 AST_RWLIST_TRAVERSE_SAFE_END; 01009 AST_RWLIST_UNLOCK(&groups); 01010 01011 return 0; 01012 }
| 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 935 of file app.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, ast_group_info::group, and ast_group_info::group_list.
Referenced by group_count_function_read().
00936 { 00937 struct ast_group_info *gi = NULL; 00938 int count = 0; 00939 00940 if (ast_strlen_zero(group)) 00941 return 0; 00942 00943 AST_RWLIST_RDLOCK(&groups); 00944 AST_RWLIST_TRAVERSE(&groups, gi, group_list) { 00945 if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) 00946 count++; 00947 } 00948 AST_RWLIST_UNLOCK(&groups); 00949 00950 return count; 00951 }
| struct ast_group_info* ast_app_group_list_head | ( | void | ) | [read] |
Get the head of the group count list.
Definition at line 1024 of file app.c.
References AST_RWLIST_FIRST.
Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().
01025 { 01026 return AST_RWLIST_FIRST(&groups); 01027 }
| int ast_app_group_list_rdlock | ( | void | ) |
Read Lock the group count list.
Definition at line 1019 of file app.c.
References AST_RWLIST_RDLOCK.
Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().
01020 { 01021 return AST_RWLIST_RDLOCK(&groups); 01022 }
| int ast_app_group_list_unlock | ( | void | ) |
Unlock the group count list.
Definition at line 1029 of file app.c.
References AST_RWLIST_UNLOCK.
Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().
01030 { 01031 return AST_RWLIST_UNLOCK(&groups); 01032 }
| int ast_app_group_list_wrlock | ( | void | ) |
Write Lock the group count list.
Definition at line 1014 of file app.c.
References AST_RWLIST_WRLOCK.
01015 { 01016 return AST_RWLIST_WRLOCK(&groups); 01017 }
| 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 953 of file app.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, ast_group_info::group, and ast_group_info::group_list.
Referenced by group_match_count_function_read().
00954 { 00955 struct ast_group_info *gi = NULL; 00956 regex_t regexbuf; 00957 int count = 0; 00958 00959 if (ast_strlen_zero(groupmatch)) 00960 return 0; 00961 00962 /* if regex compilation fails, return zero matches */ 00963 if (regcomp(®exbuf, groupmatch, REG_EXTENDED | REG_NOSUB)) 00964 return 0; 00965 00966 AST_RWLIST_RDLOCK(&groups); 00967 AST_RWLIST_TRAVERSE(&groups, gi, group_list) { 00968 if (!regexec(®exbuf, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) 00969 count++; 00970 } 00971 AST_RWLIST_UNLOCK(&groups); 00972 00973 regfree(®exbuf); 00974 00975 return count; 00976 }
| 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 890 of file app.c.
References ast_app_group_split_group(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), calloc, ast_group_info::category, ast_group_info::chan, free, ast_group_info::group, ast_group_info::group_list, and len().
Referenced by dial_exec_full(), and group_function_write().
00891 { 00892 int res = 0; 00893 char group[80] = "", category[80] = ""; 00894 struct ast_group_info *gi = NULL; 00895 size_t len = 0; 00896 00897 if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) 00898 return -1; 00899 00900 /* Calculate memory we will need if this is new */ 00901 len = sizeof(*gi) + strlen(group) + 1; 00902 if (!ast_strlen_zero(category)) 00903 len += strlen(category) + 1; 00904 00905 AST_RWLIST_WRLOCK(&groups); 00906 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) { 00907 if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) { 00908 AST_RWLIST_REMOVE_CURRENT(group_list); 00909 free(gi); 00910 break; 00911 } 00912 } 00913 AST_RWLIST_TRAVERSE_SAFE_END; 00914 00915 if (ast_strlen_zero(group)) { 00916 /* Enable unsetting the group */ 00917 } else if ((gi = calloc(1, len))) { 00918 gi->chan = chan; 00919 gi->group = (char *) gi + sizeof(*gi); 00920 strcpy(gi->group, group); 00921 if (!ast_strlen_zero(category)) { 00922 gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1; 00923 strcpy(gi->category, category); 00924 } 00925 AST_RWLIST_INSERT_TAIL(&groups, gi, group_list); 00926 } else { 00927 res = -1; 00928 } 00929 00930 AST_RWLIST_UNLOCK(&groups); 00931 00932 return res; 00933 }
| 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 863 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().
00864 { 00865 int res = 0; 00866 char tmp[256]; 00867 char *grp = NULL, *cat = NULL; 00868 00869 if (!ast_strlen_zero(data)) { 00870 ast_copy_string(tmp, data, sizeof(tmp)); 00871 grp = tmp; 00872 cat = strchr(tmp, '@'); 00873 if (cat) { 00874 *cat = '\0'; 00875 cat++; 00876 } 00877 } 00878 00879 if (!ast_strlen_zero(grp)) 00880 ast_copy_string(group, grp, group_max); 00881 else 00882 *group = '\0'; 00883 00884 if (!ast_strlen_zero(cat)) 00885 ast_copy_string(category, cat, category_max); 00886 00887 return res; 00888 }
| int ast_app_group_update | ( | struct ast_channel * | old, | |
| struct ast_channel * | new | |||
| ) |
Update all group counting for a channel to a new one.
Definition at line 978 of file app.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_group_info::chan, and ast_group_info::group_list.
Referenced by ast_do_masquerade(), and check_bridge().
00979 { 00980 struct ast_group_info *gi = NULL; 00981 00982 AST_RWLIST_WRLOCK(&groups); 00983 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) { 00984 if (gi->chan == old) { 00985 gi->chan = new; 00986 } else if (gi->chan == new) { 00987 AST_RWLIST_REMOVE_CURRENT(group_list); 00988 ast_free(gi); 00989 } 00990 } 00991 AST_RWLIST_TRAVERSE_SAFE_END 00992 AST_RWLIST_UNLOCK(&groups); 00993 00994 return 0; 00995 }
| int ast_app_has_voicemail | ( | const char * | mailbox, | |
| const char * | folder | |||
| ) |
Determine if a given mailbox has any voicemail.
Definition at line 202 of file app.c.
References ast_has_voicemail_func, and ast_verb.
Referenced by action_mailboxstatus(), has_voicemail(), notify_new_message(), play_dialtone(), poll_mailbox(), and run_externnotify().
00203 { 00204 static int warned = 0; 00205 if (ast_has_voicemail_func) 00206 return ast_has_voicemail_func(mailbox, folder); 00207 00208 if (!warned) { 00209 ast_verb(3, "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX"); 00210 warned++; 00211 } 00212 return 0; 00213 }
| int ast_app_inboxcount | ( | const char * | mailbox, | |
| int * | newmsgs, | |||
| int * | oldmsgs | |||
| ) |
Determine number of new/old messages in a mailbox.
Definition at line 216 of file app.c.
References ast_inboxcount_func, and ast_verb.
Referenced by action_mailboxcount(), notify_new_message(), sip_send_mwi_to_peer(), unistim_send_mwi_to_peer(), update_registry(), and vm_execmain().
00217 { 00218 static int warned = 0; 00219 if (newmsgs) 00220 *newmsgs = 0; 00221 if (oldmsgs) 00222 *oldmsgs = 0; 00223 if (ast_inboxcount_func) 00224 return ast_inboxcount_func(mailbox, newmsgs, oldmsgs); 00225 00226 if (!warned) { 00227 warned++; 00228 ast_verb(3, "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox); 00229 } 00230 00231 return 0; 00232 }
| 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 234 of file app.c.
References ast_messagecount_func, and ast_verb.
Referenced by acf_vmcount_exec().
00235 { 00236 static int warned = 0; 00237 if (ast_messagecount_func) 00238 return ast_messagecount_func(context, mailbox, folder); 00239 00240 if (!warned) { 00241 warned++; 00242 ast_verb(3, "Message count requested for mailbox %s@%s/%s but voicemail not loaded.\n", mailbox, context, folder); 00243 } 00244 00245 return 0; 00246 }
| void ast_app_options2str64 | ( | const struct ast_app_option * | options, | |
| struct ast_flags64 * | 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 1723 of file app.c.
References ast_test_flag64.
01724 { 01725 unsigned int i, found = 0; 01726 for (i = 32; i < 128 && found < len; i++) { 01727 if (ast_test_flag64(flags, options[i].flag)) { 01728 buf[found++] = i; 01729 } 01730 } 01731 buf[found] = '\0'; 01732 }
| 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 1647 of file app.c.
References ast_app_option::arg_index, ast_clear_flag, AST_FLAGS_ALL, ast_log(), ast_set_flag, LOG_WARNING, and s.
Referenced by app_exec(), auth_exec(), bridge_exec(), cdr_read(), cdr_write(), chanspy_exec(), conf_exec(), controlplayback_exec(), directory_exec(), disa_exec(), dundi_query_read(), dundifunc_read(), extenspy_exec(), forkcdr_exec(), handle_options(), hint_read(), minivm_accmess_exec(), minivm_greet_exec(), minivm_record_exec(), mixmonitor_exec(), page_exec(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_waitexten(), read_exec(), readexten_exec(), record_exec(), sendurl_exec(), sla_trunk_exec(), sms_exec(), softhangup_exec(), speech_background(), vm_exec(), and vm_execmain().
01648 { 01649 char *s, *arg; 01650 int curarg, res = 0; 01651 unsigned int argloc; 01652 01653 ast_clear_flag(flags, AST_FLAGS_ALL); 01654 01655 if (!optstr) 01656 return 0; 01657 01658 s = optstr; 01659 while (*s) { 01660 curarg = *s++ & 0x7f; /* the array (in app.h) has 128 entries */ 01661 argloc = options[curarg].arg_index; 01662 if (*s == '(') { 01663 /* Has argument */ 01664 arg = ++s; 01665 if ((s = strchr(s, ')'))) { 01666 if (argloc) 01667 args[argloc - 1] = arg; 01668 *s++ = '\0'; 01669 } else { 01670 ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg); 01671 res = -1; 01672 break; 01673 } 01674 } else if (argloc) { 01675 args[argloc - 1] = ""; 01676 } 01677 ast_set_flag(flags, options[curarg].flag); 01678 } 01679 01680 return res; 01681 }
| int ast_app_parse_options64 | ( | const struct ast_app_option * | options, | |
| struct ast_flags64 * | 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 64-bit 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 1687 of file app.c.
References ast_app_option::arg_index, ast_log(), ast_set_flag64, ast_flags64::flags, LOG_WARNING, and s.
Referenced by dial_exec_full().
01688 { 01689 char *s, *arg; 01690 int curarg, res = 0; 01691 unsigned int argloc; 01692 01693 flags->flags = 0; 01694 01695 if (!optstr) 01696 return 0; 01697 01698 s = optstr; 01699 while (*s) { 01700 curarg = *s++ & 0x7f; /* the array (in app.h) has 128 entries */ 01701 ast_set_flag64(flags, options[curarg].flag); 01702 argloc = options[curarg].arg_index; 01703 if (*s == '(') { 01704 /* Has argument */ 01705 arg = ++s; 01706 if ((s = strchr(s, ')'))) { 01707 if (argloc) 01708 args[argloc - 1] = arg; 01709 *s++ = '\0'; 01710 } else { 01711 ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg); 01712 res = -1; 01713 break; 01714 } 01715 } else if (argloc) { 01716 args[argloc - 1] = NULL; 01717 } 01718 } 01719 01720 return res; 01721 }
| unsigned int ast_app_separate_args | ( | char * | buf, | |
| char | delim, | |||
| char ** | array, | |||
| int | arraylen | |||
| ) |
Definition at line 1090 of file app.c.
References __ast_app_separate_args().
01091 { 01092 return __ast_app_separate_args(buf, delim, 1, array, arraylen); 01093 }
| 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, | |||
| long * | offsetms | |||
| ) |
Stream a file with fast forward, pause, reverse, restart.
| chan | ||
| file | filename | |
| fwd,rev,stop,pause,restart,skipms,offsetms |
Definition at line 415 of file app.c.
References ast_channel::_state, ast_answer(), ast_debug, ast_seekstream(), AST_STATE_UP, ast_stopstream(), ast_streamfile(), ast_tellstream(), ast_verb, ast_waitfordigit(), ast_waitstream_fr(), ast_channel::language, and ast_channel::stream.
Referenced by controlplayback_exec(), handle_controlstreamfile(), and wait_file().
00419 { 00420 char *breaks = NULL; 00421 char *end = NULL; 00422 int blen = 2; 00423 int res; 00424 long pause_restart_point = 0; 00425 long offset = 0; 00426 00427 if (offsetms) 00428 offset = *offsetms * 8; /* XXX Assumes 8kHz */ 00429 00430 if (stop) 00431 blen += strlen(stop); 00432 if (pause) 00433 blen += strlen(pause); 00434 if (restart) 00435 blen += strlen(restart); 00436 00437 if (blen > 2) { 00438 breaks = alloca(blen + 1); 00439 breaks[0] = '\0'; 00440 if (stop) 00441 strcat(breaks, stop); 00442 if (pause) 00443 strcat(breaks, pause); 00444 if (restart) 00445 strcat(breaks, restart); 00446 } 00447 if (chan->_state != AST_STATE_UP) 00448 res = ast_answer(chan); 00449 00450 if (file) { 00451 if ((end = strchr(file, ':'))) { 00452 if (!strcasecmp(end, ":end")) { 00453 *end = '\0'; 00454 end++; 00455 } 00456 } 00457 } 00458 00459 for (;;) { 00460 ast_stopstream(chan); 00461 res = ast_streamfile(chan, file, chan->language); 00462 if (!res) { 00463 if (pause_restart_point) { 00464 ast_seekstream(chan->stream, pause_restart_point, SEEK_SET); 00465 pause_restart_point = 0; 00466 } 00467 else if (end || offset < 0) { 00468 if (offset == -8) 00469 offset = 0; 00470 ast_verb(3, "ControlPlayback seek to offset %ld from end\n", offset); 00471 00472 ast_seekstream(chan->stream, offset, SEEK_END); 00473 end = NULL; 00474 offset = 0; 00475 } else if (offset) { 00476 ast_verb(3, "ControlPlayback seek to offset %ld\n", offset); 00477 ast_seekstream(chan->stream, offset, SEEK_SET); 00478 offset = 0; 00479 }; 00480 res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms); 00481 } 00482 00483 if (res < 1) 00484 break; 00485 00486 /* We go at next loop if we got the restart char */ 00487 if (restart && strchr(restart, res)) { 00488 ast_debug(1, "we'll restart the stream here at next loop\n"); 00489 pause_restart_point = 0; 00490 continue; 00491 } 00492 00493 if (pause && strchr(pause, res)) { 00494 pause_restart_point = ast_tellstream(chan->stream); 00495 for (;;) { 00496 ast_stopstream(chan); 00497 res = ast_waitfordigit(chan, 1000); 00498 if (!res) 00499 continue; 00500 else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res))) 00501 break; 00502 } 00503 if (res == *pause) { 00504 res = 0; 00505 continue; 00506 } 00507 } 00508 00509 if (res == -1) 00510 break; 00511 00512 /* if we get one of our stop chars, return it to the calling function */ 00513 if (stop && strchr(stop, res)) 00514 break; 00515 } 00516 00517 if (pause_restart_point) { 00518 offset = pause_restart_point; 00519 } else { 00520 if (chan->stream) { 00521 offset = ast_tellstream(chan->stream); 00522 } else { 00523 offset = -8; /* indicate end of file */ 00524 } 00525 } 00526 00527 if (offsetms) 00528 *offsetms = offset / 8; /* samples --> ms ... XXX Assumes 8 kHz */ 00529 00530 /* If we are returning a digit cast it as char */ 00531 if (res > 0 || chan->stream) 00532 res = (char)res; 00533 00534 ast_stopstream(chan); 00535 00536 return res; 00537 }
| int ast_dtmf_stream | ( | struct ast_channel * | chan, | |
| struct ast_channel * | peer, | |||
| const char * | digits, | |||
| int | between, | |||
| unsigned int | duration | |||
| ) |
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. | |
| duration | This is the duration that each DTMF digit should have. |
Definition at line 248 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(), dial_exec_full(), handle_cli_misdn_send_digit(), senddtmf_exec(), testclient_exec(), and testserver_exec().
00249 { 00250 const char *ptr; 00251 int res = 0; 00252 struct ast_silence_generator *silgen = NULL; 00253 00254 if (!between) 00255 between = 100; 00256 00257 if (peer) 00258 res = ast_autoservice_start(peer); 00259 00260 if (!res) 00261 res = ast_waitfor(chan, 100); 00262 00263 /* ast_waitfor will return the number of remaining ms on success */ 00264 if (res < 0) { 00265 if (peer) { 00266 ast_autoservice_stop(peer); 00267 } 00268 return res; 00269 } 00270 00271 if (ast_opt_transmit_silence) { 00272 silgen = ast_channel_start_silence_generator(chan); 00273 } 00274 00275 for (ptr = digits; *ptr; ptr++) { 00276 if (*ptr == 'w') { 00277 /* 'w' -- wait half a second */ 00278 if ((res = ast_safe_sleep(chan, 500))) 00279 break; 00280 } else if (strchr("0123456789*#abcdfABCDF", *ptr)) { 00281 /* Character represents valid DTMF */ 00282 if (*ptr == 'f' || *ptr == 'F') { 00283 /* ignore return values if not supported by channel */ 00284 ast_indicate(chan, AST_CONTROL_FLASH); 00285 } else 00286 ast_senddigit(chan, *ptr, duration); 00287 /* pause between digits */ 00288 if ((res = ast_safe_sleep(chan, between))) 00289 break; 00290 } else 00291 ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n", *ptr); 00292 } 00293 00294 if (peer) { 00295 /* Stop autoservice on the peer channel, but don't overwrite any error condition 00296 that has occurred previously while acting on the primary channel */ 00297 if (ast_autoservice_stop(peer) && !res) 00298 res = -1; 00299 } 00300 00301 if (silgen) { 00302 ast_channel_stop_silence_generator(chan, silgen); 00303 } 00304 00305 return res; 00306 }
| int ast_get_encoded_char | ( | const char * | stream, | |
| char * | result, | |||
| size_t * | consumed | |||
| ) |
Decode an encoded control or extended ASCII character.
Definition at line 1734 of file app.c.
References ast_debug, ast_log(), ast_strlen_zero(), and LOG_ERROR.
Referenced by ast_get_encoded_str(), ast_str_get_encoded_str(), cut_internal(), filter(), and function_fieldqty().
01735 { 01736 int i; 01737 *consumed = 1; 01738 *result = 0; 01739 if (ast_strlen_zero(stream)) { 01740 *consumed = 0; 01741 return -1; 01742 } 01743 01744 if (*stream == '\\') { 01745 *consumed = 2; 01746 switch (*(stream + 1)) { 01747 case 'n': 01748 *result = '\n'; 01749 break; 01750 case 'r': 01751 *result = '\r'; 01752 break; 01753 case 't': 01754 *result = '\t'; 01755 break; 01756 case 'x': 01757 /* Hexadecimal */ 01758 if (strchr("0123456789ABCDEFabcdef", *(stream + 2)) && *(stream + 2) != '\0') { 01759 *consumed = 3; 01760 if (*(stream + 2) <= '9') 01761 *result = *(stream + 2) - '0'; 01762 else if (*(stream + 2) <= 'F') 01763 *result = *(stream + 2) - 'A' + 10; 01764 else 01765 *result = *(stream + 2) - 'a' + 10; 01766 } else { 01767 ast_log(LOG_ERROR, "Illegal character '%c' in hexadecimal string\n", *(stream + 2)); 01768 return -1; 01769 } 01770 01771 if (strchr("0123456789ABCDEFabcdef", *(stream + 3)) && *(stream + 3) != '\0') { 01772 *consumed = 4; 01773 *result <<= 4; 01774 if (*(stream + 3) <= '9') 01775 *result += *(stream + 3) - '0'; 01776 else if (*(stream + 3) <= 'F') 01777 *result += *(stream + 3) - 'A' + 10; 01778 else 01779 *result += *(stream + 3) - 'a' + 10; 01780 } 01781 break; 01782 case '0': 01783 /* Octal */ 01784 *consumed = 2; 01785 for (i = 2; ; i++) { 01786 if (strchr("01234567", *(stream + i)) && *(stream + i) != '\0') { 01787 (*consumed)++; 01788 ast_debug(5, "result was %d, ", *result); 01789 *result <<= 3; 01790 *result += *(stream + i) - '0'; 01791 ast_debug(5, "is now %d\n", *result); 01792 } else 01793 break; 01794 } 01795 break; 01796 default: 01797 *result = *(stream + 1); 01798 } 01799 } else { 01800 *result = *stream; 01801 *consumed = 1; 01802 } 01803 return 0; 01804 }
| int ast_get_encoded_str | ( | const char * | stream, | |
| char * | result, | |||
| size_t | result_size | |||
| ) |
Decode a string which may contain multiple encoded control or extended ASCII characters.
Definition at line 1806 of file app.c.
References ast_get_encoded_char().
Referenced by sip_addheader().
01807 { 01808 char *cur = result; 01809 size_t consumed; 01810 01811 while (cur < result + result_size - 1 && !ast_get_encoded_char(stream, cur, &consumed)) { 01812 cur++; 01813 stream += consumed; 01814 } 01815 *cur = '\0'; 01816 return 0; 01817 }
| 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 186 of file app.c.
References ast_has_voicemail_func, ast_inboxcount_func, and ast_messagecount_func.
Referenced by load_module().
00189 { 00190 ast_has_voicemail_func = has_voicemail_func; 00191 ast_inboxcount_func = inboxcount_func; 00192 ast_messagecount_func = messagecount_func; 00193 }
| int ast_ivr_menu_run | ( | struct ast_channel * | c, | |
| struct ast_ivr_menu * | menu, | |||
| void * | cbdata | |||
| ) |
Runs an IVR menu.
Definition at line 1606 of file app.c.
References ast_ivr_menu_run_internal().
Referenced by skel_exec().
01607 { 01608 int res = ast_ivr_menu_run_internal(chan, menu, cbdata); 01609 /* Hide internal coding */ 01610 return res > 0 ? 0 : res; 01611 }
| static int ast_ivr_menu_run_internal | ( | struct ast_channel * | chan, | |
| struct ast_ivr_menu * | menu, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 1526 of file app.c.
References ast_debug, AST_DIGIT_ANY, ast_log(), AST_MAX_EXTENSION, exten, ivr_dispatch(), LOG_WARNING, maxretries, ast_ivr_option::option, option_exists(), ast_ivr_menu::options, read_newoption(), RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, and ast_ivr_menu::title.
Referenced by ast_ivr_menu_run(), and ivr_dispatch().
01527 { 01528 /* Execute an IVR menu structure */ 01529 int res = 0; 01530 int pos = 0; 01531 int retries = 0; 01532 char exten[AST_MAX_EXTENSION] = "s"; 01533 if (option_exists(menu, "s") < 0) { 01534 strcpy(exten, "g"); 01535 if (option_exists(menu, "g") < 0) { 01536 ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title); 01537 return -1; 01538 } 01539 } 01540 while (!res) { 01541 while (menu->options[pos].option) { 01542 if (!strcasecmp(menu->options[pos].option, exten)) { 01543 res = ivr_dispatch(chan, menu->options + pos, exten, cbdata); 01544 ast_debug(1, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res); 01545 if (res < 0) 01546 break; 01547 else if (res & RES_UPONE) 01548 return 0; 01549 else if (res & RES_EXIT) 01550 return res; 01551 else if (res & RES_REPEAT) { 01552 int maxretries = res & 0xffff; 01553 if ((res & RES_RESTART) == RES_RESTART) { 01554 retries = 0; 01555 } else 01556 retries++; 01557 if (!maxretries) 01558 maxretries = 3; 01559 if ((maxretries > 0) && (retries >= maxretries)) { 01560 ast_debug(1, "Max retries %d exceeded\n", maxretries); 01561 return -2; 01562 } else { 01563 if (option_exists(menu, "g") > -1) 01564 strcpy(exten, "g"); 01565 else if (option_exists(menu, "s") > -1) 01566 strcpy(exten, "s"); 01567 } 01568 pos = 0; 01569 continue; 01570 } else if (res && strchr(AST_DIGIT_ANY, res)) { 01571 ast_debug(1, "Got start of extension, %c\n", res); 01572 exten[1] = '\0'; 01573 exten[0] = res; 01574 if ((res = read_newoption(chan, menu, exten, sizeof(exten)))) 01575 break; 01576 if (option_exists(menu, exten) < 0) { 01577 if (option_exists(menu, "i")) { 01578 ast_debug(1, "Invalid extension entered, going to 'i'!\n"); 01579 strcpy(exten, "i"); 01580 pos = 0; 01581 continue; 01582 } else { 01583 ast_debug(1, "Aborting on invalid entry, with no 'i' option!\n"); 01584 res = -2; 01585 break; 01586 } 01587 } else { 01588 ast_debug(1, "New existing extension: %s\n", exten); 01589 pos = 0; 01590 continue; 01591 } 01592 } 01593 } 01594 pos++; 01595 } 01596 ast_debug(1, "Stopping option '%s', res is %d\n", exten, res); 01597 pos = 0; 01598 if (!strcasecmp(exten, "s")) 01599 strcpy(exten, "g"); 01600 else 01601 break; 01602 } 01603 return res; 01604 }
| 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 387 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.
00388 { 00389 struct linear_state *lin; 00390 char tmpf[256]; 00391 int res = -1; 00392 int autoclose = 0; 00393 if (fd < 0) { 00394 if (ast_strlen_zero(filename)) 00395 return -1; 00396 autoclose = 1; 00397 if (filename[0] == '/') 00398 ast_copy_string(tmpf, filename, sizeof(tmpf)); 00399 else 00400 snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", ast_config_AST_DATA_DIR, "sounds", filename); 00401 if ((fd = open(tmpf, O_RDONLY)) < 0) { 00402 ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno)); 00403 return -1; 00404 } 00405 } 00406 if ((lin = ast_calloc(1, sizeof(*lin)))) { 00407 lin->fd = fd; 00408 lin->allowoverride = allowoverride; 00409 lin->autoclose = autoclose; 00410 res = ast_activate_generator(chan, &linearstream, lin); 00411 } 00412 return res; 00413 }
| enum AST_LOCK_RESULT ast_lock_path | ( | const char * | path | ) |
Lock a filesystem path.
| path | the path to be locked |
Definition at line 1287 of file app.c.
References AST_LOCK_FAILURE, ast_lock_path_flock(), ast_lock_path_lockfile(), AST_LOCK_TYPE_FLOCK, and AST_LOCK_TYPE_LOCKFILE.
Referenced by vm_lock_path().
01288 { 01289 enum AST_LOCK_RESULT r = AST_LOCK_FAILURE; 01290 01291 switch (ast_lock_type) { 01292 case AST_LOCK_TYPE_LOCKFILE: 01293 r = ast_lock_path_lockfile(path); 01294 break; 01295 case AST_LOCK_TYPE_FLOCK: 01296 r = ast_lock_path_flock(path); 01297 break; 01298 } 01299 01300 return r; 01301 }
| static enum AST_LOCK_RESULT ast_lock_path_flock | ( | const char * | path | ) | [static] |
Definition at line 1166 of file app.c.
References ast_calloc, ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_LOCK_FAILURE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), errno, path_lock::fd, path_lock::le, LOG_WARNING, path_lock::path, path_lock_destroy(), and strdup.
Referenced by ast_lock_path().
01167 { 01168 char *fs; 01169 int res; 01170 int fd; 01171 time_t start; 01172 struct path_lock *pl; 01173 struct stat st, ost; 01174 01175 fs = alloca(strlen(path) + 20); 01176 01177 snprintf(fs, strlen(path) + 19, "%s/lock", path); 01178 if (lstat(fs, &st) == 0) { 01179 if ((st.st_mode & S_IFMT) == S_IFLNK) { 01180 ast_log(LOG_WARNING, "Unable to create lock file " 01181 "'%s': it's already a symbolic link\n", 01182 fs); 01183 return AST_LOCK_FAILURE; 01184 } 01185 if (st.st_nlink > 1) { 01186 ast_log(LOG_WARNING, "Unable to create lock file " 01187 "'%s': %u hard links exist\n", 01188 fs, (unsigned int) st.st_nlink); 01189 return AST_LOCK_FAILURE; 01190 } 01191 } 01192 fd = open(fs, O_WRONLY | O_CREAT, 0600); 01193 if (fd < 0) { 01194 ast_log(LOG_WARNING, "Unable to create lock file '%s': %s\n", 01195 fs, strerror(errno)); 01196 return AST_LOCK_PATH_NOT_FOUND; 01197 } 01198 pl = ast_calloc(1, sizeof(*pl)); 01199 if (!pl) { 01200 /* We don't unlink the lock file here, on the possibility that 01201 * someone else created it - better to leave a little mess 01202 * than create a big one by destroying someone else's lock 01203 * and causing something to be corrupted. 01204 */ 01205 close(fd); 01206 return AST_LOCK_FAILURE; 01207 } 01208 pl->fd = fd; 01209 pl->path = strdup(path); 01210 01211 time(&start); 01212 while (( 01213 #ifdef SOLARIS 01214 (res = fcntl(pl->fd, F_SETLK, fcntl(pl->fd, F_GETFL) | O_NONBLOCK)) < 0) && 01215 #else 01216 (res = flock(pl->fd, LOCK_EX | LOCK_NB)) < 0) && 01217 #endif 01218 (errno == EWOULDBLOCK) && 01219 (time(NULL) - start < 5)) 01220 usleep(1000); 01221 if (res) { 01222 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", 01223 path, strerror(errno)); 01224 /* No unlinking of lock done, since we tried and failed to 01225 * flock() it. 01226 */ 01227 path_lock_destroy(pl); 01228 return AST_LOCK_TIMEOUT; 01229 } 01230 01231 /* Check for the race where the file is recreated or deleted out from 01232 * underneath us. 01233 */ 01234 if (lstat(fs, &st) != 0 && fstat(pl->fd, &ost) != 0 && 01235 st.st_dev != ost.st_dev && 01236 st.st_ino != ost.st_ino) { 01237 ast_log(LOG_WARNING, "Unable to create lock file '%s': " 01238 "file changed underneath us\n", fs); 01239 path_lock_destroy(pl); 01240 return AST_LOCK_FAILURE; 01241 } 01242 01243 /* Success: file created, flocked, and is the one we started with */ 01244 AST_LIST_LOCK(&path_lock_list); 01245 AST_LIST_INSERT_TAIL(&path_lock_list, pl, le); 01246 AST_LIST_UNLOCK(&path_lock_list); 01247 01248 ast_debug(1, "Locked path '%s'\n", path); 01249 01250 return AST_LOCK_SUCCESS; 01251 }
| static enum AST_LOCK_RESULT ast_lock_path_lockfile | ( | const char * | path | ) | [static] |
Definition at line 1095 of file app.c.
References ast_debug, AST_FILE_MODE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), ast_random(), errno, LOG_ERROR, LOG_WARNING, and s.
Referenced by ast_lock_path().
01096 { 01097 char *s; 01098 char *fs; 01099 int res; 01100 int fd; 01101 int lp = strlen(path); 01102 time_t start; 01103 01104 s = alloca(lp + 10); 01105 fs = alloca(lp + 20); 01106 01107 snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, ast_random()); 01108 fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, AST_FILE_MODE); 01109 if (fd < 0) { 01110 ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno)); 01111 return AST_LOCK_PATH_NOT_FOUND; 01112 } 01113 close(fd); 01114 01115 snprintf(s, strlen(path) + 9, "%s/.lock", path); 01116 start = time(NULL); 01117 while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) 01118 usleep(1); 01119 01120 unlink(fs); 01121 01122 if (res) { 01123 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno)); 01124 return AST_LOCK_TIMEOUT; 01125 } else { 01126 ast_debug(1, "Locked path '%s'\n", path); 01127 return AST_LOCK_SUCCESS; 01128 } 01129 }
| 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 | |||
| ) |
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 856 of file app.c.
References __ast_play_and_record().
Referenced by vm_forwardoptions().
00857 { 00858 return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf); 00859 }
| 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 | |||
| ) |
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 851 of file app.c.
References __ast_play_and_record().
Referenced by app_exec(), ast_record_review(), conf_run(), and setup_privacy_args().
00852 { 00853 return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf); 00854 }
| 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 846 of file app.c.
References __ast_play_and_record(), and S_OR.
Referenced by play_record_review().
00847 { 00848 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)); 00849 }
| 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 539 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(), minivm_greet_exec(), play_message_category(), play_message_duration(), play_record_review(), vm_authenticate(), vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_browse_messages_zh(), vm_execmain(), vm_forwardoptions(), vm_instructions_en(), vm_instructions_zh(), vm_intro(), vm_intro_cz(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_gr(), 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_intro_zh(), 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().
00540 { 00541 int d = 0; 00542 00543 if ((d = ast_streamfile(chan, fn, chan->language))) 00544 return d; 00545 00546 d = ast_waitstream(chan, AST_DIGIT_ANY); 00547 00548 ast_stopstream(chan); 00549 00550 return d; 00551 }
| char* ast_read_textfile | ( | const char * | filename | ) |
Read a file into asterisk.
Definition at line 1613 of file app.c.
References ast_free, ast_log(), ast_malloc, errno, path_lock::fd, and LOG_WARNING.
Referenced by file_read(), and readfile_exec().
01614 { 01615 int fd, count = 0, res; 01616 char *output = NULL; 01617 struct stat filesize; 01618 01619 if (stat(filename, &filesize) == -1) { 01620 ast_log(LOG_WARNING, "Error can't stat %s\n", filename); 01621 return NULL; 01622 } 01623 01624 count = filesize.st_size + 1; 01625 01626 if ((fd = open(filename, O_RDONLY)) < 0) { 01627 ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno)); 01628 return NULL; 01629 } 01630 01631 if ((output = ast_malloc(count))) { 01632 res = read(fd, output, count - 1); 01633 if (res == count - 1) { 01634 output[res] = '\0'; 01635 } else { 01636 ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno)); 01637 ast_free(output); 01638 output = NULL; 01639 } 01640 } 01641 01642 close(fd); 01643 01644 return output; 01645 }
| 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 1319 of file app.c.
References AST_DIGIT_ANY, ast_log(), ast_play_and_record(), ast_play_and_wait(), ast_stream_and_wait(), ast_verb, ast_waitfordigit(), LOG_WARNING, maxsilence, and silencethreshold.
Referenced by conf_run().
01320 { 01321 int silencethreshold = 128; 01322 int maxsilence = 0; 01323 int res = 0; 01324 int cmd = 0; 01325 int max_attempts = 3; 01326 int attempts = 0; 01327 int recorded = 0; 01328 int message_exists = 0; 01329 /* Note that urgent and private are for flagging messages as such in the future */ 01330 01331 /* barf if no pointer passed to store duration in */ 01332 if (!duration) { 01333 ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n"); 01334 return -1; 01335 } 01336 01337 cmd = '3'; /* Want to start by recording */ 01338 01339 while ((cmd >= 0) && (cmd != 't')) { 01340 switch (cmd) { 01341 case '1': 01342 if (!message_exists) { 01343 /* In this case, 1 is to record a message */ 01344 cmd = '3'; 01345 break; 01346 } else { 01347 ast_stream_and_wait(chan, "vm-msgsaved", ""); 01348 cmd = 't'; 01349 return res; 01350 } 01351 case '2': 01352 /* Review */ 01353 ast_verb(3, "Reviewing the recording\n"); 01354 cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY); 01355 break; 01356 case '3': 01357 message_exists = 0; 01358 /* Record */ 01359 if (recorded == 1) 01360 ast_verb(3, "Re-recording\n"); 01361 else 01362 ast_verb(3, "Recording\n"); 01363 recorded = 1; 01364 cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path); 01365 if (cmd == -1) { 01366 /* User has hung up, no options to give */ 01367 return cmd; 01368 } 01369 if (cmd == '0') { 01370 break; 01371 } else if (cmd == '*') { 01372 break; 01373 } 01374 else { 01375 /* If all is well, a message exists */ 01376 message_exists = 1; 01377 cmd = 0; 01378 } 01379 break; 01380 case '4': 01381 case '5': 01382 case '6': 01383 case '7': 01384 case '8': 01385 case '9': 01386 case '*': 01387 case '#': 01388 cmd = ast_play_and_wait(chan, "vm-sorry"); 01389 break; 01390 default: 01391 if (message_exists) { 01392 cmd = ast_play_and_wait(chan, "vm-review"); 01393 } 01394 else { 01395 cmd = ast_play_and_wait(chan, "vm-torerecord"); 01396 if (!cmd) 01397 cmd = ast_waitfordigit(chan, 600); 01398 } 01399 01400 if (!cmd) 01401 cmd = ast_waitfordigit(chan, 6000); 01402 if (!cmd) { 01403 attempts++; 01404 } 01405 if (attempts > max_attempts) { 01406 cmd = 't'; 01407 } 01408 } 01409 } 01410 if (cmd == 't') 01411 cmd = 0; 01412 return cmd; 01413 }
| void ast_set_lock_type | ( | enum AST_LOCK_TYPE | type | ) |
Set the type of locks used by ast_lock_path().
| type | the locking type to use |
Definition at line 1282 of file app.c.
Referenced by ast_readconfig().
01283 { 01284 ast_lock_type = type; 01285 }
| int ast_str_get_encoded_str | ( | struct ast_str ** | str, | |
| int | maxlen, | |||
| const char * | stream | |||
| ) |
Decode a stream of encoded control or extended ASCII characters.
Definition at line 1819 of file app.c.
References ast_get_encoded_char(), ast_str_buffer, ast_str_make_space(), ast_str_set(), ast_str_size, ast_str_update, buf, and path_lock::next.
Referenced by system_exec_helper().
01820 { 01821 char next, *buf; 01822 size_t offset = 0; 01823 size_t consumed; 01824 01825 if (strchr(stream, '\\')) { 01826 while (!ast_get_encoded_char(stream, &next, &consumed)) { 01827 if (offset + 2 > ast_str_size(*str) && maxlen > -1) { 01828 ast_str_make_space(str, maxlen > 0 ? maxlen : (ast_str_size(*str) + 48) * 2 - 48); 01829 } 01830 if (offset + 2 > ast_str_size(*str)) { 01831 break; 01832 } 01833 buf = ast_str_buffer(*str); 01834 buf[offset++] = next; 01835 stream += consumed; 01836 } 01837 buf = ast_str_buffer(*str); 01838 buf[offset++] = '\0'; 01839 ast_str_update(*str); 01840 } else { 01841 ast_str_set(str, maxlen, "%s", stream); 01842 } 01843 return 0; 01844 }
| void ast_uninstall_vm_functions | ( | void | ) |
Definition at line 195 of file app.c.
References ast_has_voicemail_func, ast_inboxcount_func, and ast_messagecount_func.
Referenced by unload_module().
00196 { 00197 ast_has_voicemail_func = NULL; 00198 ast_inboxcount_func = NULL; 00199 ast_messagecount_func = NULL; 00200 }
| int ast_unlock_path | ( | const char * | path | ) |
Unlock a path.
Definition at line 1303 of file app.c.
References AST_LOCK_TYPE_FLOCK, AST_LOCK_TYPE_LOCKFILE, ast_unlock_path_flock(), and ast_unlock_path_lockfile().
Referenced by __ast_play_and_record(), access_counter_file(), close_mailbox(), copy_message(), count_messages(), leave_voicemail(), open_mailbox(), resequence_mailbox(), and save_to_folder().
01304 { 01305 int r = 0; 01306 01307 switch (ast_lock_type) { 01308 case AST_LOCK_TYPE_LOCKFILE: 01309 r = ast_unlock_path_lockfile(path); 01310 break; 01311 case AST_LOCK_TYPE_FLOCK: 01312 r = ast_unlock_path_flock(path); 01313 break; 01314 } 01315 01316 return r; 01317 }
| static int ast_unlock_path_flock | ( | const char * | path | ) | [static] |
Definition at line 1253 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_log(), path_lock::le, LOG_DEBUG, path_lock::path, path_lock_destroy(), and s.
Referenced by ast_unlock_path().
01254 { 01255 char *s; 01256 struct path_lock *p; 01257 01258 s = alloca(strlen(path) + 20); 01259 01260 AST_LIST_LOCK(&path_lock_list); 01261 AST_LIST_TRAVERSE_SAFE_BEGIN(&path_lock_list, p, le) { 01262 if (!strcmp(p->path, path)) { 01263 AST_LIST_REMOVE_CURRENT(le); 01264 break; 01265 } 01266 } 01267 AST_LIST_TRAVERSE_SAFE_END; 01268 AST_LIST_UNLOCK(&path_lock_list); 01269 01270 if (p) { 01271 snprintf(s, strlen(path) + 19, "%s/lock", path); 01272 unlink(s); 01273 path_lock_destroy(p); 01274 ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path); 01275 } else 01276 ast_log(LOG_DEBUG, "Failed to unlock path '%s': " 01277 "lock not found\n", path); 01278 01279 return 0; 01280 }
| static int ast_unlock_path_lockfile | ( | const char * | path | ) | [static] |
Definition at line 1131 of file app.c.
References ast_debug, ast_log(), errno, LOG_ERROR, and s.
Referenced by ast_unlock_path().
01132 { 01133 char *s; 01134 int res; 01135 01136 s = alloca(strlen(path) + 10); 01137 01138 snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock"); 01139 01140 if ((res = unlink(s))) 01141 ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno)); 01142 else { 01143 ast_debug(1, "Unlocked path '%s'\n", path); 01144 } 01145 01146 return res; 01147 }
| static int ivr_dispatch | ( | struct ast_channel * | chan, | |
| struct ast_ivr_option * | option, | |||
| char * | exten, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 1422 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().
01423 { 01424 int res; 01425 int (*ivr_func)(struct ast_channel *, void *); 01426 char *c; 01427 char *n; 01428 01429 switch (option->action) { 01430 case AST_ACTION_UPONE: 01431 return RES_UPONE; 01432 case AST_ACTION_EXIT: 01433 return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff); 01434 case AST_ACTION_REPEAT: 01435 return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff); 01436 case AST_ACTION_RESTART: 01437 return RES_RESTART ; 01438 case AST_ACTION_NOOP: 01439 return 0; 01440 case AST_ACTION_BACKGROUND: 01441 res = ast_stream_and_wait(chan, (char *)option->adata, AST_DIGIT_ANY); 01442 if (res < 0) { 01443 ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata); 01444 res = 0; 01445 } 01446 return res; 01447 case AST_ACTION_PLAYBACK: 01448 res = ast_stream_and_wait(chan, (char *)option->adata, ""); 01449 if (res < 0) { 01450 ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata); 01451 res = 0; 01452 } 01453 return res; 01454 case AST_ACTION_MENU: 01455 res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata); 01456 /* Do not pass entry errors back up, treat as though it was an "UPONE" */ 01457 if (res == -2) 01458 res = 0; 01459 return res; 01460 case AST_ACTION_WAITOPTION: 01461 res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10)); 01462 if (!res) 01463 return 't'; 01464 return res; 01465 case AST_ACTION_CALLBACK: 01466 ivr_func = option->adata; 01467 res = ivr_func(chan, cbdata); 01468 return res; 01469 case AST_ACTION_TRANSFER: 01470 res = ast_parseable_goto(chan, option->adata); 01471 return 0; 01472 case AST_ACTION_PLAYLIST: 01473 case AST_ACTION_BACKLIST: 01474 res = 0; 01475 c = ast_strdupa(option->adata); 01476 while ((n = strsep(&c, ";"))) { 01477 if ((res = ast_stream_and_wait(chan, n, 01478 (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : ""))) 01479 break; 01480 } 01481 ast_stopstream(chan); 01482 return res; 01483 default: 01484 ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action); 01485 return 0; 01486 }; 01487 return -1; 01488 }
| static void* linear_alloc | ( | struct ast_channel * | chan, | |
| void * | params | |||
| ) | [static] |
Definition at line 356 of file app.c.
References linear_state::allowoverride, ast_clear_flag, AST_FLAG_WRITE_INT, AST_FORMAT_SLINEAR, ast_free, ast_log(), ast_set_flag, ast_set_write_format(), LOG_WARNING, ast_channel::name, linear_state::origwfmt, and ast_channel::writeformat.
00357 { 00358 struct linear_state *ls = params; 00359 00360 if (!params) 00361 return NULL; 00362 00363 /* In this case, params is already malloc'd */ 00364 if (ls->allowoverride) 00365 ast_set_flag(chan, AST_FLAG_WRITE_INT); 00366 else 00367 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 00368 00369 ls->origwfmt = chan->writeformat; 00370 00371 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 00372 ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name); 00373 ast_free(ls); 00374 ls = params = NULL; 00375 } 00376 00377 return params; 00378 }
| static int linear_generator | ( | struct ast_channel * | chan, | |
| void * | data, | |||
| int | len, | |||
| int | samples | |||
| ) | [static] |
Definition at line 328 of file app.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), buf, ast_frame::datalen, linear_state::fd, ast_frame::frametype, LOG_WARNING, and ast_frame::samples.
00329 { 00330 short buf[2048 + AST_FRIENDLY_OFFSET / 2]; 00331 struct linear_state *ls = data; 00332 struct ast_frame f = { 00333 .frametype = AST_FRAME_VOICE, 00334 .subclass = AST_FORMAT_SLINEAR, 00335 .data = buf + AST_FRIENDLY_OFFSET / 2, 00336 .offset = AST_FRIENDLY_OFFSET, 00337 }; 00338 int res; 00339 00340 len = samples * 2; 00341 if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) { 00342 ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" , len); 00343 len = sizeof(buf) - AST_FRIENDLY_OFFSET; 00344 } 00345 res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len); 00346 if (res > 0) { 00347 f.datalen = res; 00348 f.samples = res / 2; 00349 ast_write(chan, &f); 00350 if (res == len) 00351 return 0; 00352 } 00353 return -1; 00354 }
| static void linear_release | ( | struct ast_channel * | chan, | |
| void * | params | |||
| ) | [static] |
Definition at line 315 of file app.c.
References ast_free, ast_log(), ast_set_write_format(), linear_state::autoclose, linear_state::fd, LOG_WARNING, ast_channel::name, and linear_state::origwfmt.
00316 { 00317 struct linear_state *ls = params; 00318 00319 if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) 00320 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt); 00321 00322 if (ls->autoclose) 00323 close(ls->fd); 00324 00325 ast_free(params); 00326 }
| static int option_exists | ( | struct ast_ivr_menu * | menu, | |
| char * | option | |||
| ) | [static] |
Definition at line 1490 of file app.c.
References ast_ivr_option::option, and ast_ivr_menu::options.
Referenced by ast_ivr_menu_run_internal().
01491 { 01492 int x; 01493 for (x = 0; menu->options[x].option; x++) 01494 if (!strcasecmp(menu->options[x].option, option)) 01495 return x; 01496 return -1; 01497 }
| static int option_matchmore | ( | struct ast_ivr_menu * | menu, | |
| char * | option | |||
| ) | [static] |
Definition at line 1499 of file app.c.
References ast_ivr_option::option, and ast_ivr_menu::options.
Referenced by read_newoption().
01500 { 01501 int x; 01502 for (x = 0; menu->options[x].option; x++) 01503 if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 01504 (menu->options[x].option[strlen(option)])) 01505 return x; 01506 return -1; 01507 }
| static void path_lock_destroy | ( | struct path_lock * | obj | ) | [static] |
| static int read_newoption | ( | struct ast_channel * | chan, | |
| struct ast_ivr_menu * | menu, | |||
| char * | exten, | |||
| int | maxexten | |||
| ) | [static] |
Definition at line 1509 of file app.c.
References ast_waitfordigit(), ast_pbx::dtimeout, option_matchmore(), and ast_channel::pbx.
Referenced by ast_ivr_menu_run_internal().
01510 { 01511 int res = 0; 01512 int ms; 01513 while (option_matchmore(menu, exten)) { 01514 ms = chan->pbx ? chan->pbx->dtimeout : 5000; 01515 if (strlen(exten) >= maxexten - 1) 01516 break; 01517 res = ast_waitfordigit(chan, ms); 01518 if (res < 1) 01519 break; 01520 exten[strlen(exten) + 1] = '\0'; 01521 exten[strlen(exten)] = res; 01522 } 01523 return res > 0 ? 0 : res; 01524 }
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().
enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE [static] |
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] |
Definition at line 554 of file app.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and play_record_review().
int global_silence_threshold = 128 [static] |
struct ast_generator linearstream [static] |
1.5.6