Generic File Format Support. More...
#include "asterisk.h"
#include <dirent.h>
#include <sys/stat.h>
#include <math.h>
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include "asterisk/mod_format.h"
#include "asterisk/cli.h"
#include "asterisk/channel.h"
#include "asterisk/sched.h"
#include "asterisk/translate.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
struct | formats |
Defines | |
#define | FORMAT "%-10s %-10s %-20s\n" |
#define | FORMAT2 "%-10s %-10s %-20s\n" |
Enumerations | |
enum | file_action { ACTION_EXISTS = 1, ACTION_DELETE, ACTION_RENAME, ACTION_OPEN, ACTION_COPY } |
enum | fsread_res { FSREAD_FAILURE, FSREAD_SUCCESS_SCHED, FSREAD_SUCCESS_NOSCHED } |
enum | wrap_fn { WRAP_OPEN, WRAP_REWRITE } |
Functions | |
int | __ast_format_register (const struct ast_format *f, struct ast_module *mod) |
Register a new file format capability. Adds a format to Asterisk's format abilities. | |
static void | __fini_formats (void) |
static void | __init_formats (void) |
int | ast_applystream (struct ast_channel *chan, struct ast_filestream *s) |
Applys a open stream to a channel. | |
int | ast_closestream (struct ast_filestream *f) |
Closes a stream. | |
int | ast_file_init (void) |
int | ast_filecopy (const char *filename, const char *filename2, const char *fmt) |
Copies a file. | |
int | ast_filedelete (const char *filename, const char *fmt) |
Deletes a file. | |
int | ast_fileexists (const char *filename, const char *fmt, const char *preflang) |
Checks for the existence of a given file. | |
static int | ast_filehelper (const char *filename, const void *arg2, const char *fmt, const enum file_action action) |
perform various actions on a file. Second argument arg2 depends on the command: unused for EXISTS and DELETE destination file name (const char *) for COPY and RENAME struct ast_channel * for OPEN if fmt is NULL, OPEN will return the first matching entry, whereas other functions will run on all matching entries. | |
int | ast_filerename (const char *filename, const char *filename2, const char *fmt) |
Renames a file. | |
char * | ast_format_str_reduce (char *fmts) |
int | ast_format_unregister (const char *name) |
Unregisters a file format. | |
static int | ast_fsread_audio (const void *data) |
static int | ast_fsread_video (const void *data) |
struct ast_filestream * | ast_openstream (struct ast_channel *chan, const char *filename, const char *preflang) |
Opens stream for use in seeking, playing. | |
struct ast_filestream * | ast_openstream_full (struct ast_channel *chan, const char *filename, const char *preflang, int asis) |
Opens stream for use in seeking, playing. | |
struct ast_filestream * | ast_openvstream (struct ast_channel *chan, const char *filename, const char *preflang) |
Opens stream for use in seeking, playing. | |
int | ast_playstream (struct ast_filestream *s) |
Play a open stream on a channel. | |
static enum fsread_res | ast_readaudio_callback (struct ast_filestream *s) |
struct ast_filestream * | ast_readfile (const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode) |
Starts reading from a file. | |
struct ast_frame * | ast_readframe (struct ast_filestream *s) |
Read a frame from a filestream. | |
static enum fsread_res | ast_readvideo_callback (struct ast_filestream *s) |
int | ast_seekstream (struct ast_filestream *fs, off_t sample_offset, int whence) |
Seeks into stream. | |
int | ast_stopstream (struct ast_channel *tmp) |
Stops a stream. | |
int | ast_stream_and_wait (struct ast_channel *chan, const char *file, const char *digits) |
stream file until digit If the file name is non-empty, try to play it. | |
int | ast_stream_fastforward (struct ast_filestream *fs, off_t ms) |
Fast forward stream ms. | |
int | ast_stream_rewind (struct ast_filestream *fs, off_t ms) |
Rewind stream ms. | |
int | ast_streamfile (struct ast_channel *chan, const char *filename, const char *preflang) |
Streams a file. | |
off_t | ast_tellstream (struct ast_filestream *fs) |
Tell where we are in a stream. | |
int | ast_truncstream (struct ast_filestream *fs) |
Trunc stream at current location. | |
int | ast_waitstream (struct ast_channel *c, const char *breakon) |
Waits for a stream to stop or digit to be pressed. | |
int | ast_waitstream_exten (struct ast_channel *c, const char *context) |
Waits for a stream to stop or digit matching a valid one digit exten to be pressed. | |
int | ast_waitstream_fr (struct ast_channel *c, const char *breakon, const char *forward, const char *reverse, int ms) |
Same as waitstream but allows stream to be forwarded or rewound. | |
int | ast_waitstream_full (struct ast_channel *c, const char *breakon, int audiofd, int cmdfd) |
struct ast_filestream * | ast_writefile (const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode) |
Starts writing a file. | |
int | ast_writestream (struct ast_filestream *fs, struct ast_frame *f) |
Writes a frame to a stream. | |
static char * | build_filename (const char *filename, const char *ext) |
construct a filename. Absolute pathnames are preserved, relative names are prefixed by the sounds/ directory. The wav49 suffix is replaced by 'WAV'. Returns a malloc'ed string to be freed by the caller. | |
static int | copy (const char *infile, const char *outfile) |
static int | exts_compare (const char *exts, const char *type) |
static int | fileexists_core (const char *filename, const char *fmt, const char *preflang, char *buf, int buflen) |
helper routine to locate a file with a given format and language preference. Try preflang, preflang with stripped '_' suffix, or NULL. In the standard asterisk, language goes just before the last component. In an alternative configuration, the language should be a prefix to the actual filename. | |
static int | fileexists_test (const char *filename, const char *fmt, const char *lang, char *buf, int buflen) |
static void | filestream_destructor (void *arg) |
static int | fn_wrapper (struct ast_filestream *s, const char *comment, enum wrap_fn mode) |
static struct ast_filestream * | get_filestream (struct ast_format *fmt, FILE *bfile) |
static char * | handle_cli_core_show_file_formats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | is_absolute_path (const char *filename) |
static int | open_wrapper (struct ast_filestream *s) |
static struct ast_frame * | read_frame (struct ast_filestream *s, int *whennext) |
static int | rewrite_wrapper (struct ast_filestream *s, const char *comment) |
static int | waitstream_core (struct ast_channel *c, const char *breakon, const char *forward, const char *reverse, int skip_ms, int audiofd, int cmdfd, const char *context) |
the core of all waitstream() functions | |
Variables | |
int | ast_language_is_prefix = 1 |
struct ast_cli_entry | cli_file [] |
static struct formats | formats |
Generic File Format Support.
Definition in file file.c.
#define FORMAT "%-10s %-10s %-20s\n" |
#define FORMAT2 "%-10s %-10s %-20s\n" |
enum file_action |
Definition at line 391 of file file.c.
{ ACTION_EXISTS = 1, /* return matching format if file exists, 0 otherwise */ ACTION_DELETE, /* delete file, return 0 on success, -1 on error */ ACTION_RENAME, /* rename file. return 0 on success, -1 on error */ ACTION_OPEN, ACTION_COPY /* copy file. return 0 on success, -1 on error */ };
enum fsread_res |
enum wrap_fn |
Definition at line 361 of file file.c.
{ WRAP_OPEN, WRAP_REWRITE };
int __ast_format_register | ( | const struct ast_format * | f, |
struct ast_module * | mod | ||
) |
Register a new file format capability. Adds a format to Asterisk's format abilities.
0 | on success |
-1 | on failure |
Definition at line 61 of file file.c.
References ast_calloc, ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_format::buf_size, ast_format::exts, f, ast_format::list, LOG_WARNING, ast_format::module, and ast_format::name.
{ struct ast_format *tmp; AST_RWLIST_WRLOCK(&formats); AST_RWLIST_TRAVERSE(&formats, tmp, list) { if (!strcasecmp(f->name, tmp->name)) { AST_RWLIST_UNLOCK(&formats); ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", f->name); return -1; } } if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { AST_RWLIST_UNLOCK(&formats); return -1; } *tmp = *f; tmp->module = mod; if (tmp->buf_size) { /* * Align buf_size properly, rounding up to the machine-specific * alignment for pointers. */ struct _test_align { void *a, *b; } p; int align = (char *)&p.b - (char *)&p.a; tmp->buf_size = ((f->buf_size + align - 1) / align) * align; } memset(&tmp->list, 0, sizeof(tmp->list)); AST_RWLIST_INSERT_HEAD(&formats, tmp, list); AST_RWLIST_UNLOCK(&formats); ast_verb(2, "Registered file format %s, extension(s) %s\n", f->name, f->exts); return 0; }
int ast_applystream | ( | struct ast_channel * | chan, |
struct ast_filestream * | s | ||
) |
Applys a open stream to a channel.
chan | channel to work |
s | ast_filestream to apply |
0 | on success. |
-1 | on failure. |
Definition at line 847 of file file.c.
References chan, and ast_filestream::owner.
Referenced by ast_streamfile(), handle_getoption(), handle_recordfile(), handle_streamfile(), and speech_streamfile().
int ast_closestream | ( | struct ast_filestream * | f | ) |
Closes a stream.
f | filestream to close Close a playback or recording stream |
0 | on success. |
-1 | on failure. |
Definition at line 890 of file file.c.
References ao2_ref, AST_FORMAT_AUDIO_MASK, AST_SCHED_DEL, ast_settimeout(), ast_filestream::fmt, ast_format::format, ast_filestream::owner, ast_channel::sched, ast_channel::stream, ast_channel::streamid, ast_channel::vstream, and ast_channel::vstreamid.
Referenced by __ast_play_and_record(), ast_filehelper(), ast_hangup(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), ast_readfile(), ast_stopstream(), ast_writefile(), dictate_exec(), filestream_destructor(), gen_closestream(), handle_cli_file_convert(), handle_recordfile(), local_ast_moh_stop(), mixmonitor_ds_close_fs(), moh_files_release(), record_exec(), recordthread(), and rpt().
{ /* This used to destroy the filestream, but it now just decrements a refcount. * We need to force the stream to quit queuing frames now, because we might * change the writeformat, which could result in a subsequent write error, if * the format is different. */ /* Stop a running stream if there is one */ if (f->owner) { if (f->fmt->format < AST_FORMAT_AUDIO_MASK) { f->owner->stream = NULL; AST_SCHED_DEL(f->owner->sched, f->owner->streamid); ast_settimeout(f->owner, 0, NULL, NULL); } else { f->owner->vstream = NULL; AST_SCHED_DEL(f->owner->sched, f->owner->vstreamid); } } ao2_ref(f, -1); return 0; }
int ast_file_init | ( | void | ) |
Provided by file.c
Definition at line 1476 of file file.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
{ ast_cli_register_multiple(cli_file, ARRAY_LEN(cli_file)); return 0; }
int ast_filecopy | ( | const char * | oldname, |
const char * | newname, | ||
const char * | fmt | ||
) |
Copies a file.
oldname | name of the file you wish to copy (minus extension) |
newname | name you wish the file to be copied to (minus extension) |
fmt | the format of the file Copy a given file in a given format, or if fmt is NULL, then do so for all |
Definition at line 941 of file file.c.
References ACTION_COPY, and ast_filehelper().
Referenced by copy_plain_file(), and vm_forwardoptions().
{ return ast_filehelper(filename, filename2, fmt, ACTION_COPY); }
int ast_filedelete | ( | const char * | filename, |
const char * | fmt | ||
) |
Deletes a file.
filename | name of the file you wish to delete (minus the extension) |
fmt | of the file Delete a given file in a given format, or if fmt is NULL, then do so for all |
Definition at line 931 of file file.c.
References ACTION_DELETE, and ast_filehelper().
Referenced by __ast_play_and_record(), announce_thread(), ast_monitor_start(), ast_monitor_stop(), conf_free(), conf_run(), dial_exec_full(), handle_cli_file_convert(), leave_voicemail(), play_record_review(), record_exec(), setup_privacy_args(), and vm_delete().
{ return ast_filehelper(filename, NULL, fmt, ACTION_DELETE); }
int ast_fileexists | ( | const char * | filename, |
const char * | fmt, | ||
const char * | preflang | ||
) |
Checks for the existence of a given file.
filename | name of the file you wish to check, minus the extension |
fmt | the format you wish to check (the extension) |
preflang | (the preferred language you wisht to find the file in) See if a given file exists in a given format. If fmt is NULL, any format is accepted. |
Definition at line 917 of file file.c.
References buf, and fileexists_core().
Referenced by announce_thread(), app_exec(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), common_exec(), dial_exec_full(), eivr_comm(), forward_message(), function_playback(), invent_message(), leave_voicemail(), minivm_delete_exec(), play_file(), play_message(), play_message_callerid(), record_exec(), retrydial_exec(), rpt_tele_thread(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), sayname(), saynode(), setup_privacy_args(), vm_intro(), vm_newuser(), vm_options(), and vm_tempgreeting().
{ char *buf; int buflen; if (preflang == NULL) preflang = ""; buflen = strlen(preflang) + strlen(filename) + 4; /* room for everything */ buf = alloca(buflen); if (buf == NULL) return 0; return fileexists_core(filename, fmt, preflang, buf, buflen); }
static int ast_filehelper | ( | const char * | filename, |
const void * | arg2, | ||
const char * | fmt, | ||
const enum file_action | action | ||
) | [static] |
perform various actions on a file. Second argument arg2 depends on the command: unused for EXISTS and DELETE destination file name (const char *) for COPY and RENAME struct ast_channel * for OPEN if fmt is NULL, OPEN will return the first matching entry, whereas other functions will run on all matching entries.
Definition at line 408 of file file.c.
References ACTION_COPY, ACTION_DELETE, ACTION_EXISTS, ACTION_OPEN, ACTION_RENAME, ast_closestream(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, ast_free, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, build_filename(), chan, copy(), errno, ext, ast_format::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::fmt, ast_format::format, get_filestream(), ast_filestream::lasttimeout, ast_format::list, LOG_WARNING, open_wrapper(), s, ast_channel::stream, strsep(), ast_filestream::trans, ast_channel::vstream, and ast_channel::writeformat.
Referenced by ast_filecopy(), ast_filedelete(), ast_filerename(), ast_openstream_full(), ast_openvstream(), and fileexists_test().
{ struct ast_format *f; int res = (action == ACTION_EXISTS) ? 0 : -1; AST_RWLIST_RDLOCK(&formats); /* Check for a specific format */ AST_RWLIST_TRAVERSE(&formats, f, list) { char *stringp, *ext = NULL; if (fmt && !exts_compare(f->exts, fmt)) continue; /* Look for a file matching the supported extensions. * The file must exist, and for OPEN, must match * one of the formats supported by the channel. */ stringp = ast_strdupa(f->exts); /* this is in the stack so does not need to be freed */ while ( (ext = strsep(&stringp, "|")) ) { struct stat st; char *fn = build_filename(filename, ext); if (fn == NULL) continue; if ( stat(fn, &st) ) { /* file not existent */ ast_free(fn); continue; } /* for 'OPEN' we need to be sure that the format matches * what the channel can process */ if (action == ACTION_OPEN) { struct ast_channel *chan = (struct ast_channel *)arg2; FILE *bfile; struct ast_filestream *s; if ( !(chan->writeformat & f->format) && !((f->format & AST_FORMAT_AUDIO_MASK && fmt) || (f->format & AST_FORMAT_VIDEO_MASK && fmt))) { ast_free(fn); continue; /* not a supported format */ } if ( (bfile = fopen(fn, "r")) == NULL) { ast_free(fn); continue; /* cannot open file */ } s = get_filestream(f, bfile); if (!s) { fclose(bfile); ast_free(fn); /* cannot allocate descriptor */ continue; } if (open_wrapper(s)) { ast_free(fn); ast_closestream(s); continue; /* cannot run open on file */ } if (st.st_size == 0) { ast_log(LOG_WARNING, "File %s detected to have zero size.\n", fn); } /* ok this is good for OPEN */ res = 1; /* found */ s->lasttimeout = -1; s->fmt = f; s->trans = NULL; s->filename = NULL; if (s->fmt->format & AST_FORMAT_AUDIO_MASK) { if (chan->stream) ast_closestream(chan->stream); chan->stream = s; } else { if (chan->vstream) ast_closestream(chan->vstream); chan->vstream = s; } ast_free(fn); break; } switch (action) { case ACTION_OPEN: break; /* will never get here */ case ACTION_EXISTS: /* return the matching format */ res |= f->format; break; case ACTION_DELETE: if ( (res = unlink(fn)) ) ast_log(LOG_WARNING, "unlink(%s) failed: %s\n", fn, strerror(errno)); break; case ACTION_RENAME: case ACTION_COPY: { char *nfn = build_filename((const char *)arg2, ext); if (!nfn) ast_log(LOG_WARNING, "Out of memory\n"); else { res = action == ACTION_COPY ? copy(fn, nfn) : rename(fn, nfn); if (res) ast_log(LOG_WARNING, "%s(%s,%s) failed: %s\n", action == ACTION_COPY ? "copy" : "rename", fn, nfn, strerror(errno)); ast_free(nfn); } } break; default: ast_log(LOG_WARNING, "Unknown helper %d\n", action); } ast_free(fn); } } AST_RWLIST_UNLOCK(&formats); return res; }
int ast_filerename | ( | const char * | oldname, |
const char * | newname, | ||
const char * | fmt | ||
) |
Renames a file.
oldname | the name of the file you wish to act upon (minus the extension) |
newname | the name you wish to rename the file to (minus the extension) |
fmt | the format of the file Rename a given file in a given format, or if fmt is NULL, then do so for all |
Definition at line 936 of file file.c.
References ACTION_RENAME, and ast_filehelper().
Referenced by __ast_play_and_record(), ast_monitor_stop(), forward_message(), leave_voicemail(), play_record_review(), rename_file(), and vm_forwardoptions().
{ return ast_filehelper(filename, filename2, fmt, ACTION_RENAME); }
char* ast_format_str_reduce | ( | char * | fmts | ) |
Remove duplicate formats from a format string.
fmts | a format string, this string will be modified |
NULL | error |
Definition at line 1360 of file file.c.
References ast_log(), AST_MAX_FORMATS, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, ast_format::exts, exts_compare(), f, first, len(), ast_format::list, LOG_WARNING, strsep(), and type.
Referenced by load_config().
{ struct ast_format *f; struct ast_format *fmts_ptr[AST_MAX_FORMATS]; char *fmts_str[AST_MAX_FORMATS]; char *stringp, *type; char *orig = fmts; int i, j, x, first, found = 0; int len = strlen(fmts) + 1; int res; if (AST_RWLIST_RDLOCK(&formats)) { ast_log(LOG_WARNING, "Unable to lock format list\n"); return NULL; } stringp = ast_strdupa(fmts); for (x = 0; (type = strsep(&stringp, "|")) && x < AST_MAX_FORMATS; x++) { AST_RWLIST_TRAVERSE(&formats, f, list) { if (exts_compare(f->exts, type)) { found = 1; break; } } fmts_str[x] = type; if (found) { fmts_ptr[x] = f; } else { fmts_ptr[x] = NULL; } } AST_RWLIST_UNLOCK(&formats); first = 1; for (i = 0; i < x; i++) { /* ignore invalid entries */ if (!fmts_ptr[i]) { ast_log(LOG_WARNING, "ignoring unknown format '%s'\n", fmts_str[i]); continue; } /* special handling for the first entry */ if (first) { res = snprintf(fmts, len, "%s", fmts_str[i]); fmts += res; len -= res; first = 0; continue; } found = 0; for (j = 0; j < i; j++) { /* this is a duplicate */ if (fmts_ptr[j] == fmts_ptr[i]) { found = 1; break; } } if (!found) { res = snprintf(fmts, len, "|%s", fmts_str[i]); fmts += res; len -= res; } } if (first) { ast_log(LOG_WARNING, "no known formats found in format list (%s)\n", orig); return NULL; } return orig; }
int ast_format_unregister | ( | const char * | name | ) |
Unregisters a file format.
name | the name of the format you wish to unregister Unregisters a format based on the name of the format. |
0 | on success |
-1 | on failure to unregister |
Definition at line 98 of file file.c.
References ast_free, ast_log(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_format::list, LOG_WARNING, and ast_format::name.
Referenced by unload_module().
{ struct ast_format *tmp; int res = -1; AST_RWLIST_WRLOCK(&formats); AST_RWLIST_TRAVERSE_SAFE_BEGIN(&formats, tmp, list) { if (!strcasecmp(name, tmp->name)) { AST_RWLIST_REMOVE_CURRENT(list); ast_free(tmp); res = 0; } } AST_RWLIST_TRAVERSE_SAFE_END; AST_RWLIST_UNLOCK(&formats); if (!res) ast_verb(2, "Unregistered format %s\n", name); else ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name); return res; }
static int ast_fsread_audio | ( | const void * | data | ) | [static] |
Definition at line 787 of file file.c.
References ast_readaudio_callback(), and FSREAD_SUCCESS_SCHED.
Referenced by ast_readaudio_callback().
{ struct ast_filestream *fs = (struct ast_filestream *)data; enum fsread_res res; res = ast_readaudio_callback(fs); if (res == FSREAD_SUCCESS_SCHED) return 1; return 0; }
static int ast_fsread_video | ( | const void * | data | ) | [static] |
Definition at line 834 of file file.c.
References ast_readvideo_callback(), and FSREAD_SUCCESS_SCHED.
Referenced by ast_readvideo_callback().
{ struct ast_filestream *fs = (struct ast_filestream *)data; enum fsread_res res; res = ast_readvideo_callback(fs); if (res == FSREAD_SUCCESS_SCHED) return 1; return 0; }
struct ast_filestream* ast_openstream | ( | struct ast_channel * | chan, |
const char * | filename, | ||
const char * | preflang | ||
) | [read] |
Opens stream for use in seeking, playing.
chan | channel to work with |
filename | to use |
preflang | prefered language to use |
a | ast_filestream pointer if it opens the file. |
NULL | on error. |
Definition at line 619 of file file.c.
References ast_openstream_full().
Referenced by ast_streamfile(), dictate_exec(), handle_getoption(), handle_streamfile(), and speech_streamfile().
{ return ast_openstream_full(chan, filename, preflang, 0); }
struct ast_filestream* ast_openstream_full | ( | struct ast_channel * | chan, |
const char * | filename, | ||
const char * | preflang, | ||
int | asis | ||
) | [read] |
Opens stream for use in seeking, playing.
chan | channel to work with |
filename | to use |
preflang | prefered language to use |
asis | if set, don't clear generators |
a | ast_filestream pointer if it opens the file. |
NULL | on error. |
Definition at line 624 of file file.c.
References ACTION_OPEN, ast_deactivate_generator(), ast_filehelper(), AST_FORMAT_AUDIO_MASK, ast_log(), ast_set_write_format(), ast_stopstream(), buf, fileexists_core(), ast_channel::generator, LOG_WARNING, ast_channel::oldwriteformat, ast_channel::stream, and ast_channel::writeformat.
Referenced by ast_moh_files_next(), ast_openstream(), and gen_nextfile().
{ /* * Use fileexists_core() to find a file in a compatible * language and format, set up a suitable translator, * and open the stream. */ int fmts, res, buflen; char *buf; if (!asis) { /* do this first, otherwise we detect the wrong writeformat */ ast_stopstream(chan); if (chan->generator) ast_deactivate_generator(chan); } if (preflang == NULL) preflang = ""; buflen = strlen(preflang) + strlen(filename) + 4; buf = alloca(buflen); if (buf == NULL) return NULL; fmts = fileexists_core(filename, NULL, preflang, buf, buflen); if (fmts > 0) fmts &= AST_FORMAT_AUDIO_MASK; if (fmts < 1) { ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename); return NULL; } chan->oldwriteformat = chan->writeformat; /* Set the channel to a format we can work with */ res = ast_set_write_format(chan, fmts); if (res == -1) { /* No format available that works with this channel */ return NULL; } res = ast_filehelper(buf, chan, NULL, ACTION_OPEN); if (res >= 0) return chan->stream; return NULL; }
struct ast_filestream* ast_openvstream | ( | struct ast_channel * | chan, |
const char * | filename, | ||
const char * | preflang | ||
) | [read] |
Opens stream for use in seeking, playing.
chan | channel to work with |
filename | to use |
preflang | prefered language to use |
a | ast_filestream pointer if it opens the file. |
NULL | on error. |
Definition at line 665 of file file.c.
References ACTION_OPEN, ast_filehelper(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, ast_getformatname(), ast_log(), buf, fileexists_core(), ast_filestream::fmt, format, LOG_WARNING, ast_channel::nativeformats, and ast_channel::vstream.
Referenced by ast_streamfile(), handle_getoption(), and handle_streamfile().
{ /* As above, but for video. But here we don't have translators * so we must enforce a format. */ unsigned int format; char *buf; int buflen; if (preflang == NULL) preflang = ""; buflen = strlen(preflang) + strlen(filename) + 4; buf = alloca(buflen); if (buf == NULL) return NULL; for (format = AST_FORMAT_AUDIO_MASK + 1; format <= AST_FORMAT_VIDEO_MASK; format = format << 1) { int fd; const char *fmt; if (!(chan->nativeformats & format)) continue; fmt = ast_getformatname(format); if ( fileexists_core(filename, fmt, preflang, buf, buflen) < 1) /* no valid format */ continue; fd = ast_filehelper(buf, chan, fmt, ACTION_OPEN); if (fd >= 0) return chan->vstream; ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename); } return NULL; }
int ast_playstream | ( | struct ast_filestream * | s | ) |
Play a open stream on a channel.
s | filestream to play |
0 | on success. |
-1 | on failure. |
Definition at line 853 of file file.c.
References AST_FORMAT_AUDIO_MASK, ast_readaudio_callback(), ast_readvideo_callback(), ast_filestream::fmt, ast_format::format, and FSREAD_FAILURE.
Referenced by ast_streamfile(), handle_getoption(), handle_streamfile(), and speech_streamfile().
{ enum fsread_res res; if (s->fmt->format & AST_FORMAT_AUDIO_MASK) res = ast_readaudio_callback(s); else res = ast_readvideo_callback(s); return (res == FSREAD_FAILURE) ? -1 : 0; }
static enum fsread_res ast_readaudio_callback | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 738 of file file.c.
References ast_format_rate(), ast_frfree, ast_fsread_audio(), ast_log(), ast_sched_add(), ast_settimeout(), ast_write(), ast_filestream::fmt, ast_format::format, FSREAD_FAILURE, FSREAD_SUCCESS_NOSCHED, FSREAD_SUCCESS_SCHED, ast_filestream::lasttimeout, LOG_WARNING, ast_channel::name, ast_filestream::orig_chan_name, ast_filestream::owner, read_frame(), ast_channel::sched, ast_channel::streamid, and ast_channel::timingfd.
Referenced by ast_fsread_audio(), and ast_playstream().
{ int whennext = 0; while (!whennext) { struct ast_frame *fr; if (s->orig_chan_name && strcasecmp(s->owner->name, s->orig_chan_name)) { goto return_failure; } fr = read_frame(s, &whennext); if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) { if (fr) { ast_log(LOG_WARNING, "Failed to write frame\n"); ast_frfree(fr); } goto return_failure; } if (fr) { ast_frfree(fr); } } if (whennext != s->lasttimeout) { if (s->owner->timingfd > -1) { float samp_rate = (float) ast_format_rate(s->fmt->format); unsigned int rate; rate = (unsigned int) roundf(samp_rate / ((float) whennext)); ast_settimeout(s->owner, rate, ast_fsread_audio, s); } else { s->owner->streamid = ast_sched_add(s->owner->sched, whennext / (ast_format_rate(s->fmt->format) / 1000), ast_fsread_audio, s); } s->lasttimeout = whennext; return FSREAD_SUCCESS_NOSCHED; } return FSREAD_SUCCESS_SCHED; return_failure: s->owner->streamid = -1; ast_settimeout(s->owner, 0, NULL, NULL); return FSREAD_FAILURE; }
struct ast_filestream* ast_readfile | ( | const char * | filename, |
const char * | type, | ||
const char * | comment, | ||
int | flags, | ||
int | check, | ||
mode_t | mode | ||
) | [read] |
Starts reading from a file.
filename | the name of the file to read from |
type | format of file you wish to read from |
comment | comment to go with |
flags | file flags |
check | (unimplemented, hence negligible) |
mode | Open mode Open an incoming file stream. flags are flags for the open() command, and if check is non-zero, then it will not read a file if there are any files that start with that name and have an extension Please note, this is a blocking function. Program execution will not return until ast_waitstream completes it's execution. |
a | struct ast_filestream on success. |
NULL | on failure. |
Definition at line 990 of file file.c.
References ast_closestream(), ast_free, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, build_filename(), errno, ast_format::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, get_filestream(), LOG_WARNING, ast_filestream::mode, open_wrapper(), ast_filestream::trans, and ast_filestream::vfs.
Referenced by __ast_play_and_record(), and handle_cli_file_convert().
{ FILE *bfile; struct ast_format *f; struct ast_filestream *fs = NULL; char *fn; int format_found = 0; AST_RWLIST_RDLOCK(&formats); AST_RWLIST_TRAVERSE(&formats, f, list) { fs = NULL; if (!exts_compare(f->exts, type)) continue; else format_found = 1; fn = build_filename(filename, type); errno = 0; bfile = fopen(fn, "r"); if (!bfile || (fs = get_filestream(f, bfile)) == NULL || open_wrapper(fs) ) { ast_log(LOG_WARNING, "Unable to open %s\n", fn); if (fs) { ast_closestream(fs); } fs = NULL; bfile = NULL; ast_free(fn); break; } /* found it */ fs->trans = NULL; fs->fmt = f; fs->flags = flags; fs->mode = mode; fs->filename = ast_strdup(filename); fs->vfs = NULL; break; } AST_RWLIST_UNLOCK(&formats); if (!format_found) ast_log(LOG_WARNING, "No such format '%s'\n", type); return fs; }
struct ast_frame* ast_readframe | ( | struct ast_filestream * | s | ) | [read] |
Read a frame from a filestream.
s | ast_filestream to act on |
NULL | if read failed. |
Definition at line 723 of file file.c.
References read_frame().
Referenced by __ast_play_and_record(), dictate_exec(), gen_readframe(), handle_cli_file_convert(), and moh_files_readframe().
{ int whennext = 0; return read_frame(s, &whennext); }
static enum fsread_res ast_readvideo_callback | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 802 of file file.c.
References ast_format_rate(), ast_frfree, ast_fsread_video(), ast_log(), ast_sched_add(), ast_write(), ast_filestream::fmt, ast_format::format, FSREAD_FAILURE, FSREAD_SUCCESS_NOSCHED, FSREAD_SUCCESS_SCHED, ast_filestream::lasttimeout, LOG_WARNING, ast_filestream::owner, read_frame(), ast_channel::sched, and ast_channel::vstreamid.
Referenced by ast_fsread_video(), and ast_playstream().
{ int whennext = 0; while (!whennext) { struct ast_frame *fr = read_frame(s, &whennext); if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) { if (fr) { ast_log(LOG_WARNING, "Failed to write frame\n"); ast_frfree(fr); } s->owner->vstreamid = -1; return FSREAD_FAILURE; } if (fr) { ast_frfree(fr); } } if (whennext != s->lasttimeout) { s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext / (ast_format_rate(s->fmt->format) / 1000), ast_fsread_video, s); s->lasttimeout = whennext; return FSREAD_SUCCESS_NOSCHED; } return FSREAD_SUCCESS_SCHED; }
int ast_seekstream | ( | struct ast_filestream * | fs, |
off_t | sample_offset, | ||
int | whence | ||
) |
Seeks into stream.
fs | ast_filestream to perform seek on |
sample_offset | numbers of samples to seek |
whence | SEEK_SET, SEEK_CUR, SEEK_END |
0 | on success. |
-1 | on failure. |
Definition at line 865 of file file.c.
References ast_filestream::fmt, and ast_format::seek.
Referenced by __ast_read(), ast_control_streamfile(), ast_moh_files_next(), ast_stream_fastforward(), ast_stream_rewind(), ast_streamfile(), ast_write(), dictate_exec(), handle_getoption(), handle_recordfile(), handle_streamfile(), and speech_streamfile().
int ast_stopstream | ( | struct ast_channel * | c | ) |
Stops a stream.
c | The channel you wish to stop playback on |
Stop playback of a stream
0 | always |
Definition at line 122 of file file.c.
References ast_channel_lock, ast_channel_unlock, ast_closestream(), ast_log(), ast_set_write_format(), LOG_WARNING, ast_channel::oldwriteformat, ast_channel::stream, and ast_channel::vstream.
Referenced by _ast_adsi_transmit_message_full(), ast_control_streamfile(), ast_openstream_full(), ast_play_and_wait(), ast_readstring_full(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_enumeration_full_he(), ast_say_number_full_cs(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_hu(), ast_say_number_full_it(), ast_say_number_full_ka(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), ast_say_number_full_th(), ast_say_number_full_zh(), background_detect_exec(), builtin_blindtransfer(), conf_exec(), conf_run(), dial_exec_full(), directory_exec(), grab_transfer(), handle_getoption(), handle_speechrecognize(), handle_streamfile(), ices_exec(), ivr_dispatch(), leave_voicemail(), menu_callback(), minivm_greet_exec(), mp3_exec(), NBScat_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_file(), play_mailbox_owner(), playback_exec(), queue_exec(), read_exec(), readexten_exec(), record_exec(), recordthread(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), saycharstr(), sayfile(), saynum(), select_item_seq(), send_morse(), send_tone_telemetry(), send_waveform_to_channel(), speech_background(), vm_authenticate(), vm_execmain(), wait_for_winner(), waitstream_core(), and zapateller_exec().
{ ast_channel_lock(tmp); /* Stop a running stream if there is one */ if (tmp->stream) { ast_closestream(tmp->stream); tmp->stream = NULL; if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat)) ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat); } /* Stop the video stream too */ if (tmp->vstream != NULL) { ast_closestream(tmp->vstream); tmp->vstream = NULL; } ast_channel_unlock(tmp); return 0; }
int ast_stream_and_wait | ( | struct ast_channel * | chan, |
const char * | file, | ||
const char * | digits | ||
) |
stream file until digit If the file name is non-empty, try to play it.
-1 | if error. |
digit | if interrupted by a digit. |
Definition at line 1348 of file file.c.
References ast_streamfile(), ast_strlen_zero(), ast_waitstream(), and ast_channel::language.
Referenced by __ast_play_and_record(), announce_user_count(), app_exec(), ast_pickup_call(), ast_record_review(), bridge_playfile(), builtin_atxfer(), builtin_automixmonitor(), builtin_blindtransfer(), confbridge_exec(), directory_exec(), feature_attended_transfer(), feature_blind_transfer(), forward_message(), grab_transfer(), invent_message(), ivr_dispatch(), join_conference_bridge(), leave_voicemail(), masq_park_call(), menu_callback(), park_exec_full(), play_mailbox_owner(), play_message_callerid(), play_message_in_bridged_call(), play_prompt_to_channel(), play_record_review(), play_sound_file(), sayname(), select_item_seq(), and wait_file2().
{ int res = 0; if (!ast_strlen_zero(file)) { res = ast_streamfile(chan, file, chan->language); if (!res) { res = ast_waitstream(chan, digits); } } return res; }
int ast_stream_fastforward | ( | struct ast_filestream * | fs, |
off_t | ms | ||
) |
Fast forward stream ms.
fs | filestream to act on |
ms | milliseconds to move |
0 | on success. |
-1 | on failure. |
Definition at line 880 of file file.c.
References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.
Referenced by waitstream_core().
{ return ast_seekstream(fs, ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR); }
int ast_stream_rewind | ( | struct ast_filestream * | fs, |
off_t | ms | ||
) |
Rewind stream ms.
fs | filestream to act on |
ms | milliseconds to move |
0 | on success. |
-1 | on failure. |
Definition at line 885 of file file.c.
References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.
Referenced by __ast_play_and_record(), handle_recordfile(), record_exec(), and waitstream_core().
{ return ast_seekstream(fs, -ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR); }
int ast_streamfile | ( | struct ast_channel * | c, |
const char * | filename, | ||
const char * | preflang | ||
) |
Streams a file.
c | channel to stream the file to |
filename | the name of the file you wish to stream, minus the extension |
preflang | the preferred language you wish to have the file streamed to you in Prepares a channel for the streaming of a file. To start the stream, afterward do a ast_waitstream() on the channel Also, it will stop any existing streams on the channel. |
0 | on success. |
-1 | on failure. |
Definition at line 946 of file file.c.
References ast_applystream(), ast_debug, AST_FLAG_MASQ_NOSTREAM, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_strdup, ast_test_flag, ast_verb, errno, ast_filestream::f, ast_filestream::fmt, ast_format::format, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, ast_filestream::orig_chan_name, ast_filestream::vfs, and ast_channel::writeformat.
Referenced by action_bridge(), agent_call(), announce_thread(), app_exec(), ast_app_getdata(), ast_app_getdata_full(), ast_control_streamfile(), ast_play_and_wait(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_th(), ast_say_date_with_format_gr(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_he(), ast_say_datetime_from_now_ka(), ast_say_datetime_gr(), ast_say_datetime_he(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_enumeration_full_he(), ast_say_number_full_cs(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_hu(), ast_say_number_full_it(), ast_say_number_full_ka(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), ast_say_number_full_th(), ast_say_number_full_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_hu(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_zh(), ast_stream_and_wait(), auth_exec(), background_detect_exec(), bridge_exec(), check_availability(), check_beep(), common_exec(), conf_exec(), conf_run(), dial_exec_full(), do_directory(), find_conf_realtime(), forward_message(), gr_say_number_female(), handle_recordfile(), invent_message(), leave_voicemail(), local_attended_transfer(), login_exec(), menu_callback(), minivm_greet_exec(), page_exec(), park_exec_full(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), play_record_review(), playback_exec(), privacy_exec(), readexten_exec(), record_exec(), retrydial_exec(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), sayfile(), select_item_menu(), setup_privacy_args(), ss_thread(), vm_authenticate(), wait_file(), and wait_for_winner().
{ struct ast_filestream *fs; struct ast_filestream *vfs=NULL; char fmt[256]; int seekattempt; int res; fs = ast_openstream(chan, filename, preflang); if (!fs) { ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), chan->nativeformats), strerror(errno)); return -1; } /* check to see if there is any data present (not a zero length file), * done this way because there is no where for ast_openstream_full to * return the file had no data. */ seekattempt = fseek(fs->f, -1, SEEK_END); if (seekattempt && errno == EINVAL) { /* Zero-length file, as opposed to a pipe */ return 0; } else { ast_seekstream(fs, 0, SEEK_SET); } vfs = ast_openvstream(chan, filename, preflang); if (vfs) { ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format)); } if (ast_test_flag(chan, AST_FLAG_MASQ_NOSTREAM)) fs->orig_chan_name = ast_strdup(chan->name); if (ast_applystream(chan, fs)) return -1; if (vfs && ast_applystream(chan, vfs)) return -1; res = ast_playstream(fs); if (!res && vfs) res = ast_playstream(vfs); ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", chan->name, filename, ast_getformatname(chan->writeformat), preflang ? preflang : "default"); return res; }
off_t ast_tellstream | ( | struct ast_filestream * | fs | ) |
Tell where we are in a stream.
fs | fs to act on |
Definition at line 875 of file file.c.
References ast_filestream::fmt, and ast_format::tell.
Referenced by __ast_play_and_record(), ast_control_streamfile(), handle_getoption(), handle_recordfile(), handle_speechrecognize(), and handle_streamfile().
int ast_truncstream | ( | struct ast_filestream * | fs | ) |
Trunc stream at current location.
fs | filestream to act on |
0 | on success. |
-1 | on failure. |
Definition at line 870 of file file.c.
References ast_filestream::fmt, and ast_format::trunc.
Referenced by __ast_play_and_record(), handle_recordfile(), and record_exec().
int ast_waitstream | ( | struct ast_channel * | c, |
const char * | breakon | ||
) |
Waits for a stream to stop or digit to be pressed.
c | channel to waitstream on |
breakon | string of DTMF digits to break upon Begins playback of a stream... Wait for a stream to stop or for any one of a given digit to arrive, |
0 | if the stream finishes |
the | character if it was interrupted, |
-1 | on error |
Definition at line 1321 of file file.c.
References waitstream_core().
Referenced by action_bridge(), agent_call(), announce_thread(), app_exec(), ast_play_and_wait(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_th(), ast_say_date_with_format_gr(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_he(), ast_say_datetime_from_now_ka(), ast_say_datetime_gr(), ast_say_datetime_he(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_enumeration_full_he(), ast_say_number_full_cs(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_hu(), ast_say_number_full_it(), ast_say_number_full_ka(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), ast_say_number_full_th(), ast_say_number_full_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_gr(), ast_say_time_he(), ast_say_time_hu(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_zh(), ast_stream_and_wait(), auth_exec(), bridge_exec(), check_availability(), check_beep(), common_exec(), conf_exec(), conf_run(), directory_exec(), find_conf_realtime(), gr_say_number_female(), handle_recordfile(), invent_message(), leave_voicemail(), local_attended_transfer(), login_exec(), menu_callback(), minivm_greet_exec(), page_exec(), park_exec_full(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), play_record_review(), playback_exec(), privacy_exec(), record_exec(), retrydial_exec(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), saycharstr(), sayfile(), saynum(), select_item_menu(), send_morse(), send_tone_telemetry(), setup_privacy_args(), ss_thread(), vm_authenticate(), and wait_file().
{ return waitstream_core(c, breakon, NULL, NULL, 0, -1, -1, NULL); }
int ast_waitstream_exten | ( | struct ast_channel * | c, |
const char * | context | ||
) |
Waits for a stream to stop or digit matching a valid one digit exten to be pressed.
c | channel to waitstream on |
context | string of context to match digits to break upon Begins playback of a stream... Wait for a stream to stop or for any one of a valid extension digit to arrive, |
0 | if the stream finishes. |
the | character if it was interrupted. |
-1 | on error. |
Definition at line 1332 of file file.c.
References ast_channel::context, and waitstream_core().
Referenced by pbx_builtin_background().
{ /* Waitstream, with return in the case of a valid 1 digit extension */ /* in the current or specified context being pressed */ if (!context) context = c->context; return waitstream_core(c, NULL, NULL, NULL, 0, -1, -1, context); }
int ast_waitstream_fr | ( | struct ast_channel * | c, |
const char * | breakon, | ||
const char * | forward, | ||
const char * | rewind, | ||
int | ms | ||
) |
Same as waitstream but allows stream to be forwarded or rewound.
c | channel to waitstream on |
breakon | string of DTMF digits to break upon |
forward | DTMF digit to fast forward upon |
rewind | DTMF digit to rewind upon |
ms | How many miliseconds to skip forward/back Begins playback of a stream... Wait for a stream to stop or for any one of a given digit to arrive, |
0 | if the stream finishes. |
the | character if it was interrupted. |
-1 | on error. |
Definition at line 1315 of file file.c.
References waitstream_core().
Referenced by ast_control_streamfile().
{ return waitstream_core(c, breakon, forward, reverse, ms, -1 /* no audiofd */, -1 /* no cmdfd */, NULL /* no context */); }
int ast_waitstream_full | ( | struct ast_channel * | c, |
const char * | breakon, | ||
int | audiofd, | ||
int | monfd | ||
) |
Same as waitstream, but with audio output to fd and monitored fd checking.
Definition at line 1326 of file file.c.
References waitstream_core().
Referenced by ast_readstring_full(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_enumeration_full_he(), ast_say_number_full_cs(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_hu(), ast_say_number_full_it(), ast_say_number_full_ka(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), ast_say_number_full_th(), ast_say_number_full_zh(), handle_getoption(), handle_streamfile(), pl_odtworz_plik(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), and say_phonetic_str_full().
{ return waitstream_core(c, breakon, NULL, NULL, 0, audiofd, cmdfd, NULL /* no context */); }
struct ast_filestream* ast_writefile | ( | const char * | filename, |
const char * | type, | ||
const char * | comment, | ||
int | flags, | ||
int | check, | ||
mode_t | mode | ||
) | [read] |
Starts writing a file.
filename | the name of the file to write to |
type | format of file you wish to write out to |
comment | comment to go with |
flags | output file flags |
check | (unimplemented, hence negligible) |
mode | Open mode Create an outgoing file stream. oflags are flags for the open() command, and if check is non-zero, then it will not write a file if there are any files that start with that name and have an extension Please note, this is a blocking function. Program execution will not return until ast_waitstream completes it's execution. |
a | struct ast_filestream on success. |
NULL | on failure. |
Definition at line 1038 of file file.c.
References ast_closestream(), ast_free, ast_log(), ast_malloc, ast_opt_cache_record_files, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_strdupa, buf, build_filename(), errno, ast_format::exts, exts_compare(), ast_filestream::f, f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, get_filestream(), LOG_WARNING, ast_filestream::mode, ast_filestream::realfilename, record_cache_dir, rewrite_wrapper(), ast_format::seek, ast_filestream::trans, ast_filestream::vfs, and ast_filestream::write_buffer.
Referenced by __ast_play_and_record(), ast_monitor_start(), ast_writestream(), dictate_exec(), handle_cli_file_convert(), handle_recordfile(), mixmonitor_thread(), record_exec(), recordthread(), and rpt().
{ int fd, myflags = 0; /* compiler claims this variable can be used before initialization... */ FILE *bfile = NULL; struct ast_format *f; struct ast_filestream *fs = NULL; char *buf = NULL; size_t size = 0; int format_found = 0; AST_RWLIST_RDLOCK(&formats); /* set the O_TRUNC flag if and only if there is no O_APPEND specified */ /* We really can't use O_APPEND as it will break WAV header updates */ if (flags & O_APPEND) { flags &= ~O_APPEND; } else { myflags = O_TRUNC; } myflags |= O_WRONLY | O_CREAT; /* XXX need to fix this - we should just do the fopen, * not open followed by fdopen() */ AST_RWLIST_TRAVERSE(&formats, f, list) { char *fn, *orig_fn = NULL; if (fs) break; if (!exts_compare(f->exts, type)) continue; else format_found = 1; fn = build_filename(filename, type); fd = open(fn, flags | myflags, mode); if (fd > -1) { /* fdopen() the resulting file stream */ bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w"); if (!bfile) { ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno)); close(fd); fd = -1; } } if (ast_opt_cache_record_files && (fd > -1)) { char *c; fclose(bfile); /* this also closes fd */ /* We touch orig_fn just as a place-holder so other things (like vmail) see the file is there. What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place. */ orig_fn = ast_strdupa(fn); for (c = fn; *c; c++) if (*c == '/') *c = '_'; size = strlen(fn) + strlen(record_cache_dir) + 2; buf = alloca(size); strcpy(buf, record_cache_dir); strcat(buf, "/"); strcat(buf, fn); ast_free(fn); fn = buf; fd = open(fn, flags | myflags, mode); if (fd > -1) { /* fdopen() the resulting file stream */ bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w"); if (!bfile) { ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno)); close(fd); fd = -1; } } } if (fd > -1) { errno = 0; fs = get_filestream(f, bfile); if (fs) { if ((fs->write_buffer = ast_malloc(32768))) { setvbuf(fs->f, fs->write_buffer, _IOFBF, 32768); } } if (!fs || rewrite_wrapper(fs, comment)) { ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn); close(fd); if (orig_fn) { unlink(fn); unlink(orig_fn); } if (fs) { ast_closestream(fs); fs = NULL; } continue; } fs->trans = NULL; fs->fmt = f; fs->flags = flags; fs->mode = mode; if (orig_fn) { fs->realfilename = ast_strdup(orig_fn); fs->filename = ast_strdup(fn); } else { fs->realfilename = NULL; fs->filename = ast_strdup(filename); } fs->vfs = NULL; /* If truncated, we'll be at the beginning; if not truncated, then append */ f->seek(fs, 0, SEEK_END); } else if (errno != EEXIST) { ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno)); if (orig_fn) unlink(orig_fn); } /* if buf != NULL then fn is already free and pointing to it */ if (!buf) ast_free(fn); } AST_RWLIST_UNLOCK(&formats); if (!format_found) ast_log(LOG_WARNING, "No such format '%s'\n", type); return fs; }
int ast_writestream | ( | struct ast_filestream * | fs, |
struct ast_frame * | f | ||
) |
Writes a frame to a stream.
fs | filestream to write to |
f | frame to write to the filestream Send a frame to a filestream -- note: does NOT free the frame, call ast_frfree manually |
0 | on success. |
-1 | on failure. |
Definition at line 144 of file file.c.
References ast_debug, AST_FORMAT_AUDIO_MASK, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_getformatname(), AST_LIST_NEXT, ast_log(), ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_writefile(), ast_writestream(), ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, ast_format::format, ast_frame::frametype, ast_filestream::lastwriteformat, LOG_WARNING, ast_filestream::mode, ast_format::name, ast_frame::subclass, ast_filestream::trans, type, ast_filestream::vfs, and ast_format::write.
Referenced by __ast_play_and_record(), __ast_read(), ast_write(), ast_writestream(), dictate_exec(), handle_cli_file_convert(), handle_recordfile(), mixmonitor_thread(), record_exec(), recordthread(), and rpt().
{ int res = -1; int alt = 0; if (f->frametype == AST_FRAME_VIDEO) { if (fs->fmt->format & AST_FORMAT_AUDIO_MASK) { /* This is the audio portion. Call the video one... */ if (!fs->vfs && fs->filename) { const char *type = ast_getformatname(f->subclass & ~0x1); fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode); ast_debug(1, "Opened video output file\n"); } if (fs->vfs) return ast_writestream(fs->vfs, f); /* else ignore */ return 0; } else { /* Might / might not have mark set */ alt = 1; } } else if (f->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Tried to write non-voice frame\n"); return -1; } if (((fs->fmt->format | alt) & f->subclass) == f->subclass) { res = fs->fmt->write(fs, f); if (res < 0) ast_log(LOG_WARNING, "Natural write failed\n"); else if (res > 0) ast_log(LOG_WARNING, "Huh??\n"); } else { /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't the one we've setup a translator for, we do the "wrong thing" XXX */ if (fs->trans && f->subclass != fs->lastwriteformat) { ast_translator_free_path(fs->trans); fs->trans = NULL; } if (!fs->trans) fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass); if (!fs->trans) ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n", fs->fmt->name, ast_getformatname(f->subclass)); else { struct ast_frame *trf; fs->lastwriteformat = f->subclass; /* Get the translated frame but don't consume the original in case they're using it on another stream */ if ((trf = ast_translate(fs->trans, f, 0))) { struct ast_frame *cur; /* the translator may have returned multiple frames, so process them */ for (cur = trf; cur; cur = AST_LIST_NEXT(cur, frame_list)) { if ((res = fs->fmt->write(fs, trf))) { ast_log(LOG_WARNING, "Translated frame write failed\n"); break; } } ast_frfree(trf); } else { res = 0; } } } return res; }
static char* build_filename | ( | const char * | filename, |
const char * | ext | ||
) | [static] |
construct a filename. Absolute pathnames are preserved, relative names are prefixed by the sounds/ directory. The wav49 suffix is replaced by 'WAV'. Returns a malloc'ed string to be freed by the caller.
Definition at line 252 of file file.c.
References asprintf, ast_config_AST_DATA_DIR, ast_log(), errno, and LOG_WARNING.
Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().
{ char *fn = NULL; if (!strcmp(ext, "wav49")) ext = "WAV"; if (filename[0] == '/') { if (asprintf(&fn, "%s.%s", filename, ext) < 0) { ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); fn = NULL; } } else { if (asprintf(&fn, "%s/sounds/%s.%s", ast_config_AST_DATA_DIR, filename, ext) < 0) { ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); fn = NULL; } } return fn; }
static int copy | ( | const char * | infile, |
const char * | outfile | ||
) | [static] |
Definition at line 209 of file file.c.
References AST_FILE_MODE, ast_log(), buf, errno, len(), and LOG_WARNING.
Referenced by ast_filehelper().
{ int ifd, ofd, len; char buf[4096]; /* XXX make it lerger. */ if ((ifd = open(infile, O_RDONLY)) < 0) { ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile); return -1; } if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, AST_FILE_MODE)) < 0) { ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile); close(ifd); return -1; } while ( (len = read(ifd, buf, sizeof(buf)) ) ) { int res; if (len < 0) { ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno)); break; } /* XXX handle partial writes */ res = write(ofd, buf, len); if (res != len) { ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno)); len = -1; /* error marker */ break; } } close(ifd); close(ofd); if (len < 0) { unlink(outfile); return -1; /* error */ } return 0; /* success */ }
static int exts_compare | ( | const char * | exts, |
const char * | type | ||
) | [static] |
Definition at line 276 of file file.c.
References ast_copy_string(), ext, and strsep().
Referenced by ast_filehelper(), ast_format_str_reduce(), ast_readfile(), and ast_writefile().
{ char tmp[256]; char *stringp = tmp, *ext; ast_copy_string(tmp, exts, sizeof(tmp)); while ((ext = strsep(&stringp, "|"))) { if (!strcmp(ext, type)) return 1; } return 0; }
static int fileexists_core | ( | const char * | filename, |
const char * | fmt, | ||
const char * | preflang, | ||
char * | buf, | ||
int | buflen | ||
) | [static] |
helper routine to locate a file with a given format and language preference. Try preflang, preflang with stripped '_' suffix, or NULL. In the standard asterisk, language goes just before the last component. In an alternative configuration, the language should be a prefix to the actual filename.
The last parameter(s) point to a buffer of sufficient size, which on success is filled with the matching filename.
Definition at line 568 of file file.c.
References ast_strdupa, ast_strlen_zero(), DEFAULT_LANGUAGE, fileexists_test(), and strsep().
Referenced by ast_fileexists(), ast_openstream_full(), and ast_openvstream().
{ int res = -1; char *lang = NULL; if (buf == NULL) { return -1; } /* We try languages in the following order: * preflang (may include dialect) * lang (preflang without dialect - if any) * <none> * default (unless the same as preflang or lang without dialect) */ /* Try preferred language */ if (!ast_strlen_zero(preflang)) { /* try the preflang exactly as it was requested */ if ((res = fileexists_test(filename, fmt, preflang, buf, buflen)) > 0) { return res; } else { /* try without a dialect */ char *postfix = NULL; postfix = lang = ast_strdupa(preflang); strsep(&postfix, "_"); if (postfix) { if ((res = fileexists_test(filename, fmt, lang, buf, buflen)) > 0) { return res; } } } } /* Try without any language */ if ((res = fileexists_test(filename, fmt, NULL, buf, buflen)) > 0) { return res; } /* Finally try the default language unless it was already tried before */ if ((ast_strlen_zero(preflang) || strcmp(preflang, DEFAULT_LANGUAGE)) && (ast_strlen_zero(lang) || strcmp(lang, DEFAULT_LANGUAGE))) { if ((res = fileexists_test(filename, fmt, DEFAULT_LANGUAGE, buf, buflen)) > 0) { return res; } } return 0; }
static int fileexists_test | ( | const char * | filename, |
const char * | fmt, | ||
const char * | lang, | ||
char * | buf, | ||
int | buflen | ||
) | [static] |
Definition at line 531 of file file.c.
References ACTION_EXISTS, ast_filehelper(), and is_absolute_path().
Referenced by fileexists_core().
{ if (buf == NULL) { return -1; } if (ast_language_is_prefix && !is_absolute_path(filename)) { /* new layout */ if (lang) { snprintf(buf, buflen, "%s/%s", lang, filename); } else { snprintf(buf, buflen, "%s", filename); } } else { /* old layout */ strcpy(buf, filename); /* first copy the full string */ if (lang) { /* insert the language and suffix if needed */ const char *c = strrchr(filename, '/'); int offset = c ? c - filename + 1 : 0; /* points right after the last '/' */ snprintf(buf + offset, buflen - offset, "%s/%s", lang, filename + offset); } } return ast_filehelper(buf, NULL, fmt, ACTION_EXISTS); }
static void filestream_destructor | ( | void * | arg | ) | [static] |
Definition at line 290 of file file.c.
References ast_closestream(), AST_FORMAT_AUDIO_MASK, ast_free, ast_module_unref(), ast_safe_system(), AST_SCHED_DEL, ast_settimeout(), ast_translator_free_path(), ast_format::close, ast_filestream::f, f, ast_filestream::filename, ast_filestream::fmt, ast_format::format, free, ast_format::module, ast_filestream::orig_chan_name, ast_filestream::owner, ast_filestream::realfilename, ast_channel::sched, ast_channel::stream, ast_channel::streamid, ast_filestream::trans, ast_filestream::vfs, ast_channel::vstream, ast_channel::vstreamid, and ast_filestream::write_buffer.
Referenced by get_filestream().
{ char *cmd = NULL; size_t size = 0; struct ast_filestream *f = arg; /* Stop a running stream if there is one */ if (f->owner) { if (f->fmt->format < AST_FORMAT_AUDIO_MASK) { f->owner->stream = NULL; AST_SCHED_DEL(f->owner->sched, f->owner->streamid); ast_settimeout(f->owner, 0, NULL, NULL); } else { f->owner->vstream = NULL; AST_SCHED_DEL(f->owner->sched, f->owner->vstreamid); } } /* destroy the translator on exit */ if (f->trans) ast_translator_free_path(f->trans); if (f->realfilename && f->filename) { size = strlen(f->filename) + strlen(f->realfilename) + 15; cmd = alloca(size); memset(cmd,0,size); snprintf(cmd,size,"/bin/mv -f %s %s",f->filename,f->realfilename); ast_safe_system(cmd); } if (f->filename) free(f->filename); if (f->realfilename) free(f->realfilename); if (f->fmt->close) { void (*closefn)(struct ast_filestream *) = f->fmt->close; closefn(f); } if (f->f) fclose(f->f); if (f->vfs) ast_closestream(f->vfs); if (f->write_buffer) { ast_free(f->write_buffer); } if (f->orig_chan_name) free((void *) f->orig_chan_name); ast_module_unref(f->fmt->module); }
static int fn_wrapper | ( | struct ast_filestream * | s, |
const char * | comment, | ||
enum wrap_fn | mode | ||
) | [static] |
Definition at line 363 of file file.c.
References ast_log(), ast_module_ref(), f, ast_filestream::fmt, LOG_WARNING, ast_format::module, ast_format::name, ast_format::open, ast_format::rewrite, s, WRAP_OPEN, and WRAP_REWRITE.
Referenced by open_wrapper(), and rewrite_wrapper().
{ struct ast_format *f = s->fmt; int ret = -1; int (*openfn)(struct ast_filestream *s); if (mode == WRAP_OPEN && (openfn = f->open) && openfn(s)) ast_log(LOG_WARNING, "Unable to open format %s\n", f->name); else if (mode == WRAP_REWRITE && f->rewrite && f->rewrite(s, comment)) ast_log(LOG_WARNING, "Unable to rewrite format %s\n", f->name); else { /* preliminary checks succeed. update usecount */ ast_module_ref(f->module); ret = 0; } return ret; }
static struct ast_filestream* get_filestream | ( | struct ast_format * | fmt, |
FILE * | bfile | ||
) | [static, read] |
Definition at line 339 of file file.c.
References ast_filestream::_private, ao2_alloc, ast_filestream::buf, ast_format::buf_size, ast_format::desc_size, ast_filestream::f, filestream_destructor(), ast_filestream::fmt, ast_filestream::fr, ast_format::name, s, and ast_frame::src.
Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().
{ struct ast_filestream *s; int l = sizeof(*s) + fmt->buf_size + fmt->desc_size; /* total allocation size */ if ( (s = ao2_alloc(l, filestream_destructor)) == NULL) return NULL; s->fmt = fmt; s->f = bfile; if (fmt->desc_size) s->_private = ((char *)(s + 1)) + fmt->buf_size; if (fmt->buf_size) s->buf = (char *)(s + 1); s->fr.src = fmt->name; return s; }
static char* handle_cli_core_show_file_formats | ( | struct ast_cli_entry * | e, |
int | cmd, | ||
struct ast_cli_args * | a | ||
) | [static] |
Definition at line 1436 of file file.c.
References ast_cli_args::argc, ast_cli(), ast_getformatname(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_format::exts, f, ast_cli_args::fd, ast_format::format, FORMAT, FORMAT2, ast_format::list, ast_format::name, and ast_cli_entry::usage.
{ #define FORMAT "%-10s %-10s %-20s\n" #define FORMAT2 "%-10s %-10s %-20s\n" struct ast_format *f; int count_fmt = 0; switch (cmd) { case CLI_INIT: e->command = "core show file formats"; e->usage = "Usage: core show file formats\n" " Displays currently registered file formats (if any).\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 4) return CLI_SHOWUSAGE; ast_cli(a->fd, FORMAT, "Format", "Name", "Extensions"); ast_cli(a->fd, FORMAT, "------", "----", "----------"); AST_RWLIST_RDLOCK(&formats); AST_RWLIST_TRAVERSE(&formats, f, list) { ast_cli(a->fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts); count_fmt++; } AST_RWLIST_UNLOCK(&formats); ast_cli(a->fd, "%d file formats registered.\n", count_fmt); return CLI_SUCCESS; #undef FORMAT #undef FORMAT2 }
static int is_absolute_path | ( | const char * | filename | ) | [static] |
Definition at line 526 of file file.c.
Referenced by fileexists_test().
{ return filename[0] == '/'; }
static int open_wrapper | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 386 of file file.c.
References fn_wrapper(), and WRAP_OPEN.
Referenced by ast_filehelper(), and ast_readfile().
{ return fn_wrapper(s, NULL, WRAP_OPEN); }
static struct ast_frame* read_frame | ( | struct ast_filestream * | s, |
int * | whennext | ||
) | [static, read] |
Definition at line 698 of file file.c.
References ast_frfree, ast_frisolate(), ast_filestream::fmt, and ast_format::read.
Referenced by ast_audiohook_read_frame(), ast_readaudio_callback(), ast_readframe(), and ast_readvideo_callback().
{ struct ast_frame *fr, *new_fr; if (!s || !s->fmt) { return NULL; } if (!(fr = s->fmt->read(s, whennext))) { return NULL; } if (!(new_fr = ast_frisolate(fr))) { ast_frfree(fr); return NULL; } if (new_fr != fr) { ast_frfree(fr); fr = new_fr; } return fr; }
static int rewrite_wrapper | ( | struct ast_filestream * | s, |
const char * | comment | ||
) | [static] |
Definition at line 381 of file file.c.
References fn_wrapper(), and WRAP_REWRITE.
Referenced by ast_writefile().
{ return fn_wrapper(s, comment, WRAP_REWRITE); }
static int waitstream_core | ( | struct ast_channel * | c, |
const char * | breakon, | ||
const char * | forward, | ||
const char * | reverse, | ||
int | skip_ms, | ||
int | audiofd, | ||
int | cmdfd, | ||
const char * | context | ||
) | [static] |
the core of all waitstream() functions
Definition at line 1173 of file file.c.
References ast_channel::_softhangup, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FLAG_MASQ_NOSTREAM, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_VOICE, ast_frfree, ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_set_flag, ast_stopstream(), ast_strdupa, ast_stream_fastforward(), ast_stream_rewind(), ast_test_flag, ast_waitfor(), ast_waitfor_nandfds(), ast_channel::cid, ast_callerid::cid_num, ast_frame::data, ast_frame::datalen, errno, exten, ast_filestream::f, ast_frame::frametype, LOG_WARNING, ast_channel::name, ast_filestream::orig_chan_name, ast_frame::ptr, ast_channel::sched, ast_channel::stream, and ast_frame::subclass.
Referenced by ast_waitstream(), ast_waitstream_exten(), ast_waitstream_fr(), and ast_waitstream_full().
{ const char *orig_chan_name = NULL; int err = 0; if (!breakon) breakon = ""; if (!forward) forward = ""; if (!reverse) reverse = ""; /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */ ast_set_flag(c, AST_FLAG_END_DTMF_ONLY); if (ast_test_flag(c, AST_FLAG_MASQ_NOSTREAM)) orig_chan_name = ast_strdupa(c->name); while (c->stream) { int res; int ms; if (orig_chan_name && strcasecmp(orig_chan_name, c->name)) { ast_stopstream(c); err = 1; break; } ms = ast_sched_wait(c->sched); if (ms < 0 && !c->timingfunc) { ast_stopstream(c); break; } if (ms < 0) ms = 1000; if (cmdfd < 0) { res = ast_waitfor(c, ms); if (res < 0) { ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno)); ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); return res; } } else { int outfd; struct ast_channel *rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); if (!rchan && (outfd < 0) && (ms)) { /* Continue */ if (errno == EINTR) continue; ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); return -1; } else if (outfd > -1) { /* this requires cmdfd set */ /* The FD we were watching has something waiting */ ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); return 1; } /* if rchan is set, it is 'c' */ res = rchan ? 1 : 0; /* map into 'res' values */ } if (res > 0) { struct ast_frame *fr = ast_read(c); if (!fr) { ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); return -1; } switch (fr->frametype) { case AST_FRAME_DTMF_END: if (context) { const char exten[2] = { fr->subclass, '\0' }; if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) { res = fr->subclass; ast_frfree(fr); ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); return res; } } else { res = fr->subclass; if (strchr(forward, res)) { int eoftest; ast_stream_fastforward(c->stream, skip_ms); eoftest = fgetc(c->stream->f); if (feof(c->stream->f)) { ast_stream_rewind(c->stream, skip_ms); } else { ungetc(eoftest, c->stream->f); } } else if (strchr(reverse, res)) { ast_stream_rewind(c->stream, skip_ms); } else if (strchr(breakon, res)) { ast_frfree(fr); ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); return res; } } break; case AST_FRAME_CONTROL: switch (fr->subclass) { case AST_CONTROL_HANGUP: case AST_CONTROL_BUSY: case AST_CONTROL_CONGESTION: ast_frfree(fr); ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); return -1; case AST_CONTROL_RINGING: case AST_CONTROL_ANSWER: case AST_CONTROL_VIDUPDATE: case AST_CONTROL_SRCUPDATE: case AST_CONTROL_SRCCHANGE: case AST_CONTROL_HOLD: case AST_CONTROL_UNHOLD: case -1: /* Unimportant */ break; default: ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass); } break; case AST_FRAME_VOICE: /* Write audio if appropriate */ if (audiofd > -1) { if (write(audiofd, fr->data.ptr, fr->datalen) < 0) { ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); } } default: /* Ignore all others */ break; } ast_frfree(fr); } ast_sched_runq(c->sched); } ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); return (err || c->_softhangup) ? -1 : 0; }
int ast_language_is_prefix = 1 |
Definition at line 57 of file file.c.
Referenced by ast_readconfig(), handle_show_settings(), and main().
struct ast_cli_entry cli_file[] |
{ AST_CLI_DEFINE(handle_cli_core_show_file_formats, "Displays file formats") }