#include <sys/types.h>
#include <asterisk/frame.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/sched.h>
#include <asterisk/options.h>
#include <asterisk/translate.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.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 |
Functions | |
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. | |
int | ast_stopstream (struct ast_channel *tmp) |
Stops a stream. | |
int | ast_writestream (struct ast_filestream *fs, struct ast_frame *f) |
Writes a frame to a stream. | |
ast_filestream * | ast_openstream (struct ast_channel *chan, char *filename, char *preflang) |
Opens stream for use in seeking, playing. | |
ast_filestream * | ast_openvstream (struct ast_channel *chan, char *filename, char *preflang) |
Opens stream for use in seeking, playing. | |
ast_frame * | ast_readframe (struct ast_filestream *s) |
Read a frame from a filestream. | |
int | ast_applystream (struct ast_channel *chan, struct ast_filestream *s) |
Applys a open stream to a channel. | |
int | ast_playstream (struct ast_filestream *s) |
play a open stream on a channel. | |
int | ast_seekstream (struct ast_filestream *fs, long sample_offset, int whence) |
Seeks into stream. | |
int | ast_truncstream (struct ast_filestream *fs) |
Trunc stream at current location. | |
long | ast_tellstream (struct ast_filestream *fs) |
Tell where we are in a stream. | |
int | ast_stream_fastforward (struct ast_filestream *fs, long ms) |
Fast forward stream ms. | |
int | ast_stream_rewind (struct ast_filestream *fs, long ms) |
Rewind stream ms. | |
int | ast_closestream (struct ast_filestream *f) |
Closes a stream. | |
int | ast_fileexists (char *filename, char *fmt, char *preflang) |
Checks for the existence of a given file. | |
int | ast_filedelete (char *filename, char *fmt) |
Deletes a file. | |
int | ast_filerename (char *filename, char *filename2, char *fmt) |
Renames a file. | |
int | ast_filecopy (char *filename, char *filename2, char *fmt) |
Copies a file. | |
int | ast_streamfile (struct ast_channel *chan, char *filename, char *preflang) |
Streams a file. | |
ast_filestream * | ast_readfile (char *filename, char *type, char *comment, int flags, int check, mode_t mode) |
Starts reading from a file. | |
ast_filestream * | ast_writefile (char *filename, char *type, char *comment, int flags, int check, mode_t mode) |
Starts writing a file. | |
char | ast_waitstream (struct ast_channel *c, char *breakon) |
Waits for a stream to stop or digit to be pressed. | |
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. | |
char | ast_waitstream_full (struct ast_channel *c, char *breakon, int audiofd, int cmdfd) |
|
Definition at line 294 of file file.c. Referenced by ast_filecopy(). |
|
Definition at line 291 of file file.c. Referenced by ast_filedelete(). |
|
Definition at line 290 of file file.c. Referenced by ast_fileexists(). |
|
Definition at line 293 of file file.c. Referenced by ast_openstream(), and ast_openvstream(). |
|
Definition at line 292 of file file.c. Referenced by ast_filerename(). |
|
Applys a open stream to a channel.
Definition at line 578 of file file.c. References s. Referenced by ast_streamfile().
00579 { 00580 s->owner = chan; 00581 return 0; 00582 } |
|
Closes a stream.
Definition at line 623 of file file.c. References AST_FORMAT_MAX_AUDIO, 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_channel::sched, ast_channel::stream, ast_channel::streamid, ast_filestream::trans, ast_channel::vstream, and ast_channel::vstreamid. Referenced by ast_app_getvoice(), and ast_stopstream().
00624 { 00625 /* Stop a running stream if there is one */ 00626 if (f->owner) { 00627 if (f->fmt->format < AST_FORMAT_MAX_AUDIO) { 00628 f->owner->stream = NULL; 00629 if (f->owner->streamid > -1) 00630 ast_sched_del(f->owner->sched, f->owner->streamid); 00631 f->owner->streamid = -1; 00632 #ifdef ZAPTEL_OPTIMIZATIONS 00633 ast_settimeout(f->owner, 0, NULL, NULL); 00634 #endif 00635 } else { 00636 f->owner->vstream = NULL; 00637 if (f->owner->vstreamid > -1) 00638 ast_sched_del(f->owner->sched, f->owner->vstreamid); 00639 f->owner->vstreamid = -1; 00640 } 00641 } 00642 /* destroy the translator on exit */ 00643 if (f->trans) { 00644 ast_translator_free_path(f->trans); 00645 f->trans = NULL; 00646 } 00647 if (f->filename) 00648 free(f->filename); 00649 f->filename = NULL; 00650 f->fmt->close(f); 00651 return 0; 00652 } |
|
Copies a file.
Definition at line 705 of file file.c. References ACTION_COPY.
00706 {
00707 return ast_filehelper(filename, filename2, fmt, ACTION_COPY);
00708 }
|
|
Deletes a file.
Definition at line 695 of file file.c. References ACTION_DELETE.
00696 {
00697 return ast_filehelper(filename, NULL, fmt, ACTION_DELETE);
00698 }
|
|
Checks for the existence of a given file.
Definition at line 655 of file file.c. References ACTION_EXISTS, and MAX_LANGUAGE. Referenced by ast_openstream(), and ast_openvstream().
00656 { 00657 char filename2[256]; 00658 char tmp[256]; 00659 char *postfix; 00660 char *prefix; 00661 char *c; 00662 char lang2[MAX_LANGUAGE]; 00663 int res = -1; 00664 if (preflang && strlen(preflang)) { 00665 /* Insert the language between the last two parts of the path */ 00666 strncpy(tmp, filename, sizeof(tmp) - 1); 00667 c = strrchr(tmp, '/'); 00668 if (c) { 00669 *c = '\0'; 00670 postfix = c+1; 00671 prefix = tmp; 00672 } else { 00673 postfix = tmp; 00674 prefix=""; 00675 } 00676 snprintf(filename2, sizeof(filename2), "%s/%s/%s", prefix, preflang, postfix); 00677 res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS); 00678 if (res < 1) { 00679 char *stringp=NULL; 00680 strncpy(lang2, preflang, sizeof(lang2)-1); 00681 stringp=lang2; 00682 strsep(&stringp, "_"); 00683 if (strcmp(lang2, preflang)) { 00684 snprintf(filename2, sizeof(filename2), "%s/%s/%s", prefix, lang2, postfix); 00685 res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS); 00686 } 00687 } 00688 } 00689 if (res < 1) { 00690 res = ast_filehelper(filename, NULL, fmt, ACTION_EXISTS); 00691 } 00692 return res; 00693 } |
|
Renames a file.
Definition at line 700 of file file.c. References ACTION_RENAME.
00701 {
00702 return ast_filehelper(filename, filename2, fmt, ACTION_RENAME);
00703 }
|
|
Definition at line 85 of file file.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), LOG_WARNING, malloc, option_verbose, and VERBOSE_PREFIX_2.
00095 { 00096 struct ast_format *tmp; 00097 if (ast_mutex_lock(&formatlock)) { 00098 ast_log(LOG_WARNING, "Unable to lock format list\n"); 00099 return -1; 00100 } 00101 tmp = formats; 00102 while(tmp) { 00103 if (!strcasecmp(name, tmp->name)) { 00104 ast_mutex_unlock(&formatlock); 00105 ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", name); 00106 return -1; 00107 } 00108 tmp = tmp->next; 00109 } 00110 tmp = malloc(sizeof(struct ast_format)); 00111 if (!tmp) { 00112 ast_log(LOG_WARNING, "Out of memory\n"); 00113 ast_mutex_unlock(&formatlock); 00114 return -1; 00115 } 00116 strncpy(tmp->name, name, sizeof(tmp->name)-1); 00117 strncpy(tmp->exts, exts, sizeof(tmp->exts)-1); 00118 tmp->open = open; 00119 tmp->rewrite = rewrite; 00120 tmp->read = read; 00121 tmp->write = write; 00122 tmp->seek = seek; 00123 tmp->trunc = trunc; 00124 tmp->tell = tell; 00125 tmp->close = close; 00126 tmp->format = format; 00127 tmp->getcomment = getcomment; 00128 tmp->next = formats; 00129 formats = tmp; 00130 ast_mutex_unlock(&formatlock); 00131 if (option_verbose > 1) 00132 ast_verbose( VERBOSE_PREFIX_2 "Registered file format %s, extension(s) %s\n", name, exts); 00133 return 0; 00134 } |
|
Unregisters a file format.
Definition at line 136 of file file.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, LOG_WARNING, ast_format::next, option_verbose, and VERBOSE_PREFIX_2.
00137 { 00138 struct ast_format *tmp, *tmpl = NULL; 00139 if (ast_mutex_lock(&formatlock)) { 00140 ast_log(LOG_WARNING, "Unable to lock format list\n"); 00141 return -1; 00142 } 00143 tmp = formats; 00144 while(tmp) { 00145 if (!strcasecmp(name, tmp->name)) { 00146 if (tmpl) 00147 tmpl->next = tmp->next; 00148 else 00149 formats = tmp->next; 00150 free(tmp); 00151 ast_mutex_unlock(&formatlock); 00152 if (option_verbose > 1) 00153 ast_verbose( VERBOSE_PREFIX_2 "Unregistered format %s\n", name); 00154 return 0; 00155 } 00156 tmp = tmp->next; 00157 } 00158 ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name); 00159 return -1; 00160 } |
|
Opens stream for use in seeking, playing.
Definition at line 406 of file file.c. References ACTION_OPEN, ast_deactivate_generator(), ast_fileexists(), ast_log(), ast_set_write_format(), ast_stopstream(), ast_channel::generator, LOG_WARNING, ast_channel::oldwriteformat, and ast_channel::writeformat. Referenced by ast_streamfile().
00407 { 00408 /* This is a fairly complex routine. Essentially we should do 00409 the following: 00410 00411 1) Find which file handlers produce our type of format. 00412 2) Look for a filename which it can handle. 00413 3) If we find one, then great. 00414 4) If not, see what files are there 00415 5) See what we can actually support 00416 6) Choose the one with the least costly translator path and 00417 set it up. 00418 00419 */ 00420 int fd = -1; 00421 int fmts = -1; 00422 char filename2[256]=""; 00423 char filename3[256]=""; 00424 char *endpart; 00425 int res; 00426 ast_stopstream(chan); 00427 /* do this first, otherwise we detect the wrong writeformat */ 00428 if (chan->generator) 00429 ast_deactivate_generator(chan); 00430 if (preflang && strlen(preflang)) { 00431 strncpy(filename3, filename, sizeof(filename3) - 1); 00432 endpart = strrchr(filename3, '/'); 00433 if (endpart) { 00434 *endpart = '\0'; 00435 endpart++; 00436 snprintf(filename2, sizeof(filename2), "%s/%s/%s", filename3, preflang, endpart); 00437 } else 00438 snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename); 00439 fmts = ast_fileexists(filename2, NULL, NULL); 00440 } 00441 if (fmts < 1) { 00442 strncpy(filename2, filename, sizeof(filename2)-1); 00443 fmts = ast_fileexists(filename2, NULL, NULL); 00444 } 00445 if (fmts < 1) { 00446 ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename); 00447 return NULL; 00448 } 00449 chan->oldwriteformat = chan->writeformat; 00450 /* Set the channel to a format we can work with */ 00451 res = ast_set_write_format(chan, fmts); 00452 00453 fd = ast_filehelper(filename2, (char *)chan, NULL, ACTION_OPEN); 00454 if(fd >= 0) 00455 return chan->stream; 00456 return NULL; 00457 } |
|
Opens stream for use in seeking, playing.
Definition at line 459 of file file.c. References ACTION_OPEN, ast_fileexists(), ast_log(), LOG_WARNING, and MAX_LANGUAGE. Referenced by ast_streamfile().
00460 { 00461 /* This is a fairly complex routine. Essentially we should do 00462 the following: 00463 00464 1) Find which file handlers produce our type of format. 00465 2) Look for a filename which it can handle. 00466 3) If we find one, then great. 00467 4) If not, see what files are there 00468 5) See what we can actually support 00469 6) Choose the one with the least costly translator path and 00470 set it up. 00471 00472 */ 00473 int fd = -1; 00474 int fmts = -1; 00475 char filename2[256]; 00476 char lang2[MAX_LANGUAGE]; 00477 /* XXX H.263 only XXX */ 00478 char *fmt = "h263"; 00479 if (preflang && strlen(preflang)) { 00480 snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename); 00481 fmts = ast_fileexists(filename2, fmt, NULL); 00482 if (fmts < 1) { 00483 strncpy(lang2, preflang, sizeof(lang2)-1); 00484 snprintf(filename2, sizeof(filename2), "%s/%s", lang2, filename); 00485 fmts = ast_fileexists(filename2, fmt, NULL); 00486 } 00487 } 00488 if (fmts < 1) { 00489 strncpy(filename2, filename, sizeof(filename2)-1); 00490 fmts = ast_fileexists(filename2, fmt, NULL); 00491 } 00492 if (fmts < 1) { 00493 return NULL; 00494 } 00495 fd = ast_filehelper(filename2, (char *)chan, fmt, ACTION_OPEN); 00496 if(fd >= 0) 00497 return chan->vstream; 00498 ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename); 00499 return NULL; 00500 } |
|
play a open stream on a channel.
Definition at line 584 of file file.c. References AST_FORMAT_MAX_AUDIO, and s. Referenced by ast_streamfile().
00585 { 00586 if (s->fmt->format < AST_FORMAT_MAX_AUDIO) 00587 ast_readaudio_callback(s); 00588 else 00589 ast_readvideo_callback(s); 00590 return 0; 00591 } |
|
Starts reading from a file.
Definition at line 738 of file file.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, free, LOG_WARNING, strdup, and type.
00739 { 00740 int fd,myflags = 0; 00741 struct ast_format *f; 00742 struct ast_filestream *fs=NULL; 00743 char *fn; 00744 char *ext; 00745 if (ast_mutex_lock(&formatlock)) { 00746 ast_log(LOG_WARNING, "Unable to lock format list\n"); 00747 return NULL; 00748 } 00749 f = formats; 00750 while(f) { 00751 if (!strcasecmp(f->name, type)) { 00752 char *stringp=NULL; 00753 /* XXX Implement check XXX */ 00754 ext = strdup(f->exts); 00755 stringp=ext; 00756 ext = strsep(&stringp, "|"); 00757 fn = build_filename(filename, ext); 00758 fd = open(fn, flags | myflags); 00759 if (fd >= 0) { 00760 errno = 0; 00761 if ((fs = f->open(fd))) { 00762 fs->trans = NULL; 00763 fs->fmt = f; 00764 fs->flags = flags; 00765 fs->mode = mode; 00766 fs->filename = strdup(filename); 00767 fs->vfs = NULL; 00768 } else { 00769 ast_log(LOG_WARNING, "Unable to open %s\n", fn); 00770 close(fd); 00771 unlink(fn); 00772 } 00773 } else if (errno != EEXIST) 00774 ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno)); 00775 free(fn); 00776 free(ext); 00777 break; 00778 } 00779 f = f->next; 00780 } 00781 ast_mutex_unlock(&formatlock); 00782 if (!f) 00783 ast_log(LOG_WARNING, "No such format '%s'\n", type); 00784 return fs; 00785 } |
|
Read a frame from a filestream.
Definition at line 502 of file file.c. References s.
|
|
Seeks into stream.
Definition at line 593 of file file.c. References ast_filestream::fmt, and ast_format::seek. Referenced by ast_read(), ast_stream_fastforward(), ast_stream_rewind(), and ast_write().
|
|
Stops a stream.
Definition at line 162 of file file.c. References ast_closestream(), ast_log(), ast_set_write_format(), LOG_WARNING, ast_channel::oldwriteformat, ast_channel::stream, and ast_channel::vstream. Referenced by ast_hangup(), ast_openstream(), ast_readstring(), ast_readstring_full(), ast_say_digit_str(), ast_say_digit_str_full(), ast_say_number(), ast_say_number_full(), ast_waitstream(), ast_waitstream_fr(), and ast_waitstream_full().
00163 { 00164 /* Stop a running stream if there is one */ 00165 if (tmp->vstream) 00166 ast_closestream(tmp->vstream); 00167 if (tmp->stream) { 00168 ast_closestream(tmp->stream); 00169 if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat)) 00170 ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat); 00171 } 00172 return 0; 00173 } |
|
Fast forward stream ms.
Definition at line 608 of file file.c. References ast_seekstream(). Referenced by ast_waitstream_fr().
00609 { 00610 /* I think this is right, 8000 samples per second, 1000 ms a second so 8 00611 * samples per ms */ 00612 long samples = ms * 8; 00613 return ast_seekstream(fs, samples, SEEK_CUR); 00614 } |
|
Rewind stream ms.
Definition at line 616 of file file.c. References ast_seekstream(). Referenced by ast_waitstream_fr().
00617 { 00618 long samples = ms * 8; 00619 samples = samples * -1; 00620 return ast_seekstream(fs, samples, SEEK_CUR); 00621 } |
|
Streams a file.
Definition at line 710 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, option_verbose, and VERBOSE_PREFIX_3. Referenced by ast_app_getdata(), ast_app_getdata_full(), ast_app_getvoice(), ast_say_date(), ast_say_datetime(), ast_say_datetime_from_now(), ast_say_digit_str(), ast_say_digit_str_full(), ast_say_number(), ast_say_number_full(), and ast_say_time().
00711 { 00712 struct ast_filestream *fs; 00713 struct ast_filestream *vfs; 00714 00715 fs = ast_openstream(chan, filename, preflang); 00716 vfs = ast_openvstream(chan, filename, preflang); 00717 if (vfs) 00718 ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n"); 00719 if(fs){ 00720 if(ast_applystream(chan, fs)) 00721 return -1; 00722 if(vfs && ast_applystream(chan, vfs)) 00723 return -1; 00724 if(ast_playstream(fs)) 00725 return -1; 00726 if(vfs && ast_playstream(vfs)) 00727 return -1; 00728 #if 1 00729 if (option_verbose > 2) 00730 ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (language '%s')\n", filename, preflang ? preflang : "default"); 00731 #endif 00732 return 0; 00733 } 00734 ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname(chan->nativeformats), strerror(errno)); 00735 return -1; 00736 } |
|
Tell where we are in a stream.
Definition at line 603 of file file.c. References ast_filestream::fmt, and ast_format::tell.
|
|
Trunc stream at current location.
Definition at line 598 of file file.c. References ast_filestream::fmt, and ast_format::trunc.
|
|
Waits for a stream to stop or digit to be pressed.
Definition at line 842 of file file.c. References ast_channel::_softhangup, AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_waitfor(), LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, and ast_channel::timingfunc. Referenced by ast_app_getvoice(), ast_readstring(), ast_say_date(), ast_say_datetime(), ast_say_datetime_from_now(), ast_say_digit_str(), ast_say_number(), and ast_say_time().
00843 { 00844 /* XXX Maybe I should just front-end ast_waitstream_full ? XXX */ 00845 int res; 00846 struct ast_frame *fr; 00847 while(c->stream) { 00848 res = ast_sched_wait(c->sched); 00849 if ((res < 0) && !c->timingfunc) { 00850 ast_stopstream(c); 00851 break; 00852 } 00853 if (res < 0) 00854 res = 1000; 00855 res = ast_waitfor(c, res); 00856 if (res < 0) { 00857 ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno)); 00858 return res; 00859 } else if (res > 0) { 00860 fr = ast_read(c); 00861 if (!fr) { 00862 #if 0 00863 ast_log(LOG_DEBUG, "Got hung up\n"); 00864 #endif 00865 return -1; 00866 } 00867 00868 switch(fr->frametype) { 00869 case AST_FRAME_DTMF: 00870 res = fr->subclass; 00871 if (strchr(breakon, res)) { 00872 ast_frfree(fr); 00873 return res; 00874 } 00875 break; 00876 case AST_FRAME_CONTROL: 00877 switch(fr->subclass) { 00878 case AST_CONTROL_HANGUP: 00879 ast_frfree(fr); 00880 return -1; 00881 case AST_CONTROL_RINGING: 00882 case AST_CONTROL_ANSWER: 00883 /* Unimportant */ 00884 break; 00885 default: 00886 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass); 00887 } 00888 } 00889 /* Ignore */ 00890 ast_frfree(fr); 00891 } 00892 ast_sched_runq(c->sched); 00893 } 00894 return (c->_softhangup ? -1 : 0); 00895 } |
|
Same as waitstream but allows stream to be forwarded or rewound.
Definition at line 897 of file file.c. References ast_channel::_softhangup, AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_stream_fastforward(), ast_stream_rewind(), ast_waitfor(), LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, and ast_channel::timingfunc.
00898 { 00899 int res; 00900 struct ast_frame *fr; 00901 while(c->stream) { 00902 res = ast_sched_wait(c->sched); 00903 if ((res < 0) && !c->timingfunc) { 00904 ast_stopstream(c); 00905 break; 00906 } 00907 if (res < 0) 00908 res = 1000; 00909 res = ast_waitfor(c, res); 00910 if (res < 0) { 00911 ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno)); 00912 return res; 00913 } else 00914 if (res > 0) { 00915 fr = ast_read(c); 00916 if (!fr) { 00917 #if 0 00918 ast_log(LOG_DEBUG, "Got hung up\n"); 00919 #endif 00920 return -1; 00921 } 00922 00923 switch(fr->frametype) { 00924 case AST_FRAME_DTMF: 00925 res = fr->subclass; 00926 if (strchr(forward,res)) { 00927 ast_stream_fastforward(c->stream, ms); 00928 } else if (strchr(rewind,res)) { 00929 ast_stream_rewind(c->stream, ms); 00930 } else if (strchr(breakon, res)) { 00931 ast_frfree(fr); 00932 return res; 00933 } 00934 break; 00935 case AST_FRAME_CONTROL: 00936 switch(fr->subclass) { 00937 case AST_CONTROL_HANGUP: 00938 ast_frfree(fr); 00939 return -1; 00940 case AST_CONTROL_RINGING: 00941 case AST_CONTROL_ANSWER: 00942 /* Unimportant */ 00943 break; 00944 default: 00945 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass); 00946 } 00947 } 00948 /* Ignore */ 00949 ast_frfree(fr); 00950 } else 00951 ast_sched_runq(c->sched); 00952 00953 00954 } 00955 return (c->_softhangup ? -1 : 0); 00956 } |
|
Definition at line 958 of file file.c. References ast_channel::_softhangup, AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_waitfor_nandfds(), LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, and ast_channel::timingfunc. Referenced by ast_readstring_full(), ast_say_digit_str_full(), and ast_say_number_full().
00959 { 00960 int res; 00961 int ms; 00962 int outfd; 00963 struct ast_frame *fr; 00964 struct ast_channel *rchan; 00965 00966 while(c->stream) { 00967 ms = ast_sched_wait(c->sched); 00968 if ((ms < 0) && !c->timingfunc) { 00969 ast_stopstream(c); 00970 break; 00971 } 00972 if (ms < 0) 00973 ms = 1000; 00974 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 00975 if (!rchan && (outfd < 0) && (ms)) { 00976 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 00977 return -1; 00978 } else if (outfd > -1) { 00979 /* The FD we were watching has something waiting */ 00980 return 1; 00981 } else if (rchan) { 00982 fr = ast_read(c); 00983 if (!fr) { 00984 #if 0 00985 ast_log(LOG_DEBUG, "Got hung up\n"); 00986 #endif 00987 return -1; 00988 } 00989 00990 switch(fr->frametype) { 00991 case AST_FRAME_DTMF: 00992 res = fr->subclass; 00993 if (strchr(breakon, res)) { 00994 ast_frfree(fr); 00995 return res; 00996 } 00997 break; 00998 case AST_FRAME_CONTROL: 00999 switch(fr->subclass) { 01000 case AST_CONTROL_HANGUP: 01001 ast_frfree(fr); 01002 return -1; 01003 case AST_CONTROL_RINGING: 01004 case AST_CONTROL_ANSWER: 01005 /* Unimportant */ 01006 break; 01007 default: 01008 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass); 01009 } 01010 case AST_FRAME_VOICE: 01011 /* Write audio if appropriate */ 01012 if (audiofd > -1) 01013 write(audiofd, fr->data, fr->datalen); 01014 } 01015 /* Ignore */ 01016 ast_frfree(fr); 01017 } 01018 ast_sched_runq(c->sched); 01019 01020 01021 } 01022 return (c->_softhangup ? -1 : 0); 01023 } |
|
Starts writing a file.
Definition at line 787 of file file.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, free, LOG_WARNING, strdup, and type. Referenced by ast_app_getvoice(), and ast_writestream().
00788 { 00789 int fd,myflags = 0; 00790 struct ast_format *f; 00791 struct ast_filestream *fs=NULL; 00792 char *fn; 00793 char *ext; 00794 if (ast_mutex_lock(&formatlock)) { 00795 ast_log(LOG_WARNING, "Unable to lock format list\n"); 00796 return NULL; 00797 } 00798 /* set the O_TRUNC flag if and only if there is no O_APPEND specified */ 00799 if (!(flags & O_APPEND)) 00800 myflags = O_TRUNC; 00801 00802 myflags |= O_WRONLY | O_CREAT; 00803 00804 f = formats; 00805 while(f) { 00806 if (!strcasecmp(f->name, type)) { 00807 char *stringp=NULL; 00808 /* XXX Implement check XXX */ 00809 ext = strdup(f->exts); 00810 stringp=ext; 00811 ext = strsep(&stringp, "|"); 00812 fn = build_filename(filename, ext); 00813 fd = open(fn, flags | myflags, mode); 00814 if (fd >= 0) { 00815 errno = 0; 00816 if ((fs = f->rewrite(fd, comment))) { 00817 fs->trans = NULL; 00818 fs->fmt = f; 00819 fs->flags = flags; 00820 fs->mode = mode; 00821 fs->filename = strdup(filename); 00822 fs->vfs = NULL; 00823 } else { 00824 ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn); 00825 close(fd); 00826 unlink(fn); 00827 } 00828 } else if (errno != EEXIST) 00829 ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno)); 00830 free(fn); 00831 free(ext); 00832 break; 00833 } 00834 f = f->next; 00835 } 00836 ast_mutex_unlock(&formatlock); 00837 if (!f) 00838 ast_log(LOG_WARNING, "No such format '%s'\n", type); 00839 return fs; 00840 } |
|
Writes a frame to a stream.
Definition at line 175 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_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_read(), and ast_write().
00176 { 00177 struct ast_frame *trf; 00178 int res = -1; 00179 int alt=0; 00180 if (f->frametype == AST_FRAME_VIDEO) { 00181 if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) { 00182 /* This is the audio portion. Call the video one... */ 00183 if (!fs->vfs && fs->filename) { 00184 /* XXX Support other video formats XXX */ 00185 char *type = "h263"; 00186 fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode); 00187 ast_log(LOG_DEBUG, "Opened video output file\n"); 00188 } 00189 if (fs->vfs) 00190 return ast_writestream(fs->vfs, f); 00191 /* Ignore */ 00192 return 0; 00193 } else { 00194 /* Might / might not have mark set */ 00195 alt = 1; 00196 } 00197 } else if (f->frametype != AST_FRAME_VOICE) { 00198 ast_log(LOG_WARNING, "Tried to write non-voice frame\n"); 00199 return -1; 00200 } 00201 if (((fs->fmt->format | alt) & f->subclass) == f->subclass) { 00202 res = fs->fmt->write(fs, f); 00203 if (res < 0) 00204 ast_log(LOG_WARNING, "Natural write failed\n"); 00205 if (res > 0) 00206 ast_log(LOG_WARNING, "Huh??\n"); 00207 return res; 00208 } else { 00209 /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't 00210 the one we've setup a translator for, we do the "wrong thing" XXX */ 00211 if (fs->trans && (f->subclass != fs->lastwriteformat)) { 00212 ast_translator_free_path(fs->trans); 00213 fs->trans = NULL; 00214 } 00215 if (!fs->trans) 00216 fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass); 00217 if (!fs->trans) 00218 ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n", fs->fmt->name, ast_getformatname(f->subclass)); 00219 else { 00220 fs->lastwriteformat = f->subclass; 00221 res = 0; 00222 /* Get the translated frame but don't consume the original in case they're using it on another stream */ 00223 trf = ast_translate(fs->trans, f, 0); 00224 if (trf) { 00225 res = fs->fmt->write(fs, trf); 00226 if (res) 00227 ast_log(LOG_WARNING, "Translated frame write failed\n"); 00228 } else 00229 res = 0; 00230 } 00231 return res; 00232 } 00233 } |