#include "asterisk.h"
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>
#include "asterisk/frame.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/sched.h"
#include "asterisk/options.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 dependency graph for file.c:
Go to the source code of this file.
Defines | |
#define | FORMAT "%-10s %-10s %-20s\n" |
#define | FORMAT "%-10s %-10s %-20s\n" |
#define | FORMAT2 "%-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 | wrap_fn { WRAP_OPEN, WRAP_REWRITE } |
Functions | |
int | __ast_format_register (const struct ast_format *f, struct ast_module *mod) |
int | ast_applystream (struct ast_channel *chan, struct ast_filestream *s) |
int | ast_closestream (struct ast_filestream *f) |
int | ast_file_init (void) |
int | ast_filecopy (const char *filename, const char *filename2, const char *fmt) |
int | ast_filedelete (const char *filename, const char *fmt) |
int | ast_fileexists (const char *filename, const char *fmt, const char *preflang) |
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) |
int | ast_format_unregister (const char *name) |
ast_filestream * | ast_openstream (struct ast_channel *chan, const char *filename, const char *preflang) |
ast_filestream * | ast_openstream_full (struct ast_channel *chan, const char *filename, const char *preflang, int asis) |
ast_filestream * | ast_openvstream (struct ast_channel *chan, const char *filename, const char *preflang) |
int | ast_playstream (struct ast_filestream *s) |
static int | ast_readaudio_callback (void *data) |
ast_filestream * | ast_readfile (const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode) |
ast_frame * | ast_readframe (struct ast_filestream *s) |
static int | ast_readvideo_callback (void *data) |
static | AST_RWLIST_HEAD_STATIC (formats, ast_format) |
int | ast_seekstream (struct ast_filestream *fs, off_t sample_offset, int whence) |
int | ast_stopstream (struct ast_channel *tmp) |
int | ast_stream_and_wait (struct ast_channel *chan, const char *file, const char *language, const char *digits) |
int | ast_stream_fastforward (struct ast_filestream *fs, off_t ms) |
int | ast_stream_rewind (struct ast_filestream *fs, off_t ms) |
int | ast_streamfile (struct ast_channel *chan, const char *filename, const char *preflang) |
off_t | ast_tellstream (struct ast_filestream *fs) |
int | ast_truncstream (struct ast_filestream *fs) |
int | ast_waitstream (struct ast_channel *c, const char *breakon) |
int | ast_waitstream_exten (struct ast_channel *c, const char *context) |
int | ast_waitstream_fr (struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms) |
int | ast_waitstream_full (struct ast_channel *c, const char *breakon, int audiofd, int cmdfd) |
ast_filestream * | ast_writefile (const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode) |
int | ast_writestream (struct ast_filestream *fs, struct ast_frame *f) |
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 | 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 int | open_wrapper (struct ast_filestream *s) |
static int | rewrite_wrapper (struct ast_filestream *s, const char *comment) |
static int | show_file_formats (int fd, int argc, char *argv[]) |
static int | show_file_formats_deprecated (int fd, int argc, char *argv[]) |
static int | waitstream_core (struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int skip_ms, int audiofd, int cmdfd, const char *context) |
the core of all waitstream() functions | |
Variables | |
int | ast_language_is_prefix = 1 |
ast_cli_entry | cli_file [] |
ast_cli_entry | cli_show_file_formats_deprecated |
char | show_file_formats_usage [] |
Definition in file file.c.
#define FORMAT "%-10s %-10s %-20s\n" |
#define FORMAT "%-10s %-10s %-20s\n" |
#define FORMAT2 "%-10s %-10s %-20s\n" |
#define FORMAT2 "%-10s %-10s %-20s\n" |
Referenced by __iax2_show_peers(), __sip_show_channels(), _sip_show_peers(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), iax2_show_channels(), iax2_show_firmware(), iax2_show_registry(), iax2_show_users(), show_file_formats(), show_file_formats_deprecated(), show_image_formats(), show_image_formats_deprecated(), sip_show_inuse(), sip_show_registry(), zap_show_channels(), and zap_show_status().
enum file_action |
Definition at line 331 of file file.c.
00331 { 00332 ACTION_EXISTS = 1, /* return matching format if file exists, 0 otherwise */ 00333 ACTION_DELETE, /* delete file, return 0 on success, -1 on error */ 00334 ACTION_RENAME, /* rename file. return 0 on success, -1 on error */ 00335 ACTION_OPEN, 00336 ACTION_COPY /* copy file. return 0 on success, -1 on error */ 00337 };
enum wrap_fn |
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. returns 0 on success, -1 on failure
Definition at line 68 of file file.c.
References ast_calloc, ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), ast_format::buf_size, ast_format::exts, f, LOG_WARNING, ast_format::module, ast_format::name, option_verbose, and VERBOSE_PREFIX_2.
00069 { 00070 struct ast_format *tmp; 00071 00072 AST_RWLIST_WRLOCK(&formats); 00073 AST_RWLIST_TRAVERSE(&formats, tmp, list) { 00074 if (!strcasecmp(f->name, tmp->name)) { 00075 AST_RWLIST_UNLOCK(&formats); 00076 ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", f->name); 00077 return -1; 00078 } 00079 } 00080 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 00081 AST_RWLIST_UNLOCK(&formats); 00082 return -1; 00083 } 00084 *tmp = *f; 00085 tmp->module = mod; 00086 if (tmp->buf_size) { 00087 /* 00088 * Align buf_size properly, rounding up to the machine-specific 00089 * alignment for pointers. 00090 */ 00091 struct _test_align { void *a, *b; } p; 00092 int align = (char *)&p.b - (char *)&p.a; 00093 tmp->buf_size = ((f->buf_size + align - 1)/align)*align; 00094 } 00095 00096 memset(&tmp->list, 0, sizeof(tmp->list)); 00097 00098 AST_RWLIST_INSERT_HEAD(&formats, tmp, list); 00099 AST_RWLIST_UNLOCK(&formats); 00100 if (option_verbose > 1) 00101 ast_verbose( VERBOSE_PREFIX_2 "Registered file format %s, extension(s) %s\n", f->name, f->exts); 00102 00103 return 0; 00104 }
int ast_applystream | ( | struct ast_channel * | chan, | |
struct ast_filestream * | s | |||
) |
chan | channel to work | |
s | ast_filestream to apply Returns 0 for success, -1 on failure |
Definition at line 660 of file file.c.
References s.
Referenced by ast_streamfile(), handle_getoption(), handle_recordfile(), handle_streamfile(), and speech_streamfile().
00661 { 00662 s->owner = chan; 00663 return 0; 00664 }
int ast_closestream | ( | struct ast_filestream * | f | ) |
f | filestream to close Close a playback or recording stream Returns 0 on success, -1 on failure |
Definition at line 700 of file file.c.
References ast_closestream(), AST_FORMAT_MAX_AUDIO, ast_module_unref(), ast_safe_system(), ast_sched_del(), ast_settimeout(), ast_translator_free_path(), ast_format::close, f, ast_format::format, free, and ast_format::module.
Referenced by __ast_play_and_record(), ast_closestream(), ast_filehelper(), ast_hangup(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), ast_stopstream(), channel_spy(), cli_audio_convert(), cli_audio_convert_deprecated(), dictate_exec(), gen_closestream(), handle_recordfile(), local_ast_moh_stop(), mixmonitor_thread(), moh_files_release(), and rpt().
00701 { 00702 char *cmd = NULL; 00703 size_t size = 0; 00704 /* Stop a running stream if there is one */ 00705 if (f->owner) { 00706 if (f->fmt->format < AST_FORMAT_MAX_AUDIO) { 00707 f->owner->stream = NULL; 00708 if (f->owner->streamid > -1) 00709 ast_sched_del(f->owner->sched, f->owner->streamid); 00710 f->owner->streamid = -1; 00711 #ifdef HAVE_ZAPTEL 00712 ast_settimeout(f->owner, 0, NULL, NULL); 00713 #endif 00714 } else { 00715 f->owner->vstream = NULL; 00716 if (f->owner->vstreamid > -1) 00717 ast_sched_del(f->owner->sched, f->owner->vstreamid); 00718 f->owner->vstreamid = -1; 00719 } 00720 } 00721 /* destroy the translator on exit */ 00722 if (f->trans) 00723 ast_translator_free_path(f->trans); 00724 00725 if (f->realfilename && f->filename) { 00726 size = strlen(f->filename) + strlen(f->realfilename) + 15; 00727 cmd = alloca(size); 00728 memset(cmd,0,size); 00729 snprintf(cmd,size,"/bin/mv -f %s %s",f->filename,f->realfilename); 00730 ast_safe_system(cmd); 00731 } 00732 00733 if (f->filename) 00734 free(f->filename); 00735 if (f->realfilename) 00736 free(f->realfilename); 00737 if (f->fmt->close) 00738 f->fmt->close(f); 00739 fclose(f->f); 00740 if (f->vfs) 00741 ast_closestream(f->vfs); 00742 ast_module_unref(f->fmt->module); 00743 free(f); 00744 return 0; 00745 }
int ast_file_init | ( | void | ) |
Initializes all the various file stuff. Basically just registers the cli stuff Returns 0 all the time
Definition at line 1205 of file file.c.
References ast_cli_register_multiple(), and cli_file.
Referenced by main().
01206 { 01207 ast_cli_register_multiple(cli_file, sizeof(cli_file) / sizeof(struct ast_cli_entry)); 01208 return 0; 01209 }
int ast_filecopy | ( | const char * | oldname, | |
const char * | newname, | |||
const char * | fmt | |||
) |
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 775 of file file.c.
References ast_filehelper().
Referenced by copy_file().
00776 { 00777 return ast_filehelper(filename, filename2, fmt, ACTION_COPY); 00778 }
int ast_filedelete | ( | const char * | filename, | |
const char * | fmt | |||
) |
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 765 of file file.c.
References ACTION_DELETE, and ast_filehelper().
Referenced by __ast_play_and_record(), ast_monitor_start(), ast_monitor_stop(), cli_audio_convert(), cli_audio_convert_deprecated(), leave_voicemail(), play_mailbox_owner(), play_record_review(), and vm_delete().
00766 { 00767 return ast_filehelper(filename, NULL, fmt, ACTION_DELETE); 00768 }
int ast_fileexists | ( | const char * | filename, | |
const char * | fmt, | |||
const char * | preflang | |||
) |
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. Returns -1 if file does not exist, non-zero positive otherwise. |
Definition at line 751 of file file.c.
References fileexists_core().
Referenced by app_exec(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), common_exec(), conf_run(), invent_message(), last_message_index(), leave_voicemail(), play_mailbox_owner(), play_message_callerid(), record_exec(), retrydial_exec(), rxfax_exec(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), vm_intro(), vm_newuser(), and vm_tempgreeting().
00752 { 00753 char *buf; 00754 int buflen; 00755 00756 if (preflang == NULL) 00757 preflang = ""; 00758 buflen = strlen(preflang) + strlen(filename) + 2; /* room for everything */ 00759 buf = alloca(buflen); 00760 if (buf == NULL) 00761 return 0; 00762 return fileexists_core(filename, fmt, preflang, buf, buflen); 00763 }
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 348 of file file.c.
References ACTION_DELETE, ACTION_EXISTS, ACTION_OPEN, ACTION_RENAME, ast_closestream(), AST_FORMAT_MAX_AUDIO, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, build_filename(), copy(), ext, ast_format::exts, exts_compare(), f, ast_format::format, free, get_filestream(), LOG_WARNING, open_wrapper(), s, ast_channel::stream, strsep(), ast_channel::vstream, and ast_channel::writeformat.
Referenced by ast_filecopy(), ast_filedelete(), ast_filerename(), ast_openstream_full(), ast_openvstream(), and fileexists_core().
00349 { 00350 struct ast_format *f; 00351 int res = (action == ACTION_EXISTS) ? 0 : -1; 00352 00353 AST_RWLIST_RDLOCK(&formats); 00354 /* Check for a specific format */ 00355 AST_RWLIST_TRAVERSE(&formats, f, list) { 00356 char *stringp, *ext = NULL; 00357 00358 if (fmt && !exts_compare(f->exts, fmt)) 00359 continue; 00360 00361 /* Look for a file matching the supported extensions. 00362 * The file must exist, and for OPEN, must match 00363 * one of the formats supported by the channel. 00364 */ 00365 stringp = ast_strdupa(f->exts); /* this is in the stack so does not need to be freed */ 00366 while ( (ext = strsep(&stringp, "|")) ) { 00367 struct stat st; 00368 char *fn = build_filename(filename, ext); 00369 00370 if (fn == NULL) 00371 continue; 00372 00373 if ( stat(fn, &st) ) { /* file not existent */ 00374 free(fn); 00375 continue; 00376 } 00377 /* for 'OPEN' we need to be sure that the format matches 00378 * what the channel can process 00379 */ 00380 if (action == ACTION_OPEN) { 00381 struct ast_channel *chan = (struct ast_channel *)arg2; 00382 FILE *bfile; 00383 struct ast_filestream *s; 00384 00385 if ( !(chan->writeformat & f->format) && 00386 !(f->format >= AST_FORMAT_MAX_AUDIO && fmt)) { 00387 free(fn); 00388 continue; /* not a supported format */ 00389 } 00390 if ( (bfile = fopen(fn, "r")) == NULL) { 00391 free(fn); 00392 continue; /* cannot open file */ 00393 } 00394 s = get_filestream(f, bfile); 00395 if (!s) { 00396 fclose(bfile); 00397 free(fn); /* cannot allocate descriptor */ 00398 continue; 00399 } 00400 if (open_wrapper(s)) { 00401 fclose(bfile); 00402 free(fn); 00403 free(s); 00404 continue; /* cannot run open on file */ 00405 } 00406 /* ok this is good for OPEN */ 00407 res = 1; /* found */ 00408 s->lasttimeout = -1; 00409 s->fmt = f; 00410 s->trans = NULL; 00411 s->filename = NULL; 00412 if (s->fmt->format < AST_FORMAT_MAX_AUDIO) { 00413 if (chan->stream) 00414 ast_closestream(chan->stream); 00415 chan->stream = s; 00416 } else { 00417 if (chan->vstream) 00418 ast_closestream(chan->vstream); 00419 chan->vstream = s; 00420 } 00421 free(fn); 00422 break; 00423 } 00424 switch (action) { 00425 case ACTION_OPEN: 00426 break; /* will never get here */ 00427 00428 case ACTION_EXISTS: /* return the matching format */ 00429 res |= f->format; 00430 break; 00431 00432 case ACTION_DELETE: 00433 if ( (res = unlink(fn)) ) 00434 ast_log(LOG_WARNING, "unlink(%s) failed: %s\n", fn, strerror(errno)); 00435 break; 00436 00437 case ACTION_RENAME: 00438 case ACTION_COPY: { 00439 char *nfn = build_filename((const char *)arg2, ext); 00440 if (!nfn) 00441 ast_log(LOG_WARNING, "Out of memory\n"); 00442 else { 00443 res = action == ACTION_COPY ? copy(fn, nfn) : rename(fn, nfn); 00444 if (res) 00445 ast_log(LOG_WARNING, "%s(%s,%s) failed: %s\n", 00446 action == ACTION_COPY ? "copy" : "rename", 00447 fn, nfn, strerror(errno)); 00448 free(nfn); 00449 } 00450 } 00451 break; 00452 00453 default: 00454 ast_log(LOG_WARNING, "Unknown helper %d\n", action); 00455 } 00456 free(fn); 00457 } 00458 } 00459 AST_RWLIST_UNLOCK(&formats); 00460 return res; 00461 }
int ast_filerename | ( | const char * | oldname, | |
const char * | newname, | |||
const char * | fmt | |||
) |
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 Returns -1 on failure |
Definition at line 770 of file file.c.
References ACTION_RENAME, and ast_filehelper().
Referenced by __ast_play_and_record(), ast_monitor_stop(), leave_voicemail(), play_record_review(), and rename_file().
00771 { 00772 return ast_filehelper(filename, filename2, fmt, ACTION_RENAME); 00773 }
int ast_format_unregister | ( | const char * | name | ) |
name | the name of the format you wish to unregister Unregisters a format based on the name of the format. Returns 0 on success, -1 on failure to unregister |
Definition at line 106 of file file.c.
References ast_log(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), free, LOG_WARNING, ast_format::name, option_verbose, and VERBOSE_PREFIX_2.
Referenced by unload_module().
00107 { 00108 struct ast_format *tmp; 00109 int res = -1; 00110 00111 AST_RWLIST_WRLOCK(&formats); 00112 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&formats, tmp, list) { 00113 if (!strcasecmp(name, tmp->name)) { 00114 AST_RWLIST_REMOVE_CURRENT(&formats, list); 00115 free(tmp); 00116 res = 0; 00117 } 00118 } 00119 AST_RWLIST_TRAVERSE_SAFE_END 00120 AST_RWLIST_UNLOCK(&formats); 00121 00122 if (!res) { 00123 if (option_verbose > 1) 00124 ast_verbose( VERBOSE_PREFIX_2 "Unregistered format %s\n", name); 00125 } else 00126 ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name); 00127 00128 return res; 00129 }
struct ast_filestream* ast_openstream | ( | struct ast_channel * | chan, | |
const char * | filename, | |||
const char * | preflang | |||
) |
chan | channel to work with | |
filename | to use | |
preflang | prefered language to use Returns a ast_filestream pointer if it opens the file, NULL on error |
Definition at line 523 of file file.c.
References ast_openstream_full().
Referenced by ast_streamfile(), dictate_exec(), handle_getoption(), handle_streamfile(), and speech_streamfile().
00524 { 00525 return ast_openstream_full(chan, filename, preflang, 0); 00526 }
struct ast_filestream* ast_openstream_full | ( | struct ast_channel * | chan, | |
const char * | filename, | |||
const char * | preflang, | |||
int | asis | |||
) |
chan | channel to work with | |
filename | to use | |
preflang | prefered language to use | |
asis | if set, don't clear generators Returns a ast_filestream pointer if it opens the file, NULL on error |
Definition at line 528 of file file.c.
References ACTION_OPEN, ast_deactivate_generator(), ast_filehelper(), AST_FORMAT_AUDIO_MASK, ast_log(), ast_set_write_format(), ast_stopstream(), ast_filestream::buf, fileexists_core(), LOG_WARNING, ast_channel::oldwriteformat, ast_channel::stream, and ast_channel::writeformat.
Referenced by ast_moh_files_next(), ast_openstream(), channel_spy(), and gen_nextfile().
00529 { 00530 /* 00531 * Use fileexists_core() to find a file in a compatible 00532 * language and format, set up a suitable translator, 00533 * and open the stream. 00534 */ 00535 int fmts, res, buflen; 00536 char *buf; 00537 00538 if (!asis) { 00539 /* do this first, otherwise we detect the wrong writeformat */ 00540 ast_stopstream(chan); 00541 if (chan->generator) 00542 ast_deactivate_generator(chan); 00543 } 00544 if (preflang == NULL) 00545 preflang = ""; 00546 buflen = strlen(preflang) + strlen(filename) + 2; 00547 buf = alloca(buflen); 00548 if (buf == NULL) 00549 return NULL; 00550 fmts = fileexists_core(filename, NULL, preflang, buf, buflen); 00551 if (fmts > 0) 00552 fmts &= AST_FORMAT_AUDIO_MASK; 00553 if (fmts < 1) { 00554 ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename); 00555 return NULL; 00556 } 00557 chan->oldwriteformat = chan->writeformat; 00558 /* Set the channel to a format we can work with */ 00559 res = ast_set_write_format(chan, fmts); 00560 res = ast_filehelper(buf, chan, NULL, ACTION_OPEN); 00561 if (res >= 0) 00562 return chan->stream; 00563 return NULL; 00564 }
struct ast_filestream* ast_openvstream | ( | struct ast_channel * | chan, | |
const char * | filename, | |||
const char * | preflang | |||
) |
chan | channel to work with | |
filename | to use | |
preflang | prefered language to use Returns a ast_filestream pointer if it opens the file, NULL on error |
Definition at line 566 of file file.c.
References ACTION_OPEN, ast_filehelper(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_MAX_VIDEO, ast_getformatname(), ast_log(), ast_filestream::buf, fileexists_core(), fmt, format, LOG_WARNING, ast_channel::nativeformats, and ast_channel::vstream.
Referenced by ast_streamfile(), handle_getoption(), and handle_streamfile().
00567 { 00568 /* As above, but for video. But here we don't have translators 00569 * so we must enforce a format. 00570 */ 00571 unsigned int format; 00572 char *buf; 00573 int buflen; 00574 00575 if (preflang == NULL) 00576 preflang = ""; 00577 buflen = strlen(preflang) + strlen(filename) + 2; 00578 buf = alloca(buflen); 00579 if (buf == NULL) 00580 return NULL; 00581 00582 for (format = AST_FORMAT_MAX_AUDIO << 1; format <= AST_FORMAT_MAX_VIDEO; format = format << 1) { 00583 int fd; 00584 const char *fmt; 00585 00586 if (!(chan->nativeformats & format)) 00587 continue; 00588 fmt = ast_getformatname(format); 00589 if ( fileexists_core(filename, fmt, preflang, buf, buflen) < 1) /* no valid format */ 00590 continue; 00591 fd = ast_filehelper(buf, chan, fmt, ACTION_OPEN); 00592 if (fd >= 0) 00593 return chan->vstream; 00594 ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename); 00595 } 00596 return NULL; 00597 }
int ast_playstream | ( | struct ast_filestream * | s | ) |
s | filestream to play Returns 0 for success, -1 on failure |
Definition at line 666 of file file.c.
References AST_FORMAT_MAX_AUDIO, ast_readaudio_callback(), ast_readvideo_callback(), and s.
Referenced by ast_streamfile(), handle_getoption(), handle_streamfile(), and speech_streamfile().
00667 { 00668 if (s->fmt->format < AST_FORMAT_MAX_AUDIO) 00669 ast_readaudio_callback(s); 00670 else 00671 ast_readvideo_callback(s); 00672 return 0; 00673 }
static int ast_readaudio_callback | ( | void * | data | ) | [static] |
Definition at line 608 of file file.c.
References ast_log(), ast_sched_add(), ast_settimeout(), ast_write(), LOG_WARNING, and s.
Referenced by ast_playstream().
00609 { 00610 struct ast_filestream *s = data; 00611 int whennext = 0; 00612 00613 while(!whennext) { 00614 struct ast_frame *fr = s->fmt->read(s, &whennext); 00615 if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) { 00616 if (fr) 00617 ast_log(LOG_WARNING, "Failed to write frame\n"); 00618 s->owner->streamid = -1; 00619 #ifdef HAVE_ZAPTEL 00620 ast_settimeout(s->owner, 0, NULL, NULL); 00621 #endif 00622 return 0; 00623 } 00624 } 00625 if (whennext != s->lasttimeout) { 00626 #ifdef HAVE_ZAPTEL 00627 if (s->owner->timingfd > -1) 00628 ast_settimeout(s->owner, whennext, ast_readaudio_callback, s); 00629 else 00630 #endif 00631 s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_readaudio_callback, s); 00632 s->lasttimeout = whennext; 00633 return 0; 00634 } 00635 return 1; 00636 }
struct ast_filestream* ast_readfile | ( | const char * | filename, | |
const char * | type, | |||
const char * | comment, | |||
int | flags, | |||
int | check, | |||
mode_t | mode | |||
) |
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. Returns a struct ast_filestream on success, NULL on failure |
Definition at line 808 of file file.c.
References ast_free, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, build_filename(), ast_format::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, free, get_filestream(), LOG_WARNING, ast_filestream::mode, open_wrapper(), strdup, ast_filestream::trans, and ast_filestream::vfs.
Referenced by __ast_play_and_record(), cli_audio_convert(), and cli_audio_convert_deprecated().
00809 { 00810 FILE *bfile; 00811 struct ast_format *f; 00812 struct ast_filestream *fs = NULL; 00813 char *fn; 00814 00815 AST_RWLIST_RDLOCK(&formats); 00816 00817 AST_RWLIST_TRAVERSE(&formats, f, list) { 00818 fs = NULL; 00819 if (!exts_compare(f->exts, type)) 00820 continue; 00821 00822 fn = build_filename(filename, type); 00823 errno = 0; 00824 bfile = fopen(fn, "r"); 00825 if (!bfile || (fs = get_filestream(f, bfile)) == NULL || 00826 open_wrapper(fs) ) { 00827 ast_log(LOG_WARNING, "Unable to open %s\n", fn); 00828 if (fs) 00829 ast_free(fs); 00830 if (bfile) 00831 fclose(bfile); 00832 free(fn); 00833 continue; 00834 } 00835 /* found it */ 00836 fs->trans = NULL; 00837 fs->fmt = f; 00838 fs->flags = flags; 00839 fs->mode = mode; 00840 fs->filename = strdup(filename); 00841 fs->vfs = NULL; 00842 break; 00843 } 00844 00845 AST_RWLIST_UNLOCK(&formats); 00846 if (!fs) 00847 ast_log(LOG_WARNING, "No such format '%s'\n", type); 00848 00849 return fs; 00850 }
struct ast_frame* ast_readframe | ( | struct ast_filestream * | s | ) |
s | ast_filestream to act on Returns a frame or NULL if read failed |
Definition at line 599 of file file.c.
Referenced by __ast_play_and_record(), channel_spy(), cli_audio_convert(), cli_audio_convert_deprecated(), dictate_exec(), gen_readframe(), and moh_files_readframe().
00600 { 00601 struct ast_frame *f = NULL; 00602 int whennext = 0; 00603 if (s && s->fmt) 00604 f = s->fmt->read(s, &whennext); 00605 return f; 00606 }
static int ast_readvideo_callback | ( | void * | data | ) | [static] |
Definition at line 638 of file file.c.
References ast_log(), ast_sched_add(), ast_write(), LOG_WARNING, and s.
Referenced by ast_playstream().
00639 { 00640 struct ast_filestream *s = data; 00641 int whennext = 0; 00642 00643 while (!whennext) { 00644 struct ast_frame *fr = s->fmt->read(s, &whennext); 00645 if (!fr || ast_write(s->owner, fr)) { /* no stream or error, as above */ 00646 if (fr) 00647 ast_log(LOG_WARNING, "Failed to write frame\n"); 00648 s->owner->vstreamid = -1; 00649 return 0; 00650 } 00651 } 00652 if (whennext != s->lasttimeout) { 00653 s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext/8, ast_readvideo_callback, s); 00654 s->lasttimeout = whennext; 00655 return 0; 00656 } 00657 return 1; 00658 }
static AST_RWLIST_HEAD_STATIC | ( | formats | , | |
ast_format | ||||
) | [static] |
int ast_seekstream | ( | struct ast_filestream * | fs, | |
off_t | sample_offset, | |||
int | whence | |||
) |
fs | ast_filestream to perform seek on | |
sample_offset | numbers of samples to seek | |
whence | SEEK_SET, SEEK_CUR, SEEK_END Returns 0 for success, or -1 for error |
Definition at line 675 of file file.c.
References ast_filestream::fmt, and ast_format::seek.
Referenced by __ast_read(), ast_control_streamfile(), ast_stream_fastforward(), ast_stream_rewind(), ast_write(), dictate_exec(), handle_getoption(), handle_recordfile(), and handle_streamfile().
int ast_stopstream | ( | struct ast_channel * | c | ) |
c | The channel you wish to stop playback on Stop playback of a stream Returns 0 regardless |
Definition at line 131 of file file.c.
References ast_closestream(), ast_log(), ast_set_write_format(), LOG_WARNING, ast_channel::oldwriteformat, ast_channel::stream, and ast_channel::vstream.
Referenced by app_exec(), ast_adsi_transmit_message_full(), ast_app_getdata(), 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_number_full_cz(), 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_ge(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_it(), 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_tw(), background_detect_exec(), builtin_blindtransfer(), conf_exec(), conf_run(), directory_exec(), handle_getoption(), handle_streamfile(), ices_exec(), ivr_dispatch(), leave_voicemail(), mp3_exec(), NBScat_exec(), nv_background_detect_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_file(), play_mailbox_owner(), playback_exec(), queue_exec(), read_exec(), recordthread(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), saycharstr(), sayfile(), saynum(), send_morse(), send_tone_telemetry(), send_waveform_to_channel(), speech_background(), vm_authenticate(), vm_execmain(), wait_for_winner(), waitstream_core(), and zapateller_exec().
00132 { 00133 /* Stop a running stream if there is one */ 00134 if (tmp->stream) { 00135 ast_closestream(tmp->stream); 00136 tmp->stream = NULL; 00137 if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat)) 00138 ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat); 00139 } 00140 /* Stop the video stream too */ 00141 if (tmp->vstream != NULL) { 00142 ast_closestream(tmp->vstream); 00143 tmp->vstream = NULL; 00144 } 00145 return 0; 00146 }
int ast_stream_and_wait | ( | struct ast_channel * | chan, | |
const char * | file, | |||
const char * | language, | |||
const char * | digits | |||
) |
Definition at line 1128 of file file.c.
References ast_streamfile(), ast_strlen_zero(), and ast_waitstream().
Referenced by __ast_play_and_record(), app_exec(), ast_record_review(), bridge_playfile(), builtin_atxfer(), builtin_automonitor(), builtin_blindtransfer(), directory_exec(), invent_message(), ivr_dispatch(), leave_voicemail(), park_exec(), play_mailbox_owner(), play_message_callerid(), play_record_review(), and wait_file2().
01130 { 01131 int res = 0; 01132 if (!ast_strlen_zero(file)) { 01133 res = ast_streamfile(chan, file, language); 01134 if (!res) 01135 res = ast_waitstream(chan, digits); 01136 } 01137 return res; 01138 }
int ast_stream_fastforward | ( | struct ast_filestream * | fs, | |
off_t | ms | |||
) |
fs | filestream to act on | |
ms | milliseconds to move Returns 0 for success, or -1 for error |
Definition at line 690 of file file.c.
References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.
Referenced by waitstream_core().
00691 { 00692 return ast_seekstream(fs, ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR); 00693 }
int ast_stream_rewind | ( | struct ast_filestream * | fs, | |
off_t | ms | |||
) |
fs | filestream to act on | |
ms | milliseconds to move Returns 0 for success, or -1 for error |
Definition at line 695 of file file.c.
References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.
Referenced by __ast_play_and_record(), handle_recordfile(), and waitstream_core().
00696 { 00697 return ast_seekstream(fs, -ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR); 00698 }
int ast_streamfile | ( | struct ast_channel * | c, | |
const char * | filename, | |||
const char * | preflang | |||
) |
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. Returns 0 on success, or -1 on failure. |
Definition at line 780 of file file.c.
References ast_applystream(), ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_verbose(), fmt, ast_filestream::fmt, ast_format::format, LOG_DEBUG, LOG_WARNING, ast_channel::nativeformats, option_verbose, VERBOSE_PREFIX_3, and ast_filestream::vfs.
Referenced by __login_exec(), agent_call(), 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_ge(), ast_say_date_gr(), ast_say_date_nl(), 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_ge(), ast_say_datetime_gr(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_tw(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_number_full_cz(), 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_ge(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_it(), 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_tw(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_ge(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_tw(), ast_stream_and_wait(), background_detect_exec(), check_availability(), check_beep(), common_exec(), conf_exec(), conf_run(), do_directory(), forward_message(), gr_say_number_female(), handle_recordfile(), leave_voicemail(), nv_background_detect_exec(), page_exec(), park_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), playback_exec(), privacy_exec(), retrydial_exec(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), sayfile(), ss_thread(), vm_authenticate(), wait_file(), and wait_for_winner().
00781 { 00782 struct ast_filestream *fs; 00783 struct ast_filestream *vfs=NULL; 00784 char fmt[256]; 00785 00786 fs = ast_openstream(chan, filename, preflang); 00787 if (fs) 00788 vfs = ast_openvstream(chan, filename, preflang); 00789 if (vfs) 00790 ast_log(LOG_DEBUG, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format)); 00791 if (fs){ 00792 if (ast_applystream(chan, fs)) 00793 return -1; 00794 if (vfs && ast_applystream(chan, vfs)) 00795 return -1; 00796 ast_playstream(fs); 00797 if (vfs) 00798 ast_playstream(vfs); 00799 if (option_verbose > 2) 00800 ast_verbose(VERBOSE_PREFIX_3 "<%s> Playing '%s' (language '%s')\n", chan->name, filename, preflang ? preflang : "default"); 00801 00802 return 0; 00803 } 00804 ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), chan->nativeformats), strerror(errno)); 00805 return -1; 00806 }
off_t ast_tellstream | ( | struct ast_filestream * | fs | ) |
fs | fs to act on Returns a long as a sample offset into stream |
Definition at line 685 of file file.c.
References ast_filestream::fmt, and ast_format::tell.
Referenced by ast_control_streamfile(), handle_getoption(), handle_recordfile(), and handle_streamfile().
int ast_truncstream | ( | struct ast_filestream * | fs | ) |
fs | filestream to act on Returns 0 for success, or -1 for error |
Definition at line 680 of file file.c.
References ast_filestream::fmt, and ast_format::trunc.
Referenced by __ast_play_and_record(), and handle_recordfile().
int ast_waitstream | ( | struct ast_channel * | c, | |
const char * | breakon | |||
) |
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, Returns 0 if the stream finishes, the character if it was interrupted, and -1 on error |
Definition at line 1101 of file file.c.
References waitstream_core().
Referenced by __login_exec(), agent_call(), app_exec(), ast_app_getdata(), ast_play_and_wait(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_ge(), ast_say_date_gr(), ast_say_date_nl(), 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_ge(), ast_say_datetime_gr(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_tw(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_number_full_cz(), 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_ge(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_it(), 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_tw(), ast_say_time_de(), ast_say_time_en(), ast_say_time_ge(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_tw(), ast_stream_and_wait(), check_availability(), check_beep(), common_exec(), conf_exec(), conf_run(), directory_exec(), gr_say_number_female(), handle_recordfile(), leave_voicemail(), page_exec(), park_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), playback_exec(), privacy_exec(), retrydial_exec(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), saycharstr(), sayfile(), saynum(), send_morse(), send_tone_telemetry(), ss_thread(), vm_authenticate(), and wait_file().
01102 { 01103 return waitstream_core(c, breakon, NULL, NULL, 0, -1, -1, NULL); 01104 }
int ast_waitstream_exten | ( | struct ast_channel * | c, | |
const char * | context | |||
) |
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, Returns 0 if the stream finishes, the character if it was interrupted, and -1 on error |
Definition at line 1112 of file file.c.
References ast_channel::context, and waitstream_core().
Referenced by pbx_builtin_background().
01113 { 01114 /* Waitstream, with return in the case of a valid 1 digit extension */ 01115 /* in the current or specified context being pressed */ 01116 01117 if (!context) 01118 context = c->context; 01119 return waitstream_core(c, NULL, NULL, NULL, 0, 01120 -1, -1, context); 01121 }
int ast_waitstream_fr | ( | struct ast_channel * | c, | |
const char * | breakon, | |||
const char * | forward, | |||
const char * | rewind, | |||
int | ms | |||
) |
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, Returns 0 if the stream finishes, the character if it was interrupted, and -1 on error |
Definition at line 1095 of file file.c.
References waitstream_core().
Referenced by ast_control_streamfile().
01096 { 01097 return waitstream_core(c, breakon, forward, rewind, ms, 01098 -1 /* no audiofd */, -1 /* no cmdfd */, NULL /* no context */); 01099 }
int ast_waitstream_full | ( | struct ast_channel * | c, | |
const char * | breakon, | |||
int | audiofd, | |||
int | cmdfd | |||
) |
Definition at line 1106 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_number_full_cz(), 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_ge(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_it(), 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_tw(), handle_getoption(), handle_streamfile(), pl_odtworz_plik(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), and say_phonetic_str_full().
01107 { 01108 return waitstream_core(c, breakon, NULL, NULL, 0, 01109 audiofd, cmdfd, NULL /* no context */); 01110 }
struct ast_filestream* ast_writefile | ( | const char * | filename, | |
const char * | type, | |||
const char * | comment, | |||
int | flags, | |||
int | check, | |||
mode_t | mode | |||
) |
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. Returns a struct ast_filestream on success, NULL on failure |
Definition at line 852 of file file.c.
References ast_free, ast_log(), ast_opt_cache_record_files, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, ast_filestream::buf, build_filename(), ast_format::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, free, get_filestream(), LOG_WARNING, ast_filestream::mode, ast_filestream::realfilename, record_cache_dir, rewrite_wrapper(), ast_format::seek, strdup, ast_filestream::trans, and ast_filestream::vfs.
Referenced by __ast_play_and_record(), ast_monitor_start(), ast_writestream(), cli_audio_convert(), cli_audio_convert_deprecated(), dictate_exec(), handle_recordfile(), mixmonitor_thread(), recordthread(), and rpt().
00853 { 00854 int fd, myflags = 0; 00855 /* compiler claims this variable can be used before initialization... */ 00856 FILE *bfile = NULL; 00857 struct ast_format *f; 00858 struct ast_filestream *fs = NULL; 00859 char *buf = NULL; 00860 size_t size = 0; 00861 int format_found = 0; 00862 00863 AST_RWLIST_RDLOCK(&formats); 00864 00865 /* set the O_TRUNC flag if and only if there is no O_APPEND specified */ 00866 /* We really can't use O_APPEND as it will break WAV header updates */ 00867 if (flags & O_APPEND) { 00868 flags &= ~O_APPEND; 00869 } else { 00870 myflags = O_TRUNC; 00871 } 00872 00873 myflags |= O_WRONLY | O_CREAT; 00874 00875 /* XXX need to fix this - we should just do the fopen, 00876 * not open followed by fdopen() 00877 */ 00878 AST_RWLIST_TRAVERSE(&formats, f, list) { 00879 char *fn, *orig_fn = NULL; 00880 if (fs) 00881 break; 00882 00883 if (!exts_compare(f->exts, type)) 00884 continue; 00885 else 00886 format_found = 1; 00887 00888 fn = build_filename(filename, type); 00889 fd = open(fn, flags | myflags, mode); 00890 if (fd > -1) { 00891 /* fdopen() the resulting file stream */ 00892 bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w"); 00893 if (!bfile) { 00894 ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno)); 00895 close(fd); 00896 fd = -1; 00897 } 00898 } 00899 00900 if (ast_opt_cache_record_files && (fd > -1)) { 00901 char *c; 00902 00903 fclose(bfile); /* this also closes fd */ 00904 /* 00905 We touch orig_fn just as a place-holder so other things (like vmail) see the file is there. 00906 What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place. 00907 */ 00908 orig_fn = ast_strdupa(fn); 00909 for (c = fn; *c; c++) 00910 if (*c == '/') 00911 *c = '_'; 00912 00913 size = strlen(fn) + strlen(record_cache_dir) + 2; 00914 buf = alloca(size); 00915 strcpy(buf, record_cache_dir); 00916 strcat(buf, "/"); 00917 strcat(buf, fn); 00918 free(fn); 00919 fn = buf; 00920 fd = open(fn, flags | myflags, mode); 00921 if (fd > -1) { 00922 /* fdopen() the resulting file stream */ 00923 bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w"); 00924 if (!bfile) { 00925 ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno)); 00926 close(fd); 00927 fd = -1; 00928 } 00929 } 00930 } 00931 if (fd > -1) { 00932 errno = 0; 00933 fs = get_filestream(f, bfile); 00934 if (!fs || rewrite_wrapper(fs, comment)) { 00935 ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn); 00936 close(fd); 00937 if (orig_fn) { 00938 unlink(fn); 00939 unlink(orig_fn); 00940 } 00941 if (fs) 00942 ast_free(fs); 00943 fs = NULL; 00944 continue; 00945 } 00946 fs->trans = NULL; 00947 fs->fmt = f; 00948 fs->flags = flags; 00949 fs->mode = mode; 00950 if (orig_fn) { 00951 fs->realfilename = strdup(orig_fn); 00952 fs->filename = strdup(fn); 00953 } else { 00954 fs->realfilename = NULL; 00955 fs->filename = strdup(filename); 00956 } 00957 fs->vfs = NULL; 00958 /* If truncated, we'll be at the beginning; if not truncated, then append */ 00959 f->seek(fs, 0, SEEK_END); 00960 } else if (errno != EEXIST) { 00961 ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno)); 00962 if (orig_fn) 00963 unlink(orig_fn); 00964 } 00965 /* if buf != NULL then fn is already free and pointing to it */ 00966 if (!buf) 00967 free(fn); 00968 } 00969 00970 AST_RWLIST_UNLOCK(&formats); 00971 00972 if (!format_found) 00973 ast_log(LOG_WARNING, "No such format '%s'\n", type); 00974 00975 return fs; 00976 }
int ast_writestream | ( | struct ast_filestream * | fs, | |
struct ast_frame * | f | |||
) |
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 Returns 0 on success, -1 on failure. |
Definition at line 148 of file file.c.
References AST_FORMAT_MAX_AUDIO, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_writefile(), ast_writestream(), f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, ast_format::format, ast_filestream::lastwriteformat, LOG_DEBUG, LOG_WARNING, ast_filestream::mode, ast_format::name, ast_filestream::trans, type, ast_filestream::vfs, and ast_format::write.
Referenced by __ast_play_and_record(), __ast_read(), ast_write(), ast_writestream(), cli_audio_convert(), cli_audio_convert_deprecated(), dictate_exec(), handle_recordfile(), mixmonitor_thread(), recordthread(), and rpt().
00149 { 00150 int res = -1; 00151 int alt = 0; 00152 if (f->frametype == AST_FRAME_VIDEO) { 00153 if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) { 00154 /* This is the audio portion. Call the video one... */ 00155 if (!fs->vfs && fs->filename) { 00156 const char *type = ast_getformatname(f->subclass & ~0x1); 00157 fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode); 00158 ast_log(LOG_DEBUG, "Opened video output file\n"); 00159 } 00160 if (fs->vfs) 00161 return ast_writestream(fs->vfs, f); 00162 /* else ignore */ 00163 return 0; 00164 } else { 00165 /* Might / might not have mark set */ 00166 alt = 1; 00167 } 00168 } else if (f->frametype != AST_FRAME_VOICE) { 00169 ast_log(LOG_WARNING, "Tried to write non-voice frame\n"); 00170 return -1; 00171 } 00172 if (((fs->fmt->format | alt) & f->subclass) == f->subclass) { 00173 res = fs->fmt->write(fs, f); 00174 if (res < 0) 00175 ast_log(LOG_WARNING, "Natural write failed\n"); 00176 else if (res > 0) 00177 ast_log(LOG_WARNING, "Huh??\n"); 00178 } else { 00179 /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't 00180 the one we've setup a translator for, we do the "wrong thing" XXX */ 00181 if (fs->trans && f->subclass != fs->lastwriteformat) { 00182 ast_translator_free_path(fs->trans); 00183 fs->trans = NULL; 00184 } 00185 if (!fs->trans) 00186 fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass); 00187 if (!fs->trans) 00188 ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n", 00189 fs->fmt->name, ast_getformatname(f->subclass)); 00190 else { 00191 struct ast_frame *trf; 00192 fs->lastwriteformat = f->subclass; 00193 /* Get the translated frame but don't consume the original in case they're using it on another stream */ 00194 trf = ast_translate(fs->trans, f, 0); 00195 if (trf) { 00196 res = fs->fmt->write(fs, trf); 00197 if (res) 00198 ast_log(LOG_WARNING, "Translated frame write failed\n"); 00199 } else 00200 res = 0; 00201 } 00202 } 00203 return res; 00204 }
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 249 of file file.c.
References asprintf, and ast_config_AST_DATA_DIR.
Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().
00250 { 00251 char *fn = NULL; 00252 00253 if (!strcmp(ext, "wav49")) 00254 ext = "WAV"; 00255 00256 if (filename[0] == '/') 00257 asprintf(&fn, "%s.%s", filename, ext); 00258 else 00259 asprintf(&fn, "%s/sounds/%s.%s", 00260 ast_config_AST_DATA_DIR, filename, ext); 00261 return fn; 00262 }
static int copy | ( | const char * | infile, | |
const char * | outfile | |||
) | [static] |
Definition at line 206 of file file.c.
References ast_log(), len, and LOG_WARNING.
Referenced by action_getvar(), ast_filehelper(), copy_file(), and iax2_register().
00207 { 00208 int ifd, ofd, len; 00209 char buf[4096]; /* XXX make it lerger. */ 00210 00211 if ((ifd = open(infile, O_RDONLY)) < 0) { 00212 ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile); 00213 return -1; 00214 } 00215 if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) { 00216 ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile); 00217 close(ifd); 00218 return -1; 00219 } 00220 while ( (len = read(ifd, buf, sizeof(buf)) ) ) { 00221 int res; 00222 if (len < 0) { 00223 ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno)); 00224 break; 00225 } 00226 /* XXX handle partial writes */ 00227 res = write(ofd, buf, len); 00228 if (res != len) { 00229 ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno)); 00230 len = -1; /* error marker */ 00231 break; 00232 } 00233 } 00234 close(ifd); 00235 close(ofd); 00236 if (len < 0) { 00237 unlink(outfile); 00238 return -1; /* error */ 00239 } 00240 return 0; /* success */ 00241 }
static int exts_compare | ( | const char * | exts, | |
const char * | type | |||
) | [static] |
Definition at line 266 of file file.c.
Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().
00267 { 00268 char tmp[256]; 00269 char *stringp = tmp, *ext; 00270 00271 ast_copy_string(tmp, exts, sizeof(tmp)); 00272 while ((ext = strsep(&stringp, "|"))) { 00273 if (!strcmp(ext, type)) 00274 return 1; 00275 } 00276 00277 return 0; 00278 }
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 474 of file file.c.
References ACTION_EXISTS, ast_filehelper(), ast_log(), LOG_WARNING, and offset.
Referenced by ast_fileexists(), ast_openstream_full(), and ast_openvstream().
00476 { 00477 int res = -1; 00478 int langlen; /* length of language string */ 00479 const char *c = strrchr(filename, '/'); 00480 int offset = c ? c - filename + 1 : 0; /* points right after the last '/' */ 00481 00482 if (preflang == NULL) 00483 preflang = ""; 00484 langlen = strlen(preflang); 00485 00486 if (buflen < langlen + strlen(filename) + 2) { 00487 ast_log(LOG_WARNING, "buffer too small\n"); 00488 buf[0] = '\0'; /* set to empty */ 00489 buf = alloca(langlen + strlen(filename) + 2); /* room for everything */ 00490 } 00491 if (buf == NULL) 00492 return 0; 00493 buf[0] = '\0'; 00494 for (;;) { 00495 if (ast_language_is_prefix) { /* new layout */ 00496 if (langlen) { 00497 strcpy(buf, preflang); 00498 buf[langlen] = '/'; 00499 strcpy(buf + langlen + 1, filename); 00500 } else 00501 strcpy(buf, filename); /* first copy the full string */ 00502 } else { /* old layout */ 00503 strcpy(buf, filename); /* first copy the full string */ 00504 if (langlen) { 00505 /* insert the language and suffix if needed */ 00506 strcpy(buf + offset, preflang); 00507 sprintf(buf + offset + langlen, "/%s", filename + offset); 00508 } 00509 } 00510 res = ast_filehelper(buf, NULL, fmt, ACTION_EXISTS); 00511 if (res > 0) /* found format */ 00512 break; 00513 if (langlen == 0) /* no more formats */ 00514 break; 00515 if (preflang[langlen] == '_') /* we are on the local suffix */ 00516 langlen = 0; /* try again with no language */ 00517 else 00518 langlen = (c = strchr(preflang, '_')) ? c - preflang : 0; 00519 } 00520 return res; 00521 }
static int fn_wrapper | ( | struct ast_filestream * | s, | |
const char * | comment, | |||
enum wrap_fn | mode | |||
) | [static] |
Definition at line 304 of file file.c.
References ast_log(), ast_module_ref(), f, LOG_WARNING, ast_format::module, ast_format::name, ast_format::open, ast_format::rewrite, s, and WRAP_OPEN.
Referenced by open_wrapper(), and rewrite_wrapper().
00305 { 00306 struct ast_format *f = s->fmt; 00307 int ret = -1; 00308 00309 if (mode == WRAP_OPEN && f->open && f->open(s)) 00310 ast_log(LOG_WARNING, "Unable to open format %s\n", f->name); 00311 else if (mode == WRAP_REWRITE && f->rewrite && f->rewrite(s, comment)) 00312 ast_log(LOG_WARNING, "Unable to rewrite format %s\n", f->name); 00313 else { 00314 /* preliminary checks succeed. update usecount */ 00315 ast_module_ref(f->module); 00316 ret = 0; 00317 } 00318 return ret; 00319 }
static struct ast_filestream* get_filestream | ( | struct ast_format * | fmt, | |
FILE * | bfile | |||
) | [static] |
Definition at line 280 of file file.c.
References ast_calloc, fmt, and s.
Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().
00281 { 00282 struct ast_filestream *s; 00283 00284 int l = sizeof(*s) + fmt->buf_size + fmt->desc_size; /* total allocation size */ 00285 if ( (s = ast_calloc(1, l)) == NULL) 00286 return NULL; 00287 s->fmt = fmt; 00288 s->f = bfile; 00289 00290 if (fmt->desc_size) 00291 s->private = ((char *)(s+1)) + fmt->buf_size; 00292 if (fmt->buf_size) 00293 s->buf = (char *)(s+1); 00294 s->fr.src = fmt->name; 00295 return s; 00296 }
static int open_wrapper | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 326 of file file.c.
References fn_wrapper(), s, and WRAP_OPEN.
Referenced by ast_filehelper(), and ast_readfile().
00327 { 00328 return fn_wrapper(s, NULL, WRAP_OPEN); 00329 }
static int rewrite_wrapper | ( | struct ast_filestream * | s, | |
const char * | comment | |||
) | [static] |
Definition at line 321 of file file.c.
References fn_wrapper(), and s.
Referenced by ast_writefile().
00322 { 00323 return fn_wrapper(s, comment, WRAP_REWRITE); 00324 }
static int show_file_formats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1140 of file file.c.
References ast_cli(), ast_getformatname(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_format::exts, f, ast_format::format, FORMAT, FORMAT2, ast_format::name, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01141 { 01142 #define FORMAT "%-10s %-10s %-20s\n" 01143 #define FORMAT2 "%-10s %-10s %-20s\n" 01144 struct ast_format *f; 01145 int count_fmt = 0; 01146 01147 if (argc != 4) 01148 return RESULT_SHOWUSAGE; 01149 ast_cli(fd, FORMAT, "Format", "Name", "Extensions"); 01150 01151 AST_RWLIST_RDLOCK(&formats); 01152 AST_RWLIST_TRAVERSE(&formats, f, list) { 01153 ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts); 01154 count_fmt++; 01155 } 01156 AST_RWLIST_UNLOCK(&formats); 01157 ast_cli(fd, "%d file formats registered.\n", count_fmt); 01158 return RESULT_SUCCESS; 01159 #undef FORMAT 01160 #undef FORMAT2 01161 }
static int show_file_formats_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1163 of file file.c.
References ast_cli(), ast_getformatname(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_format::exts, f, ast_format::format, FORMAT, FORMAT2, LOG_WARNING, ast_format::name, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01164 { 01165 #define FORMAT "%-10s %-10s %-20s\n" 01166 #define FORMAT2 "%-10s %-10s %-20s\n" 01167 struct ast_format *f; 01168 int count_fmt = 0; 01169 01170 if (argc != 3) 01171 return RESULT_SHOWUSAGE; 01172 ast_cli(fd, FORMAT, "Format", "Name", "Extensions"); 01173 01174 if (AST_LIST_LOCK(&formats)) { 01175 ast_log(LOG_WARNING, "Unable to lock format list\n"); 01176 return -1; 01177 } 01178 01179 AST_LIST_TRAVERSE(&formats, f, list) { 01180 ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts); 01181 count_fmt++; 01182 } 01183 AST_LIST_UNLOCK(&formats); 01184 ast_cli(fd, "%d file formats registered.\n", count_fmt); 01185 return RESULT_SUCCESS; 01186 #undef FORMAT 01187 #undef FORMAT2 01188 }
static int waitstream_core | ( | struct ast_channel * | c, | |
const char * | breakon, | |||
const char * | forward, | |||
const char * | rewind, | |||
int | skip_ms, | |||
int | audiofd, | |||
int | cmdfd, | |||
const char * | context | |||
) | [static] |
the core of all waitstream() functions
Definition at line 981 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_UNHOLD, AST_CONTROL_VIDUPDATE, ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, 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_stream_fastforward(), ast_stream_rewind(), ast_waitfor(), ast_waitfor_nandfds(), ast_channel::cid, ast_callerid::cid_num, ast_frame::data, ast_frame::datalen, exten, ast_frame::frametype, LOG_WARNING, ast_channel::sched, ast_channel::stream, and ast_frame::subclass.
Referenced by ast_waitstream(), ast_waitstream_exten(), ast_waitstream_fr(), and ast_waitstream_full().
00984 { 00985 if (!breakon) 00986 breakon = ""; 00987 if (!forward) 00988 forward = ""; 00989 if (!rewind) 00990 rewind = ""; 00991 00992 /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */ 00993 ast_set_flag(c, AST_FLAG_END_DTMF_ONLY); 00994 00995 while (c->stream) { 00996 int res; 00997 int ms = ast_sched_wait(c->sched); 00998 if (ms < 0 && !c->timingfunc) { 00999 ast_stopstream(c); 01000 break; 01001 } 01002 if (ms < 0) 01003 ms = 1000; 01004 if (cmdfd < 0) { 01005 res = ast_waitfor(c, ms); 01006 if (res < 0) { 01007 ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno)); 01008 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 01009 return res; 01010 } 01011 } else { 01012 int outfd; 01013 struct ast_channel *rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 01014 if (!rchan && (outfd < 0) && (ms)) { 01015 /* Continue */ 01016 if (errno == EINTR) 01017 continue; 01018 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 01019 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 01020 return -1; 01021 } else if (outfd > -1) { /* this requires cmdfd set */ 01022 /* The FD we were watching has something waiting */ 01023 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 01024 return 1; 01025 } 01026 /* if rchan is set, it is 'c' */ 01027 res = rchan ? 1 : 0; /* map into 'res' values */ 01028 } 01029 if (res > 0) { 01030 struct ast_frame *fr = ast_read(c); 01031 if (!fr) { 01032 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 01033 return -1; 01034 } 01035 switch(fr->frametype) { 01036 case AST_FRAME_DTMF_END: 01037 if (context) { 01038 const char exten[2] = { fr->subclass, '\0' }; 01039 if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) { 01040 res = fr->subclass; 01041 ast_frfree(fr); 01042 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 01043 return res; 01044 } 01045 } else { 01046 res = fr->subclass; 01047 if (strchr(forward,res)) { 01048 ast_stream_fastforward(c->stream, skip_ms); 01049 } else if (strchr(rewind,res)) { 01050 ast_stream_rewind(c->stream, skip_ms); 01051 } else if (strchr(breakon, res)) { 01052 ast_frfree(fr); 01053 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 01054 return res; 01055 } 01056 } 01057 break; 01058 case AST_FRAME_CONTROL: 01059 switch(fr->subclass) { 01060 case AST_CONTROL_HANGUP: 01061 case AST_CONTROL_BUSY: 01062 case AST_CONTROL_CONGESTION: 01063 ast_frfree(fr); 01064 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 01065 return -1; 01066 case AST_CONTROL_RINGING: 01067 case AST_CONTROL_ANSWER: 01068 case AST_CONTROL_VIDUPDATE: 01069 case AST_CONTROL_HOLD: 01070 case AST_CONTROL_UNHOLD: 01071 /* Unimportant */ 01072 break; 01073 default: 01074 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass); 01075 } 01076 break; 01077 case AST_FRAME_VOICE: 01078 /* Write audio if appropriate */ 01079 if (audiofd > -1) 01080 write(audiofd, fr->data, fr->datalen); 01081 default: 01082 /* Ignore all others */ 01083 break; 01084 } 01085 ast_frfree(fr); 01086 } 01087 ast_sched_runq(c->sched); 01088 } 01089 01090 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 01091 01092 return (c->_softhangup ? -1 : 0); 01093 }
int ast_language_is_prefix = 1 |
struct ast_cli_entry cli_file[] |
Initial value:
{ { { "core", "show", "file", "formats" }, show_file_formats, "Displays file formats", show_file_formats_usage, NULL, &cli_show_file_formats_deprecated }, }
Definition at line 1199 of file file.c.
Referenced by ast_file_init().
Initial value:
{ { "show", "file", "formats" }, show_file_formats_deprecated, NULL, NULL }
char show_file_formats_usage[] |