#include <sys/types.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 <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.h"#include "astconf.h"Go to the source code of this file.
Data Structures | |
| struct | ast_filestream |
| struct | ast_format |
Defines | |
| #define | ACTION_EXISTS 1 |
| #define | ACTION_DELETE 2 |
| #define | ACTION_RENAME 3 |
| #define | ACTION_OPEN 4 |
| #define | ACTION_COPY 5 |
| #define | FORMAT "%-10s %-10s %-20s\n" |
| #define | FORMAT2 "%-10s %-10s %-20s\n" |
Functions | |
| AST_MUTEX_DEFINE_STATIC (formatlock) | |
| int | ast_format_register (char *name, char *exts, int format, struct ast_filestream *(*open)(int fd), struct ast_filestream *(*rewrite)(int fd, char *comment), int(*write)(struct ast_filestream *, struct ast_frame *), int(*seek)(struct ast_filestream *, long sample_offset, int whence), int(*trunc)(struct ast_filestream *), long(*tell)(struct ast_filestream *), struct ast_frame *(*read)(struct ast_filestream *, int *whennext), void(*close)(struct ast_filestream *), char *(*getcomment)(struct ast_filestream *)) |
| int | ast_format_unregister (char *name) |
| Unregisters a file format. More... | |
| int | ast_stopstream (struct ast_channel *tmp) |
| Stops a stream. More... | |
| int | ast_writestream (struct ast_filestream *fs, struct ast_frame *f) |
| Writes a frame to a stream. More... | |
| ast_filestream * | ast_openstream (struct ast_channel *chan, char *filename, char *preflang) |
| Opens stream for use in seeking, playing. More... | |
| ast_filestream * | ast_openvstream (struct ast_channel *chan, char *filename, char *preflang) |
| Opens stream for use in seeking, playing. More... | |
| ast_frame * | ast_readframe (struct ast_filestream *s) |
| Read a frame from a filestream. More... | |
| int | ast_applystream (struct ast_channel *chan, struct ast_filestream *s) |
| Applys a open stream to a channel. More... | |
| int | ast_playstream (struct ast_filestream *s) |
| play a open stream on a channel. More... | |
| int | ast_seekstream (struct ast_filestream *fs, long sample_offset, int whence) |
| Seeks into stream. More... | |
| int | ast_truncstream (struct ast_filestream *fs) |
| Trunc stream at current location. More... | |
| long | ast_tellstream (struct ast_filestream *fs) |
| Tell where we are in a stream. More... | |
| int | ast_stream_fastforward (struct ast_filestream *fs, long ms) |
| Fast forward stream ms. More... | |
| int | ast_stream_rewind (struct ast_filestream *fs, long ms) |
| Rewind stream ms. More... | |
| int | ast_closestream (struct ast_filestream *f) |
| Closes a stream. More... | |
| int | ast_fileexists (char *filename, char *fmt, char *preflang) |
| Checks for the existence of a given file. More... | |
| int | ast_filedelete (char *filename, char *fmt) |
| Deletes a file. More... | |
| int | ast_filerename (char *filename, char *filename2, char *fmt) |
| Renames a file. More... | |
| int | ast_filecopy (char *filename, char *filename2, char *fmt) |
| Copies a file. More... | |
| int | ast_streamfile (struct ast_channel *chan, char *filename, char *preflang) |
| Streams a file. More... | |
| ast_filestream * | ast_readfile (char *filename, char *type, char *comment, int flags, int check, mode_t mode) |
| Starts reading from a file. More... | |
| ast_filestream * | ast_writefile (char *filename, char *type, char *comment, int flags, int check, mode_t mode) |
| Starts writing a file. More... | |
| char | ast_waitstream (struct ast_channel *c, char *breakon) |
| Waits for a stream to stop or digit to be pressed. More... | |
| char | ast_waitstream_fr (struct ast_channel *c, char *breakon, char *forward, char *rewind, int ms) |
| Same as waitstream but allows stream to be forwarded or rewound. More... | |
| char | ast_waitstream_full (struct ast_channel *c, char *breakon, int audiofd, int cmdfd) |
| int | ast_file_init (void) |
| Initialize file stuff. More... | |
Variables | |
| ast_cli_entry | show_file |
|
|
Definition at line 320 of file file.c. Referenced by ast_filecopy(). |
|
|
Definition at line 317 of file file.c. Referenced by ast_filedelete(). |
|
|
Definition at line 316 of file file.c. Referenced by ast_fileexists(). |
|
|
Definition at line 319 of file file.c. Referenced by ast_openstream(), and ast_openvstream(). |
|
|
Definition at line 318 of file file.c. Referenced by ast_filerename(). |
|
|
|
|
|
|
|
||||||||||||
|
Applys a open stream to a channel.
Definition at line 607 of file file.c. References ast_filestream::owner. Referenced by ast_streamfile().
00608 {
00609 s->owner = chan;
00610 return 0;
00611 }
|
|
|
Closes a stream.
Definition at line 652 of file file.c. References ast_safe_system(), ast_sched_del(), ast_settimeout(), ast_translator_free_path(), ast_format::close, ast_filestream::filename, ast_filestream::fmt, ast_format::format, free, ast_filestream::owner, ast_filestream::realfilename, ast_channel::sched, ast_channel::stream, ast_channel::streamid, ast_filestream::trans, ast_channel::vstream, and ast_channel::vstreamid. Referenced by ast_app_getvoice(), ast_hangup(), ast_play_and_prepend(), ast_play_and_record(), and ast_stopstream().
00653 {
00654 char *cmd = NULL;
00655 size_t size = 0;
00656 /* Stop a running stream if there is one */
00657 if (f->owner) {
00658 if (f->fmt->format < AST_FORMAT_MAX_AUDIO) {
00659 f->owner->stream = NULL;
00660 if (f->owner->streamid > -1)
00661 ast_sched_del(f->owner->sched, f->owner->streamid);
00662 f->owner->streamid = -1;
00663 #ifdef ZAPTEL_OPTIMIZATIONS
00664 ast_settimeout(f->owner, 0, NULL, NULL);
00665 #endif
00666 } else {
00667 f->owner->vstream = NULL;
00668 if (f->owner->vstreamid > -1)
00669 ast_sched_del(f->owner->sched, f->owner->vstreamid);
00670 f->owner->vstreamid = -1;
00671 }
00672 }
00673 /* destroy the translator on exit */
00674 if (f->trans) {
00675 ast_translator_free_path(f->trans);
00676 f->trans = NULL;
00677 }
00678
00679 if (f->realfilename && f->filename) {
00680 size = strlen(f->filename) + strlen(f->realfilename) + 15;
00681 cmd = alloca(size);
00682 memset(cmd,0,size);
00683 snprintf(cmd,size,"/bin/mv -f %s %s",f->filename,f->realfilename);
00684 ast_safe_system(cmd);
00685 }
00686
00687 if (f->filename) {
00688 free(f->filename);
00689 f->filename = NULL;
00690 }
00691 if (f->realfilename) {
00692 free(f->realfilename);
00693 f->realfilename = NULL;
00694 }
00695 f->fmt->close(f);
00696 return 0;
00697 }
|
|
|
Initialize file stuff. Initializes all the various file stuff. Basically just registers the cli stuff Returns 0 all the time Definition at line 1139 of file file.c. References ast_cli_register(). Referenced by main().
01140 {
01141 ast_cli_register(&show_file);
01142 return 0;
01143 }
|
|
||||||||||||||||
|
Copies a file.
Definition at line 750 of file file.c. References ACTION_COPY.
00751 {
00752 return ast_filehelper(filename, filename2, fmt, ACTION_COPY);
00753 }
|
|
||||||||||||
|
Deletes a file.
Definition at line 740 of file file.c. References ACTION_DELETE. Referenced by ast_play_and_prepend().
00741 {
00742 return ast_filehelper(filename, NULL, fmt, ACTION_DELETE);
00743 }
|
|
||||||||||||||||
|
Checks for the existence of a given file.
Definition at line 700 of file file.c. References ACTION_EXISTS, and MAX_LANGUAGE. Referenced by ast_openstream(), and ast_openvstream().
00701 {
00702 char filename2[256];
00703 char tmp[256];
00704 char *postfix;
00705 char *prefix;
00706 char *c;
00707 char lang2[MAX_LANGUAGE];
00708 int res = -1;
00709 if (preflang && !ast_strlen_zero(preflang)) {
00710 /* Insert the language between the last two parts of the path */
00711 strncpy(tmp, filename, sizeof(tmp) - 1);
00712 c = strrchr(tmp, '/');
00713 if (c) {
00714 *c = '\0';
00715 postfix = c+1;
00716 prefix = tmp;
00717 } else {
00718 postfix = tmp;
00719 prefix="";
00720 }
00721 snprintf(filename2, sizeof(filename2), "%s/%s/%s", prefix, preflang, postfix);
00722 res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS);
00723 if (res < 1) {
00724 char *stringp=NULL;
00725 strncpy(lang2, preflang, sizeof(lang2)-1);
00726 stringp=lang2;
00727 strsep(&stringp, "_");
00728 if (strcmp(lang2, preflang)) {
00729 snprintf(filename2, sizeof(filename2), "%s/%s/%s", prefix, lang2, postfix);
00730 res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS);
00731 }
00732 }
00733 }
00734 if (res < 1) {
00735 res = ast_filehelper(filename, NULL, fmt, ACTION_EXISTS);
00736 }
00737 return res;
00738 }
|
|
||||||||||||||||
|
Renames a file.
Definition at line 745 of file file.c. References ACTION_RENAME. Referenced by ast_play_and_prepend().
00746 {
00747 return ast_filehelper(filename, filename2, fmt, ACTION_RENAME);
00748 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 90 of file file.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), ast_format::close, ast_format::exts, ast_format::format, ast_format::getcomment, LOG_WARNING, malloc, ast_format::name, ast_format::next, ast_format::open, ast_format::read, ast_format::rewrite, ast_format::seek, ast_format::tell, ast_format::trunc, VERBOSE_PREFIX_2, and ast_format::write.
00100 {
00101 struct ast_format *tmp;
00102 if (ast_mutex_lock(&formatlock)) {
00103 ast_log(LOG_WARNING, "Unable to lock format list\n");
00104 return -1;
00105 }
00106 tmp = formats;
00107 while(tmp) {
00108 if (!strcasecmp(name, tmp->name)) {
00109 ast_mutex_unlock(&formatlock);
00110 ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", name);
00111 return -1;
00112 }
00113 tmp = tmp->next;
00114 }
00115 tmp = malloc(sizeof(struct ast_format));
00116 if (!tmp) {
00117 ast_log(LOG_WARNING, "Out of memory\n");
00118 ast_mutex_unlock(&formatlock);
00119 return -1;
00120 }
00121 strncpy(tmp->name, name, sizeof(tmp->name)-1);
00122 strncpy(tmp->exts, exts, sizeof(tmp->exts)-1);
00123 tmp->open = open;
00124 tmp->rewrite = rewrite;
00125 tmp->read = read;
00126 tmp->write = write;
00127 tmp->seek = seek;
00128 tmp->trunc = trunc;
00129 tmp->tell = tell;
00130 tmp->close = close;
00131 tmp->format = format;
00132 tmp->getcomment = getcomment;
00133 tmp->next = formats;
00134 formats = tmp;
00135 ast_mutex_unlock(&formatlock);
00136 if (option_verbose > 1)
00137 ast_verbose( VERBOSE_PREFIX_2 "Registered file format %s, extension(s) %s\n", name, exts);
00138 return 0;
00139 }
|
|
|
Unregisters a file format.
Definition at line 141 of file file.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, LOG_WARNING, ast_format::name, ast_format::next, and VERBOSE_PREFIX_2.
00142 {
00143 struct ast_format *tmp, *tmpl = NULL;
00144 if (ast_mutex_lock(&formatlock)) {
00145 ast_log(LOG_WARNING, "Unable to lock format list\n");
00146 return -1;
00147 }
00148 tmp = formats;
00149 while(tmp) {
00150 if (!strcasecmp(name, tmp->name)) {
00151 if (tmpl)
00152 tmpl->next = tmp->next;
00153 else
00154 formats = tmp->next;
00155 free(tmp);
00156 ast_mutex_unlock(&formatlock);
00157 if (option_verbose > 1)
00158 ast_verbose( VERBOSE_PREFIX_2 "Unregistered format %s\n", name);
00159 return 0;
00160 }
00161 tmpl = tmp;
00162 tmp = tmp->next;
00163 }
00164 ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name);
00165 return -1;
00166 }
|
|
|
|
|
||||||||||||||||
|
Opens stream for use in seeking, playing.
Definition at line 435 of file file.c. References ACTION_OPEN, ast_deactivate_generator(), ast_fileexists(), ast_log(), ast_set_write_format(), ast_stopstream(), and LOG_WARNING. Referenced by ast_streamfile().
00436 {
00437 /* This is a fairly complex routine. Essentially we should do
00438 the following:
00439
00440 1) Find which file handlers produce our type of format.
00441 2) Look for a filename which it can handle.
00442 3) If we find one, then great.
00443 4) If not, see what files are there
00444 5) See what we can actually support
00445 6) Choose the one with the least costly translator path and
00446 set it up.
00447
00448 */
00449 int fd = -1;
00450 int fmts = -1;
00451 char filename2[256]="";
00452 char filename3[256]="";
00453 char *endpart;
00454 int res;
00455 ast_stopstream(chan);
00456 /* do this first, otherwise we detect the wrong writeformat */
00457 if (chan->generator)
00458 ast_deactivate_generator(chan);
00459 if (preflang && !ast_strlen_zero(preflang)) {
00460 strncpy(filename3, filename, sizeof(filename3) - 1);
00461 endpart = strrchr(filename3, '/');
00462 if (endpart) {
00463 *endpart = '\0';
00464 endpart++;
00465 snprintf(filename2, sizeof(filename2), "%s/%s/%s", filename3, preflang, endpart);
00466 } else
00467 snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename);
00468 fmts = ast_fileexists(filename2, NULL, NULL);
00469 }
00470 if (fmts < 1) {
00471 strncpy(filename2, filename, sizeof(filename2)-1);
00472 fmts = ast_fileexists(filename2, NULL, NULL);
00473 }
00474 if (fmts < 1) {
00475 ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
00476 return NULL;
00477 }
00478 chan->oldwriteformat = chan->writeformat;
00479 /* Set the channel to a format we can work with */
00480 res = ast_set_write_format(chan, fmts);
00481
00482 fd = ast_filehelper(filename2, (char *)chan, NULL, ACTION_OPEN);
00483 if (fd >= 0)
00484 return chan->stream;
00485 return NULL;
00486 }
|
|
||||||||||||||||
|
Opens stream for use in seeking, playing.
Definition at line 488 of file file.c. References ACTION_OPEN, ast_fileexists(), ast_log(), ast_filestream::fmt, LOG_WARNING, and MAX_LANGUAGE. Referenced by ast_streamfile().
00489 {
00490 /* This is a fairly complex routine. Essentially we should do
00491 the following:
00492
00493 1) Find which file handlers produce our type of format.
00494 2) Look for a filename which it can handle.
00495 3) If we find one, then great.
00496 4) If not, see what files are there
00497 5) See what we can actually support
00498 6) Choose the one with the least costly translator path and
00499 set it up.
00500
00501 */
00502 int fd = -1;
00503 int fmts = -1;
00504 char filename2[256];
00505 char lang2[MAX_LANGUAGE];
00506 /* XXX H.263 only XXX */
00507 char *fmt = "h263";
00508 if (preflang && !ast_strlen_zero(preflang)) {
00509 snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename);
00510 fmts = ast_fileexists(filename2, fmt, NULL);
00511 if (fmts < 1) {
00512 strncpy(lang2, preflang, sizeof(lang2)-1);
00513 snprintf(filename2, sizeof(filename2), "%s/%s", lang2, filename);
00514 fmts = ast_fileexists(filename2, fmt, NULL);
00515 }
00516 }
00517 if (fmts < 1) {
00518 strncpy(filename2, filename, sizeof(filename2)-1);
00519 fmts = ast_fileexists(filename2, fmt, NULL);
00520 }
00521 if (fmts < 1) {
00522 return NULL;
00523 }
00524 fd = ast_filehelper(filename2, (char *)chan, fmt, ACTION_OPEN);
00525 if (fd >= 0)
00526 return chan->vstream;
00527 ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
00528 return NULL;
00529 }
|
|
|
play a open stream on a channel.
Definition at line 613 of file file.c. References ast_filestream::fmt, and ast_format::format. Referenced by ast_streamfile().
|
|
||||||||||||||||||||||||||||
|
Starts reading from a file.
Definition at line 783 of file file.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_format::exts, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, free, LOG_WARNING, ast_filestream::mode, ast_format::next, ast_format::open, strdup, ast_filestream::trans, and ast_filestream::vfs. Referenced by ast_play_and_prepend().
00784 {
00785 int fd,myflags = 0;
00786 struct ast_format *f;
00787 struct ast_filestream *fs=NULL;
00788 char *fn;
00789 char *ext;
00790 if (ast_mutex_lock(&formatlock)) {
00791 ast_log(LOG_WARNING, "Unable to lock format list\n");
00792 return NULL;
00793 }
00794 f = formats;
00795 while(f) {
00796 if (exts_compare(f->exts, type)) {
00797 char *stringp=NULL;
00798 /* XXX Implement check XXX */
00799 ext = strdup(f->exts);
00800 stringp=ext;
00801 ext = strsep(&stringp, "|");
00802 fn = build_filename(filename, ext);
00803 fd = open(fn, flags | myflags);
00804 if (fd >= 0) {
00805 errno = 0;
00806 if ((fs = f->open(fd))) {
00807 fs->trans = NULL;
00808 fs->fmt = f;
00809 fs->flags = flags;
00810 fs->mode = mode;
00811 fs->filename = strdup(filename);
00812 fs->vfs = NULL;
00813 } else {
00814 ast_log(LOG_WARNING, "Unable to open %s\n", fn);
00815 close(fd);
00816 unlink(fn);
00817 }
00818 } else if (errno != EEXIST)
00819 ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
00820 free(fn);
00821 free(ext);
00822 break;
00823 }
00824 f = f->next;
00825 }
00826 ast_mutex_unlock(&formatlock);
00827 if (!f)
00828 ast_log(LOG_WARNING, "No such format '%s'\n", type);
00829 return fs;
00830 }
|
|
|
Read a frame from a filestream.
Definition at line 531 of file file.c. Referenced by ast_play_and_prepend().
|
|
||||||||||||||||
|
Seeks into stream.
Definition at line 622 of file file.c. References ast_filestream::fmt, and ast_format::seek. Referenced by ast_control_streamfile(), ast_read(), ast_stream_fastforward(), ast_stream_rewind(), and ast_write().
|
|
|
||||||||||||
|
Fast forward stream ms.
Definition at line 637 of file file.c. References ast_seekstream(). Referenced by ast_control_streamfile(), and ast_waitstream_fr().
00638 {
00639 /* I think this is right, 8000 samples per second, 1000 ms a second so 8
00640 * samples per ms */
00641 long samples = ms * 8;
00642 return ast_seekstream(fs, samples, SEEK_CUR);
00643 }
|
|
||||||||||||
|
Rewind stream ms.
Definition at line 645 of file file.c. References ast_seekstream(). Referenced by ast_play_and_prepend(), ast_play_and_record(), and ast_waitstream_fr().
00646 {
00647 long samples = ms * 8;
00648 samples = samples * -1;
00649 return ast_seekstream(fs, samples, SEEK_CUR);
00650 }
|
|
||||||||||||||||
|
Streams a file.
Definition at line 755 of file file.c. References ast_applystream(), ast_getformatname(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_verbose(), LOG_DEBUG, LOG_WARNING, ast_channel::nativeformats, and VERBOSE_PREFIX_3. Referenced by ast_app_getdata(), ast_app_getdata_full(), ast_app_getvoice(), ast_control_streamfile(), ast_play_and_prepend(), ast_play_and_record(), ast_play_and_wait(), ast_say_character_str(), ast_say_character_str_full(), ast_say_digit_str(), ast_say_digit_str_full(), ast_say_phonetic_str(), and ast_say_phonetic_str_full().
00756 {
00757 struct ast_filestream *fs;
00758 struct ast_filestream *vfs;
00759
00760 fs = ast_openstream(chan, filename, preflang);
00761 vfs = ast_openvstream(chan, filename, preflang);
00762 if (vfs)
00763 ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n");
00764 if (fs){
00765 if (ast_applystream(chan, fs))
00766 return -1;
00767 if (vfs && ast_applystream(chan, vfs))
00768 return -1;
00769 if (ast_playstream(fs))
00770 return -1;
00771 if (vfs && ast_playstream(vfs))
00772 return -1;
00773 #if 1
00774 if (option_verbose > 2)
00775 ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (language '%s')\n", filename, preflang ? preflang : "default");
00776 #endif
00777 return 0;
00778 }
00779 ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname(chan->nativeformats), strerror(errno));
00780 return -1;
00781 }
|
|
|
Tell where we are in a stream.
Definition at line 632 of file file.c. References ast_filestream::fmt, and ast_format::tell.
|
|
|
Trunc stream at current location.
Definition at line 627 of file file.c. References ast_filestream::fmt, and ast_format::trunc. Referenced by ast_play_and_prepend(), and ast_play_and_record().
|
|
||||||||||||
|
Waits for a stream to stop or digit to be pressed.
Definition at line 923 of file file.c. References ast_channel::_softhangup, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_waitfor(), ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, ast_frame::subclass, and ast_channel::timingfunc. Referenced by ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record(), ast_play_and_wait(), ast_readstring(), ast_say_character_str(), ast_say_digit_str(), and ast_say_phonetic_str().
00924 {
00925 /* XXX Maybe I should just front-end ast_waitstream_full ? XXX */
00926 int res;
00927 struct ast_frame *fr;
00928 if (!breakon) breakon = "";
00929 while(c->stream) {
00930 res = ast_sched_wait(c->sched);
00931 if ((res < 0) && !c->timingfunc) {
00932 ast_stopstream(c);
00933 break;
00934 }
00935 if (res < 0)
00936 res = 1000;
00937 res = ast_waitfor(c, res);
00938 if (res < 0) {
00939 ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
00940 return res;
00941 } else if (res > 0) {
00942 fr = ast_read(c);
00943 if (!fr) {
00944 #if 0
00945 ast_log(LOG_DEBUG, "Got hung up\n");
00946 #endif
00947 return -1;
00948 }
00949
00950 switch(fr->frametype) {
00951 case AST_FRAME_DTMF:
00952 res = fr->subclass;
00953 if (strchr(breakon, res)) {
00954 ast_frfree(fr);
00955 return res;
00956 }
00957 break;
00958 case AST_FRAME_CONTROL:
00959 switch(fr->subclass) {
00960 case AST_CONTROL_HANGUP:
00961 ast_frfree(fr);
00962 return -1;
00963 case AST_CONTROL_RINGING:
00964 case AST_CONTROL_ANSWER:
00965 /* Unimportant */
00966 break;
00967 default:
00968 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
00969 }
00970 }
00971 /* Ignore */
00972 ast_frfree(fr);
00973 }
00974 ast_sched_runq(c->sched);
00975 }
00976 return (c->_softhangup ? -1 : 0);
00977 }
|
|
||||||||||||||||||||||||
|
Same as waitstream but allows stream to be forwarded or rewound.
Definition at line 979 of file file.c. References ast_channel::_softhangup, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_stream_fastforward(), ast_stream_rewind(), ast_waitfor(), ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, ast_frame::subclass, and ast_channel::timingfunc. Referenced by ast_control_streamfile().
00980 {
00981 int res;
00982 struct ast_frame *fr;
00983 while(c->stream) {
00984 res = ast_sched_wait(c->sched);
00985 if ((res < 0) && !c->timingfunc) {
00986 ast_stopstream(c);
00987 break;
00988 }
00989 if (res < 0)
00990 res = 1000;
00991 res = ast_waitfor(c, res);
00992 if (res < 0) {
00993 ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
00994 return res;
00995 } else
00996 if (res > 0) {
00997 fr = ast_read(c);
00998 if (!fr) {
00999 #if 0
01000 ast_log(LOG_DEBUG, "Got hung up\n");
01001 #endif
01002 return -1;
01003 }
01004
01005 switch(fr->frametype) {
01006 case AST_FRAME_DTMF:
01007 res = fr->subclass;
01008 if (strchr(forward,res)) {
01009 ast_stream_fastforward(c->stream, ms);
01010 } else if (strchr(rewind,res)) {
01011 ast_stream_rewind(c->stream, ms);
01012 } else if (strchr(breakon, res)) {
01013 ast_frfree(fr);
01014 return res;
01015 }
01016 break;
01017 case AST_FRAME_CONTROL:
01018 switch(fr->subclass) {
01019 case AST_CONTROL_HANGUP:
01020 ast_frfree(fr);
01021 return -1;
01022 case AST_CONTROL_RINGING:
01023 case AST_CONTROL_ANSWER:
01024 /* Unimportant */
01025 break;
01026 default:
01027 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
01028 }
01029 }
01030 /* Ignore */
01031 ast_frfree(fr);
01032 } else
01033 ast_sched_runq(c->sched);
01034
01035
01036 }
01037 return (c->_softhangup ? -1 : 0);
01038 }
|
|
||||||||||||||||||||
|
Definition at line 1040 of file file.c. References ast_channel::_softhangup, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_waitfor_nandfds(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, ast_frame::subclass, and ast_channel::timingfunc. Referenced by ast_readstring_full(), ast_say_character_str_full(), ast_say_digit_str_full(), and ast_say_phonetic_str_full().
01041 {
01042 int res;
01043 int ms;
01044 int outfd;
01045 struct ast_frame *fr;
01046 struct ast_channel *rchan;
01047
01048 while(c->stream) {
01049 ms = ast_sched_wait(c->sched);
01050 if ((ms < 0) && !c->timingfunc) {
01051 ast_stopstream(c);
01052 break;
01053 }
01054 if (ms < 0)
01055 ms = 1000;
01056 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01057 if (!rchan && (outfd < 0) && (ms)) {
01058 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01059 return -1;
01060 } else if (outfd > -1) {
01061 /* The FD we were watching has something waiting */
01062 return 1;
01063 } else if (rchan) {
01064 fr = ast_read(c);
01065 if (!fr) {
01066 #if 0
01067 ast_log(LOG_DEBUG, "Got hung up\n");
01068 #endif
01069 return -1;
01070 }
01071
01072 switch(fr->frametype) {
01073 case AST_FRAME_DTMF:
01074 res = fr->subclass;
01075 if (strchr(breakon, res)) {
01076 ast_frfree(fr);
01077 return res;
01078 }
01079 break;
01080 case AST_FRAME_CONTROL:
01081 switch(fr->subclass) {
01082 case AST_CONTROL_HANGUP:
01083 ast_frfree(fr);
01084 return -1;
01085 case AST_CONTROL_RINGING:
01086 case AST_CONTROL_ANSWER:
01087 /* Unimportant */
01088 break;
01089 default:
01090 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
01091 }
01092 case AST_FRAME_VOICE:
01093 /* Write audio if appropriate */
01094 if (audiofd > -1)
01095 write(audiofd, fr->data, fr->datalen);
01096 }
01097 /* Ignore */
01098 ast_frfree(fr);
01099 }
01100 ast_sched_runq(c->sched);
01101
01102
01103 }
01104 return (c->_softhangup ? -1 : 0);
01105 }
|
|
||||||||||||||||||||||||||||
|
Starts writing a file.
Definition at line 832 of file file.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_format::exts, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, free, LOG_WARNING, ast_filestream::mode, ast_format::next, ast_filestream::realfilename, ast_format::rewrite, strdup, ast_filestream::trans, and ast_filestream::vfs. Referenced by ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record(), and ast_writestream().
00833 {
00834 int fd,myflags = 0;
00835 struct ast_format *f;
00836 struct ast_filestream *fs=NULL;
00837 char *fn,*orig_fn=NULL;
00838 char *ext;
00839 char *buf=NULL;
00840 size_t size = 0;
00841
00842 if (ast_mutex_lock(&formatlock)) {
00843 ast_log(LOG_WARNING, "Unable to lock format list\n");
00844 return NULL;
00845 }
00846 /* set the O_TRUNC flag if and only if there is no O_APPEND specified */
00847 if (!(flags & O_APPEND))
00848 myflags = O_TRUNC;
00849
00850 myflags |= O_WRONLY | O_CREAT;
00851
00852 f = formats;
00853 while(f) {
00854 if (exts_compare(f->exts, type)) {
00855 char *stringp=NULL;
00856 /* XXX Implement check XXX */
00857 ext = ast_strdupa(f->exts);
00858 stringp=ext;
00859 ext = strsep(&stringp, "|");
00860 fn = build_filename(filename, ext);
00861 fd = open(fn, flags | myflags, mode);
00862
00863 if (option_cache_record_files && fd >= 0) {
00864 close(fd);
00865 /*
00866 We touch orig_fn just as a place-holder so other things (like vmail) see the file is there.
00867 What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place.
00868 */
00869 orig_fn = ast_strdupa(fn);
00870 for (size=0;size<strlen(fn);size++) {
00871 if (fn[size] == '/')
00872 fn[size] = '_';
00873 }
00874
00875 size += (strlen(record_cache_dir) + 10);
00876 buf = alloca(size);
00877 memset(buf, 0, size);
00878 snprintf(buf, size, "%s/%s", record_cache_dir, fn);
00879 free(fn);
00880 fn=buf;
00881 fd = open(fn, flags | myflags, mode);
00882 }
00883 if (fd >= 0) {
00884 errno = 0;
00885 if ((fs = f->rewrite(fd, comment))) {
00886 fs->trans = NULL;
00887 fs->fmt = f;
00888 fs->flags = flags;
00889 fs->mode = mode;
00890 if (option_cache_record_files) {
00891 fs->realfilename = build_filename(filename, ext);
00892 fs->filename = strdup(fn);
00893 } else {
00894 fs->realfilename = NULL;
00895 fs->filename = strdup(filename);
00896 }
00897 fs->vfs = NULL;
00898 } else {
00899 ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn);
00900 close(fd);
00901 unlink(fn);
00902 if (orig_fn)
00903 unlink(orig_fn);
00904 }
00905 } else if (errno != EEXIST) {
00906 ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
00907 if (orig_fn)
00908 unlink(orig_fn);
00909 }
00910 if (!buf) /* if buf != NULL then fn is already free and pointing to it */
00911 free(fn);
00912
00913 break;
00914 }
00915 f = f->next;
00916 }
00917 ast_mutex_unlock(&formatlock);
00918 if (!f)
00919 ast_log(LOG_WARNING, "No such format '%s'\n", type);
00920 return fs;
00921 }
|
|
||||||||||||
|
Writes a frame to a stream.
Definition at line 181 of file file.c. References ast_getformatname(), ast_log(), ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_writefile(), ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, ast_format::format, ast_frame::frametype, ast_filestream::lastwriteformat, LOG_DEBUG, LOG_WARNING, ast_filestream::mode, ast_format::name, ast_frame::subclass, ast_filestream::trans, type, ast_filestream::vfs, and ast_format::write. Referenced by ast_play_and_prepend(), ast_play_and_record(), ast_read(), and ast_write().
00182 {
00183 struct ast_frame *trf;
00184 int res = -1;
00185 int alt=0;
00186 if (f->frametype == AST_FRAME_VIDEO) {
00187 if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) {
00188 /* This is the audio portion. Call the video one... */
00189 if (!fs->vfs && fs->filename) {
00190 /* XXX Support other video formats XXX */
00191 char *type = "h263";
00192 fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
00193 ast_log(LOG_DEBUG, "Opened video output file\n");
00194 }
00195 if (fs->vfs)
00196 return ast_writestream(fs->vfs, f);
00197 /* Ignore */
00198 return 0;
00199 } else {
00200 /* Might / might not have mark set */
00201 alt = 1;
00202 }
00203 } else if (f->frametype != AST_FRAME_VOICE) {
00204 ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
00205 return -1;
00206 }
00207 if (((fs->fmt->format | alt) & f->subclass) == f->subclass) {
00208 res = fs->fmt->write(fs, f);
00209 if (res < 0)
00210 ast_log(LOG_WARNING, "Natural write failed\n");
00211 if (res > 0)
00212 ast_log(LOG_WARNING, "Huh??\n");
00213 return res;
00214 } else {
00215 /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
00216 the one we've setup a translator for, we do the "wrong thing" XXX */
00217 if (fs->trans && (f->subclass != fs->lastwriteformat)) {
00218 ast_translator_free_path(fs->trans);
00219 fs->trans = NULL;
00220 }
00221 if (!fs->trans)
00222 fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass);
00223 if (!fs->trans)
00224 ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n", fs->fmt->name, ast_getformatname(f->subclass));
00225 else {
00226 fs->lastwriteformat = f->subclass;
00227 res = 0;
00228 /* Get the translated frame but don't consume the original in case they're using it on another stream */
00229 trf = ast_translate(fs->trans, f, 0);
00230 if (trf) {
00231 res = fs->fmt->write(fs, trf);
00232 if (res)
00233 ast_log(LOG_WARNING, "Translated frame write failed\n");
00234 } else
00235 res = 0;
00236 }
00237 return res;
00238 }
00239 }
|
|
|
|
1.2.15