#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 326 of file file.c.
00326 { 00327 ACTION_EXISTS = 1, /* return matching format if file exists, 0 otherwise */ 00328 ACTION_DELETE, /* delete file, return 0 on success, -1 on error */ 00329 ACTION_RENAME, /* rename file. return 0 on success, -1 on error */ 00330 ACTION_OPEN, 00331 ACTION_COPY /* copy file. return 0 on success, -1 on error */ 00332 };
| 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 655 of file file.c.
References s.
Referenced by ast_streamfile(), handle_getoption(), handle_recordfile(), handle_streamfile(), and speech_streamfile().
00656 { 00657 s->owner = chan; 00658 return 0; 00659 }
| 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 695 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(), and moh_files_release().
00696 { 00697 char *cmd = NULL; 00698 size_t size = 0; 00699 /* Stop a running stream if there is one */ 00700 if (f->owner) { 00701 if (f->fmt->format < AST_FORMAT_MAX_AUDIO) { 00702 f->owner->stream = NULL; 00703 if (f->owner->streamid > -1) 00704 ast_sched_del(f->owner->sched, f->owner->streamid); 00705 f->owner->streamid = -1; 00706 #ifdef HAVE_ZAPTEL 00707 ast_settimeout(f->owner, 0, NULL, NULL); 00708 #endif 00709 } else { 00710 f->owner->vstream = NULL; 00711 if (f->owner->vstreamid > -1) 00712 ast_sched_del(f->owner->sched, f->owner->vstreamid); 00713 f->owner->vstreamid = -1; 00714 } 00715 } 00716 /* destroy the translator on exit */ 00717 if (f->trans) 00718 ast_translator_free_path(f->trans); 00719 00720 if (f->realfilename && f->filename) { 00721 size = strlen(f->filename) + strlen(f->realfilename) + 15; 00722 cmd = alloca(size); 00723 memset(cmd,0,size); 00724 snprintf(cmd,size,"/bin/mv -f %s %s",f->filename,f->realfilename); 00725 ast_safe_system(cmd); 00726 } 00727 00728 if (f->filename) 00729 free(f->filename); 00730 if (f->realfilename) 00731 free(f->realfilename); 00732 if (f->fmt->close) 00733 f->fmt->close(f); 00734 fclose(f->f); 00735 if (f->vfs) 00736 ast_closestream(f->vfs); 00737 ast_module_unref(f->fmt->module); 00738 free(f); 00739 return 0; 00740 }
| 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 1185 of file file.c.
References ast_cli_register_multiple(), and cli_file.
Referenced by main().
01186 { 01187 ast_cli_register_multiple(cli_file, sizeof(cli_file) / sizeof(struct ast_cli_entry)); 01188 return 0; 01189 }
| 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 770 of file file.c.
References ast_filehelper().
Referenced by copy_file().
00771 { 00772 return ast_filehelper(filename, filename2, fmt, ACTION_COPY); 00773 }
| 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 760 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(), and vm_delete().
00761 { 00762 return ast_filehelper(filename, NULL, fmt, ACTION_DELETE); 00763 }
| 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 746 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(), rxfax_exec(), vm_intro(), vm_newuser(), and vm_tempgreeting().
00747 { 00748 char *buf; 00749 int buflen; 00750 00751 if (preflang == NULL) 00752 preflang = ""; 00753 buflen = strlen(preflang) + strlen(filename) + 2; /* room for everything */ 00754 buf = alloca(buflen); 00755 if (buf == NULL) 00756 return 0; 00757 return fileexists_core(filename, fmt, preflang, buf, buflen); 00758 }
| 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 343 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().
00344 { 00345 struct ast_format *f; 00346 int res = (action == ACTION_EXISTS) ? 0 : -1; 00347 00348 AST_RWLIST_RDLOCK(&formats); 00349 /* Check for a specific format */ 00350 AST_RWLIST_TRAVERSE(&formats, f, list) { 00351 char *stringp, *ext = NULL; 00352 00353 if (fmt && !exts_compare(f->exts, fmt)) 00354 continue; 00355 00356 /* Look for a file matching the supported extensions. 00357 * The file must exist, and for OPEN, must match 00358 * one of the formats supported by the channel. 00359 */ 00360 stringp = ast_strdupa(f->exts); /* this is in the stack so does not need to be freed */ 00361 while ( (ext = strsep(&stringp, "|")) ) { 00362 struct stat st; 00363 char *fn = build_filename(filename, ext); 00364 00365 if (fn == NULL) 00366 continue; 00367 00368 if ( stat(fn, &st) ) { /* file not existent */ 00369 free(fn); 00370 continue; 00371 } 00372 /* for 'OPEN' we need to be sure that the format matches 00373 * what the channel can process 00374 */ 00375 if (action == ACTION_OPEN) { 00376 struct ast_channel *chan = (struct ast_channel *)arg2; 00377 FILE *bfile; 00378 struct ast_filestream *s; 00379 00380 if ( !(chan->writeformat & f->format) && 00381 !(f->format >= AST_FORMAT_MAX_AUDIO && fmt)) { 00382 free(fn); 00383 continue; /* not a supported format */ 00384 } 00385 if ( (bfile = fopen(fn, "r")) == NULL) { 00386 free(fn); 00387 continue; /* cannot open file */ 00388 } 00389 s = get_filestream(f, bfile); 00390 if (!s) { 00391 fclose(bfile); 00392 free(fn); /* cannot allocate descriptor */ 00393 continue; 00394 } 00395 if (open_wrapper(s)) { 00396 fclose(bfile); 00397 free(fn); 00398 free(s); 00399 continue; /* cannot run open on file */ 00400 } 00401 /* ok this is good for OPEN */ 00402 res = 1; /* found */ 00403 s->lasttimeout = -1; 00404 s->fmt = f; 00405 s->trans = NULL; 00406 s->filename = NULL; 00407 if (s->fmt->format < AST_FORMAT_MAX_AUDIO) { 00408 if (chan->stream) 00409 ast_closestream(chan->stream); 00410 chan->stream = s; 00411 } else { 00412 if (chan->vstream) 00413 ast_closestream(chan->vstream); 00414 chan->vstream = s; 00415 } 00416 free(fn); 00417 break; 00418 } 00419 switch (action) { 00420 case ACTION_OPEN: 00421 break; /* will never get here */ 00422 00423 case ACTION_EXISTS: /* return the matching format */ 00424 res |= f->format; 00425 break; 00426 00427 case ACTION_DELETE: 00428 if ( (res = unlink(fn)) ) 00429 ast_log(LOG_WARNING, "unlink(%s) failed: %s\n", fn, strerror(errno)); 00430 break; 00431 00432 case ACTION_RENAME: 00433 case ACTION_COPY: { 00434 char *nfn = build_filename((const char *)arg2, ext); 00435 if (!nfn) 00436 ast_log(LOG_WARNING, "Out of memory\n"); 00437 else { 00438 res = action == ACTION_COPY ? copy(fn, nfn) : rename(fn, nfn); 00439 if (res) 00440 ast_log(LOG_WARNING, "%s(%s,%s) failed: %s\n", 00441 action == ACTION_COPY ? "copy" : "rename", 00442 fn, nfn, strerror(errno)); 00443 free(nfn); 00444 } 00445 } 00446 break; 00447 00448 default: 00449 ast_log(LOG_WARNING, "Unknown helper %d\n", action); 00450 } 00451 free(fn); 00452 } 00453 } 00454 AST_RWLIST_UNLOCK(&formats); 00455 return res; 00456 }
| 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 765 of file file.c.
References ACTION_RENAME, and ast_filehelper().
Referenced by __ast_play_and_record(), ast_monitor_stop(), leave_voicemail(), and rename_file().
00766 { 00767 return ast_filehelper(filename, filename2, fmt, ACTION_RENAME); 00768 }
| 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 518 of file file.c.
References ast_openstream_full().
Referenced by ast_streamfile(), dictate_exec(), handle_getoption(), handle_streamfile(), and speech_streamfile().
00519 { 00520 return ast_openstream_full(chan, filename, preflang, 0); 00521 }
| 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 523 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().
00524 { 00525 /* 00526 * Use fileexists_core() to find a file in a compatible 00527 * language and format, set up a suitable translator, 00528 * and open the stream. 00529 */ 00530 int fmts, res, buflen; 00531 char *buf; 00532 00533 if (!asis) { 00534 /* do this first, otherwise we detect the wrong writeformat */ 00535 ast_stopstream(chan); 00536 if (chan->generator) 00537 ast_deactivate_generator(chan); 00538 } 00539 if (preflang == NULL) 00540 preflang = ""; 00541 buflen = strlen(preflang) + strlen(filename) + 2; 00542 buf = alloca(buflen); 00543 if (buf == NULL) 00544 return NULL; 00545 fmts = fileexists_core(filename, NULL, preflang, buf, buflen); 00546 if (fmts > 0) 00547 fmts &= AST_FORMAT_AUDIO_MASK; 00548 if (fmts < 1) { 00549 ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename); 00550 return NULL; 00551 } 00552 chan->oldwriteformat = chan->writeformat; 00553 /* Set the channel to a format we can work with */ 00554 res = ast_set_write_format(chan, fmts); 00555 res = ast_filehelper(buf, chan, NULL, ACTION_OPEN); 00556 if (res >= 0) 00557 return chan->stream; 00558 return NULL; 00559 }
| 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 561 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().
00562 { 00563 /* As above, but for video. But here we don't have translators 00564 * so we must enforce a format. 00565 */ 00566 unsigned int format; 00567 char *buf; 00568 int buflen; 00569 00570 if (preflang == NULL) 00571 preflang = ""; 00572 buflen = strlen(preflang) + strlen(filename) + 2; 00573 buf = alloca(buflen); 00574 if (buf == NULL) 00575 return NULL; 00576 00577 for (format = AST_FORMAT_MAX_AUDIO << 1; format <= AST_FORMAT_MAX_VIDEO; format = format << 1) { 00578 int fd; 00579 const char *fmt; 00580 00581 if (!(chan->nativeformats & format)) 00582 continue; 00583 fmt = ast_getformatname(format); 00584 if ( fileexists_core(filename, fmt, preflang, buf, buflen) < 1) /* no valid format */ 00585 continue; 00586 fd = ast_filehelper(buf, chan, fmt, ACTION_OPEN); 00587 if (fd >= 0) 00588 return chan->vstream; 00589 ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename); 00590 } 00591 return NULL; 00592 }
| int ast_playstream | ( | struct ast_filestream * | s | ) |
| s | filestream to play Returns 0 for success, -1 on failure |
Definition at line 661 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().
00662 { 00663 if (s->fmt->format < AST_FORMAT_MAX_AUDIO) 00664 ast_readaudio_callback(s); 00665 else 00666 ast_readvideo_callback(s); 00667 return 0; 00668 }
| static int ast_readaudio_callback | ( | void * | data | ) | [static] |
Definition at line 603 of file file.c.
References ast_log(), ast_sched_add(), ast_settimeout(), ast_write(), LOG_WARNING, and s.
Referenced by ast_playstream().
00604 { 00605 struct ast_filestream *s = data; 00606 int whennext = 0; 00607 00608 while(!whennext) { 00609 struct ast_frame *fr = s->fmt->read(s, &whennext); 00610 if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) { 00611 if (fr) 00612 ast_log(LOG_WARNING, "Failed to write frame\n"); 00613 s->owner->streamid = -1; 00614 #ifdef HAVE_ZAPTEL 00615 ast_settimeout(s->owner, 0, NULL, NULL); 00616 #endif 00617 return 0; 00618 } 00619 } 00620 if (whennext != s->lasttimeout) { 00621 #ifdef HAVE_ZAPTEL 00622 if (s->owner->timingfd > -1) 00623 ast_settimeout(s->owner, whennext, ast_readaudio_callback, s); 00624 else 00625 #endif 00626 s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_readaudio_callback, s); 00627 s->lasttimeout = whennext; 00628 return 0; 00629 } 00630 return 1; 00631 }
| 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 804 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().
00805 { 00806 FILE *bfile; 00807 struct ast_format *f; 00808 struct ast_filestream *fs = NULL; 00809 char *fn; 00810 00811 AST_RWLIST_RDLOCK(&formats); 00812 00813 AST_RWLIST_TRAVERSE(&formats, f, list) { 00814 fs = NULL; 00815 if (!exts_compare(f->exts, type)) 00816 continue; 00817 00818 fn = build_filename(filename, type); 00819 errno = 0; 00820 bfile = fopen(fn, "r"); 00821 if (!bfile || (fs = get_filestream(f, bfile)) == NULL || 00822 open_wrapper(fs) ) { 00823 ast_log(LOG_WARNING, "Unable to open %s\n", fn); 00824 if (fs) 00825 ast_free(fs); 00826 if (bfile) 00827 fclose(bfile); 00828 free(fn); 00829 continue; 00830 } 00831 /* found it */ 00832 fs->trans = NULL; 00833 fs->fmt = f; 00834 fs->flags = flags; 00835 fs->mode = mode; 00836 fs->filename = strdup(filename); 00837 fs->vfs = NULL; 00838 break; 00839 } 00840 00841 AST_RWLIST_UNLOCK(&formats); 00842 if (!fs) 00843 ast_log(LOG_WARNING, "No such format '%s'\n", type); 00844 00845 return fs; 00846 }
| 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 594 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().
00595 { 00596 struct ast_frame *f = NULL; 00597 int whennext = 0; 00598 if (s && s->fmt) 00599 f = s->fmt->read(s, &whennext); 00600 return f; 00601 }
| static int ast_readvideo_callback | ( | void * | data | ) | [static] |
Definition at line 633 of file file.c.
References ast_log(), ast_sched_add(), ast_write(), LOG_WARNING, and s.
Referenced by ast_playstream().
00634 { 00635 struct ast_filestream *s = data; 00636 int whennext = 0; 00637 00638 while (!whennext) { 00639 struct ast_frame *fr = s->fmt->read(s, &whennext); 00640 if (!fr || ast_write(s->owner, fr)) { /* no stream or error, as above */ 00641 if (fr) 00642 ast_log(LOG_WARNING, "Failed to write frame\n"); 00643 s->owner->vstreamid = -1; 00644 return 0; 00645 } 00646 } 00647 if (whennext != s->lasttimeout) { 00648 s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext/8, ast_readvideo_callback, s); 00649 s->lasttimeout = whennext; 00650 return 0; 00651 } 00652 return 1; 00653 }
| 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 670 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, and ast_channel::stream.
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(), background_file(), 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 return 0; 00141 }
| int ast_stream_and_wait | ( | struct ast_channel * | chan, | |
| const char * | file, | |||
| const char * | language, | |||
| const char * | digits | |||
| ) |
Definition at line 1108 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().
01110 { 01111 int res = 0; 01112 if (!ast_strlen_zero(file)) { 01113 res = ast_streamfile(chan, file, language); 01114 if (!res) 01115 res = ast_waitstream(chan, digits); 01116 } 01117 return res; 01118 }
| 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 685 of file file.c.
References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.
Referenced by waitstream_core().
00686 { 00687 return ast_seekstream(fs, ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR); 00688 }
| 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 690 of file file.c.
References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.
Referenced by __ast_play_and_record(), handle_recordfile(), and waitstream_core().
00691 { 00692 return ast_seekstream(fs, -ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR); 00693 }
| 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 775 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(), background_file(), 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().
00776 { 00777 struct ast_filestream *fs; 00778 struct ast_filestream *vfs=NULL; 00779 char fmt[256]; 00780 00781 fs = ast_openstream(chan, filename, preflang); 00782 if (fs) 00783 vfs = ast_openvstream(chan, filename, preflang); 00784 if (vfs) 00785 ast_log(LOG_DEBUG, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format)); 00786 if (fs){ 00787 if (ast_applystream(chan, fs)) 00788 return -1; 00789 if (vfs && ast_applystream(chan, vfs)) 00790 return -1; 00791 if (ast_playstream(fs)) 00792 return -1; 00793 if (vfs && ast_playstream(vfs)) 00794 return -1; 00795 if (option_verbose > 2) 00796 ast_verbose(VERBOSE_PREFIX_3 "<%s> Playing '%s' (language '%s')\n", chan->name, filename, preflang ? preflang : "default"); 00797 00798 return 0; 00799 } 00800 ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), chan->nativeformats), strerror(errno)); 00801 return -1; 00802 }
| 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 680 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 675 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 1081 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(), background_file(), 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(), saycharstr(), sayfile(), saynum(), send_morse(), send_tone_telemetry(), ss_thread(), vm_authenticate(), and wait_file().
01082 { 01083 return waitstream_core(c, breakon, NULL, NULL, 0, -1, -1, NULL); 01084 }
| 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 1092 of file file.c.
References ast_channel::context, and waitstream_core().
Referenced by pbx_builtin_background().
01093 { 01094 /* Waitstream, with return in the case of a valid 1 digit extension */ 01095 /* in the current or specified context being pressed */ 01096 01097 if (!context) 01098 context = c->context; 01099 return waitstream_core(c, NULL, NULL, NULL, 0, 01100 -1, -1, context); 01101 }
| 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 1075 of file file.c.
References waitstream_core().
Referenced by ast_control_streamfile().
01076 { 01077 return waitstream_core(c, breakon, forward, rewind, ms, 01078 -1 /* no audiofd */, -1 /* no cmdfd */, NULL /* no context */); 01079 }
| int ast_waitstream_full | ( | struct ast_channel * | c, | |
| const char * | breakon, | |||
| int | audiofd, | |||
| int | cmdfd | |||
| ) |
Definition at line 1086 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().
01087 { 01088 return waitstream_core(c, breakon, NULL, NULL, 0, 01089 audiofd, cmdfd, NULL /* no context */); 01090 }
| 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 848 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(), and recordthread().
00849 { 00850 int fd, myflags = 0; 00851 /* compiler claims this variable can be used before initialization... */ 00852 FILE *bfile = NULL; 00853 struct ast_format *f; 00854 struct ast_filestream *fs = NULL; 00855 char *buf = NULL; 00856 size_t size = 0; 00857 int format_found = 0; 00858 00859 AST_RWLIST_RDLOCK(&formats); 00860 00861 /* set the O_TRUNC flag if and only if there is no O_APPEND specified */ 00862 /* We really can't use O_APPEND as it will break WAV header updates */ 00863 if (flags & O_APPEND) { 00864 flags &= ~O_APPEND; 00865 } else { 00866 myflags = O_TRUNC; 00867 } 00868 00869 myflags |= O_WRONLY | O_CREAT; 00870 00871 /* XXX need to fix this - we should just do the fopen, 00872 * not open followed by fdopen() 00873 */ 00874 AST_RWLIST_TRAVERSE(&formats, f, list) { 00875 char *fn, *orig_fn = NULL; 00876 if (fs) 00877 break; 00878 00879 if (!exts_compare(f->exts, type)) 00880 continue; 00881 else 00882 format_found = 1; 00883 00884 fn = build_filename(filename, type); 00885 fd = open(fn, flags | myflags, mode); 00886 if (fd > -1) { 00887 /* fdopen() the resulting file stream */ 00888 bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w"); 00889 if (!bfile) { 00890 ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno)); 00891 close(fd); 00892 fd = -1; 00893 } 00894 } 00895 00896 if (ast_opt_cache_record_files && (fd > -1)) { 00897 char *c; 00898 00899 fclose(bfile); /* this also closes fd */ 00900 /* 00901 We touch orig_fn just as a place-holder so other things (like vmail) see the file is there. 00902 What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place. 00903 */ 00904 orig_fn = ast_strdupa(fn); 00905 for (c = fn; *c; c++) 00906 if (*c == '/') 00907 *c = '_'; 00908 00909 size = strlen(fn) + strlen(record_cache_dir) + 2; 00910 buf = alloca(size); 00911 strcpy(buf, record_cache_dir); 00912 strcat(buf, "/"); 00913 strcat(buf, fn); 00914 free(fn); 00915 fn = buf; 00916 fd = open(fn, flags | myflags, mode); 00917 if (fd > -1) { 00918 /* fdopen() the resulting file stream */ 00919 bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w"); 00920 if (!bfile) { 00921 ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno)); 00922 close(fd); 00923 fd = -1; 00924 } 00925 } 00926 } 00927 if (fd > -1) { 00928 errno = 0; 00929 fs = get_filestream(f, bfile); 00930 if (!fs || rewrite_wrapper(fs, comment)) { 00931 ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn); 00932 close(fd); 00933 if (orig_fn) { 00934 unlink(fn); 00935 unlink(orig_fn); 00936 } 00937 if (fs) 00938 ast_free(fs); 00939 } 00940 fs->trans = NULL; 00941 fs->fmt = f; 00942 fs->flags = flags; 00943 fs->mode = mode; 00944 if (orig_fn) { 00945 fs->realfilename = strdup(orig_fn); 00946 fs->filename = strdup(fn); 00947 } else { 00948 fs->realfilename = NULL; 00949 fs->filename = strdup(filename); 00950 } 00951 fs->vfs = NULL; 00952 /* If truncated, we'll be at the beginning; if not truncated, then append */ 00953 f->seek(fs, 0, SEEK_END); 00954 } else if (errno != EEXIST) { 00955 ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno)); 00956 if (orig_fn) 00957 unlink(orig_fn); 00958 } 00959 /* if buf != NULL then fn is already free and pointing to it */ 00960 if (!buf) 00961 free(fn); 00962 } 00963 00964 AST_RWLIST_UNLOCK(&formats); 00965 00966 if (!format_found) 00967 ast_log(LOG_WARNING, "No such format '%s'\n", type); 00968 00969 return fs; 00970 }
| 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 143 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(), and recordthread().
00144 { 00145 int res = -1; 00146 int alt = 0; 00147 if (f->frametype == AST_FRAME_VIDEO) { 00148 if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) { 00149 /* This is the audio portion. Call the video one... */ 00150 if (!fs->vfs && fs->filename) { 00151 const char *type = ast_getformatname(f->subclass & ~0x1); 00152 fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode); 00153 ast_log(LOG_DEBUG, "Opened video output file\n"); 00154 } 00155 if (fs->vfs) 00156 return ast_writestream(fs->vfs, f); 00157 /* else ignore */ 00158 return 0; 00159 } else { 00160 /* Might / might not have mark set */ 00161 alt = 1; 00162 } 00163 } else if (f->frametype != AST_FRAME_VOICE) { 00164 ast_log(LOG_WARNING, "Tried to write non-voice frame\n"); 00165 return -1; 00166 } 00167 if (((fs->fmt->format | alt) & f->subclass) == f->subclass) { 00168 res = fs->fmt->write(fs, f); 00169 if (res < 0) 00170 ast_log(LOG_WARNING, "Natural write failed\n"); 00171 else if (res > 0) 00172 ast_log(LOG_WARNING, "Huh??\n"); 00173 } else { 00174 /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't 00175 the one we've setup a translator for, we do the "wrong thing" XXX */ 00176 if (fs->trans && f->subclass != fs->lastwriteformat) { 00177 ast_translator_free_path(fs->trans); 00178 fs->trans = NULL; 00179 } 00180 if (!fs->trans) 00181 fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass); 00182 if (!fs->trans) 00183 ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n", 00184 fs->fmt->name, ast_getformatname(f->subclass)); 00185 else { 00186 struct ast_frame *trf; 00187 fs->lastwriteformat = f->subclass; 00188 /* Get the translated frame but don't consume the original in case they're using it on another stream */ 00189 trf = ast_translate(fs->trans, f, 0); 00190 if (trf) { 00191 res = fs->fmt->write(fs, trf); 00192 if (res) 00193 ast_log(LOG_WARNING, "Translated frame write failed\n"); 00194 } else 00195 res = 0; 00196 } 00197 } 00198 return res; 00199 }
| 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 244 of file file.c.
References asprintf, and ast_config_AST_DATA_DIR.
Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().
00245 { 00246 char *fn = NULL; 00247 00248 if (!strcmp(ext, "wav49")) 00249 ext = "WAV"; 00250 00251 if (filename[0] == '/') 00252 asprintf(&fn, "%s.%s", filename, ext); 00253 else 00254 asprintf(&fn, "%s/sounds/%s.%s", 00255 ast_config_AST_DATA_DIR, filename, ext); 00256 return fn; 00257 }
| static int copy | ( | const char * | infile, | |
| const char * | outfile | |||
| ) | [static] |
Definition at line 201 of file file.c.
References ast_log(), len, and LOG_WARNING.
Referenced by action_getvar(), ast_filehelper(), copy_file(), and iax2_register().
00202 { 00203 int ifd, ofd, len; 00204 char buf[4096]; /* XXX make it lerger. */ 00205 00206 if ((ifd = open(infile, O_RDONLY)) < 0) { 00207 ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile); 00208 return -1; 00209 } 00210 if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) { 00211 ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile); 00212 close(ifd); 00213 return -1; 00214 } 00215 while ( (len = read(ifd, buf, sizeof(buf)) ) ) { 00216 int res; 00217 if (len < 0) { 00218 ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno)); 00219 break; 00220 } 00221 /* XXX handle partial writes */ 00222 res = write(ofd, buf, len); 00223 if (res != len) { 00224 ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno)); 00225 len = -1; /* error marker */ 00226 break; 00227 } 00228 } 00229 close(ifd); 00230 close(ofd); 00231 if (len < 0) { 00232 unlink(outfile); 00233 return -1; /* error */ 00234 } 00235 return 0; /* success */ 00236 }
| static int exts_compare | ( | const char * | exts, | |
| const char * | type | |||
| ) | [static] |
Definition at line 261 of file file.c.
Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().
00262 { 00263 char tmp[256]; 00264 char *stringp = tmp, *ext; 00265 00266 ast_copy_string(tmp, exts, sizeof(tmp)); 00267 while ((ext = strsep(&stringp, "|"))) { 00268 if (!strcmp(ext, type)) 00269 return 1; 00270 } 00271 00272 return 0; 00273 }
| 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 469 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().
00471 { 00472 int res = -1; 00473 int langlen; /* length of language string */ 00474 const char *c = strrchr(filename, '/'); 00475 int offset = c ? c - filename + 1 : 0; /* points right after the last '/' */ 00476 00477 if (preflang == NULL) 00478 preflang = ""; 00479 langlen = strlen(preflang); 00480 00481 if (buflen < langlen + strlen(filename) + 2) { 00482 ast_log(LOG_WARNING, "buffer too small\n"); 00483 buf[0] = '\0'; /* set to empty */ 00484 buf = alloca(langlen + strlen(filename) + 2); /* room for everything */ 00485 } 00486 if (buf == NULL) 00487 return 0; 00488 buf[0] = '\0'; 00489 for (;;) { 00490 if (ast_language_is_prefix) { /* new layout */ 00491 if (langlen) { 00492 strcpy(buf, preflang); 00493 buf[langlen] = '/'; 00494 strcpy(buf + langlen + 1, filename); 00495 } else 00496 strcpy(buf, filename); /* first copy the full string */ 00497 } else { /* old layout */ 00498 strcpy(buf, filename); /* first copy the full string */ 00499 if (langlen) { 00500 /* insert the language and suffix if needed */ 00501 strcpy(buf + offset, preflang); 00502 sprintf(buf + offset + langlen, "/%s", filename + offset); 00503 } 00504 } 00505 res = ast_filehelper(buf, NULL, fmt, ACTION_EXISTS); 00506 if (res > 0) /* found format */ 00507 break; 00508 if (langlen == 0) /* no more formats */ 00509 break; 00510 if (preflang[langlen] == '_') /* we are on the local suffix */ 00511 langlen = 0; /* try again with no language */ 00512 else 00513 langlen = (c = strchr(preflang, '_')) ? c - preflang : 0; 00514 } 00515 return res; 00516 }
| static int fn_wrapper | ( | struct ast_filestream * | s, | |
| const char * | comment, | |||
| enum wrap_fn | mode | |||
| ) | [static] |
Definition at line 299 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().
00300 { 00301 struct ast_format *f = s->fmt; 00302 int ret = -1; 00303 00304 if (mode == WRAP_OPEN && f->open && f->open(s)) 00305 ast_log(LOG_WARNING, "Unable to open format %s\n", f->name); 00306 else if (mode == WRAP_REWRITE && f->rewrite && f->rewrite(s, comment)) 00307 ast_log(LOG_WARNING, "Unable to rewrite format %s\n", f->name); 00308 else { 00309 /* preliminary checks succeed. update usecount */ 00310 ast_module_ref(f->module); 00311 ret = 0; 00312 } 00313 return ret; 00314 }
| static struct ast_filestream* get_filestream | ( | struct ast_format * | fmt, | |
| FILE * | bfile | |||
| ) | [static] |
Definition at line 275 of file file.c.
References ast_calloc, fmt, and s.
Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().
00276 { 00277 struct ast_filestream *s; 00278 00279 int l = sizeof(*s) + fmt->buf_size + fmt->desc_size; /* total allocation size */ 00280 if ( (s = ast_calloc(1, l)) == NULL) 00281 return NULL; 00282 s->fmt = fmt; 00283 s->f = bfile; 00284 00285 if (fmt->desc_size) 00286 s->private = ((char *)(s+1)) + fmt->buf_size; 00287 if (fmt->buf_size) 00288 s->buf = (char *)(s+1); 00289 s->fr.src = fmt->name; 00290 return s; 00291 }
| static int open_wrapper | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 321 of file file.c.
References fn_wrapper(), s, and WRAP_OPEN.
Referenced by ast_filehelper(), and ast_readfile().
00322 { 00323 return fn_wrapper(s, NULL, WRAP_OPEN); 00324 }
| static int rewrite_wrapper | ( | struct ast_filestream * | s, | |
| const char * | comment | |||
| ) | [static] |
Definition at line 316 of file file.c.
References fn_wrapper(), and s.
Referenced by ast_writefile().
00317 { 00318 return fn_wrapper(s, comment, WRAP_REWRITE); 00319 }
| static int show_file_formats | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1120 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.
01121 { 01122 #define FORMAT "%-10s %-10s %-20s\n" 01123 #define FORMAT2 "%-10s %-10s %-20s\n" 01124 struct ast_format *f; 01125 int count_fmt = 0; 01126 01127 if (argc != 4) 01128 return RESULT_SHOWUSAGE; 01129 ast_cli(fd, FORMAT, "Format", "Name", "Extensions"); 01130 01131 AST_RWLIST_RDLOCK(&formats); 01132 AST_RWLIST_TRAVERSE(&formats, f, list) { 01133 ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts); 01134 count_fmt++; 01135 } 01136 AST_RWLIST_UNLOCK(&formats); 01137 ast_cli(fd, "%d file formats registered.\n", count_fmt); 01138 return RESULT_SUCCESS; 01139 #undef FORMAT 01140 #undef FORMAT2 01141 }
| static int show_file_formats_deprecated | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 1143 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.
01144 { 01145 #define FORMAT "%-10s %-10s %-20s\n" 01146 #define FORMAT2 "%-10s %-10s %-20s\n" 01147 struct ast_format *f; 01148 int count_fmt = 0; 01149 01150 if (argc != 3) 01151 return RESULT_SHOWUSAGE; 01152 ast_cli(fd, FORMAT, "Format", "Name", "Extensions"); 01153 01154 if (AST_LIST_LOCK(&formats)) { 01155 ast_log(LOG_WARNING, "Unable to lock format list\n"); 01156 return -1; 01157 } 01158 01159 AST_LIST_TRAVERSE(&formats, f, list) { 01160 ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts); 01161 count_fmt++; 01162 } 01163 AST_LIST_UNLOCK(&formats); 01164 ast_cli(fd, "%d file formats registered.\n", count_fmt); 01165 return RESULT_SUCCESS; 01166 #undef FORMAT 01167 #undef FORMAT2 01168 }
| 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 975 of file file.c.
References ast_channel::_softhangup, 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_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), 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().
00978 { 00979 if (!breakon) 00980 breakon = ""; 00981 if (!forward) 00982 forward = ""; 00983 if (!rewind) 00984 rewind = ""; 00985 00986 while (c->stream) { 00987 int res; 00988 int ms = ast_sched_wait(c->sched); 00989 if (ms < 0 && !c->timingfunc) { 00990 ast_stopstream(c); 00991 break; 00992 } 00993 if (ms < 0) 00994 ms = 1000; 00995 if (cmdfd < 0) { 00996 res = ast_waitfor(c, ms); 00997 if (res < 0) { 00998 ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno)); 00999 return res; 01000 } 01001 } else { 01002 int outfd; 01003 struct ast_channel *rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 01004 if (!rchan && (outfd < 0) && (ms)) { 01005 /* Continue */ 01006 if (errno == EINTR) 01007 continue; 01008 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 01009 return -1; 01010 } else if (outfd > -1) { /* this requires cmdfd set */ 01011 /* The FD we were watching has something waiting */ 01012 return 1; 01013 } 01014 /* if rchan is set, it is 'c' */ 01015 res = rchan ? 1 : 0; /* map into 'res' values */ 01016 } 01017 if (res > 0) { 01018 struct ast_frame *fr = ast_read(c); 01019 if (!fr) 01020 return -1; 01021 switch(fr->frametype) { 01022 case AST_FRAME_DTMF_END: 01023 if (context) { 01024 const char exten[2] = { fr->subclass, '\0' }; 01025 if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) { 01026 res = fr->subclass; 01027 ast_frfree(fr); 01028 return res; 01029 } 01030 } else { 01031 res = fr->subclass; 01032 if (strchr(forward,res)) { 01033 ast_stream_fastforward(c->stream, skip_ms); 01034 } else if (strchr(rewind,res)) { 01035 ast_stream_rewind(c->stream, skip_ms); 01036 } else if (strchr(breakon, res)) { 01037 ast_frfree(fr); 01038 return res; 01039 } 01040 } 01041 break; 01042 case AST_FRAME_CONTROL: 01043 switch(fr->subclass) { 01044 case AST_CONTROL_HANGUP: 01045 case AST_CONTROL_BUSY: 01046 case AST_CONTROL_CONGESTION: 01047 ast_frfree(fr); 01048 return -1; 01049 case AST_CONTROL_RINGING: 01050 case AST_CONTROL_ANSWER: 01051 case AST_CONTROL_VIDUPDATE: 01052 case AST_CONTROL_HOLD: 01053 case AST_CONTROL_UNHOLD: 01054 /* Unimportant */ 01055 break; 01056 default: 01057 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass); 01058 } 01059 break; 01060 case AST_FRAME_VOICE: 01061 /* Write audio if appropriate */ 01062 if (audiofd > -1) 01063 write(audiofd, fr->data, fr->datalen); 01064 default: 01065 /* Ignore all others */ 01066 break; 01067 } 01068 ast_frfree(fr); 01069 } 01070 ast_sched_runq(c->sched); 01071 } 01072 return (c->_softhangup ? -1 : 0); 01073 }
| 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 1179 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[] |
1.5.1