00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 364578 $")
00034
00035 #include "asterisk/mod_format.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/endian.h"
00038
00039 #define BUF_SIZE 80
00040 #define VOX_SAMPLES 160
00041
00042 static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext)
00043 {
00044 int res;
00045
00046
00047 s->fr.frametype = AST_FRAME_VOICE;
00048 s->fr.subclass.codec = AST_FORMAT_ADPCM;
00049 s->fr.mallocd = 0;
00050 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
00051 if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
00052 if (res)
00053 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00054 return NULL;
00055 }
00056 *whennext = s->fr.samples = res * 2;
00057 s->fr.datalen = res;
00058 return &s->fr;
00059 }
00060
00061 static int vox_write(struct ast_filestream *s, struct ast_frame *f)
00062 {
00063 int res;
00064 if (f->frametype != AST_FRAME_VOICE) {
00065 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00066 return -1;
00067 }
00068 if (f->subclass.codec != AST_FORMAT_ADPCM) {
00069 ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%s)!\n", ast_getformatname(f->subclass.codec));
00070 return -1;
00071 }
00072 if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) {
00073 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
00074 return -1;
00075 }
00076 return 0;
00077 }
00078
00079 static int vox_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00080 {
00081 off_t offset = 0, min = 0, cur, max, distance;
00082
00083 if ((cur = ftello(fs->f)) < 0) {
00084 ast_log(AST_LOG_WARNING, "Unable to determine current position in g719 filestream %p: %s\n", fs, strerror(errno));
00085 return -1;
00086 }
00087
00088 if (fseeko(fs->f, 0, SEEK_END) < 0) {
00089 ast_log(AST_LOG_WARNING, "Unable to seek to end of g719 filestream %p: %s\n", fs, strerror(errno));
00090 return -1;
00091 }
00092
00093 if ((max = ftello(fs->f)) < 0) {
00094 ast_log(AST_LOG_WARNING, "Unable to determine max position in g719 filestream %p: %s\n", fs, strerror(errno));
00095 return -1;
00096 }
00097
00098
00099 distance = sample_offset/2;
00100 if (whence == SEEK_SET) {
00101 offset = distance;
00102 } else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) {
00103 offset = distance + cur;
00104 } else if (whence == SEEK_END) {
00105 offset = max - distance;
00106 }
00107 if (whence != SEEK_FORCECUR) {
00108 offset = (offset > max)?max:offset;
00109 offset = (offset < min)?min:offset;
00110 }
00111 return fseeko(fs->f, offset, SEEK_SET);
00112 }
00113
00114 static int vox_trunc(struct ast_filestream *fs)
00115 {
00116 int fd;
00117 off_t cur;
00118
00119 if ((fd = fileno(fs->f)) < 0) {
00120 ast_log(AST_LOG_WARNING, "Unable to determine file descriptor for vox filestream %p: %s\n", fs, strerror(errno));
00121 return -1;
00122 }
00123 if ((cur = ftello(fs->f)) < 0) {
00124 ast_log(AST_LOG_WARNING, "Unable to determine current position in vox filestream %p: %s\n", fs, strerror(errno));
00125 return -1;
00126 }
00127
00128 return ftruncate(fd, cur);}
00129
00130 static off_t vox_tell(struct ast_filestream *fs)
00131 {
00132 off_t offset;
00133 offset = ftello(fs->f) << 1;
00134 return offset;
00135 }
00136
00137 static const struct ast_format vox_f = {
00138 .name = "vox",
00139 .exts = "vox",
00140 .format = AST_FORMAT_ADPCM,
00141 .write = vox_write,
00142 .seek = vox_seek,
00143 .trunc = vox_trunc,
00144 .tell = vox_tell,
00145 .read = vox_read,
00146 .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00147 };
00148
00149 static int load_module(void)
00150 {
00151 if (ast_format_register(&vox_f))
00152 return AST_MODULE_LOAD_FAILURE;
00153 return AST_MODULE_LOAD_SUCCESS;
00154 }
00155
00156 static int unload_module(void)
00157 {
00158 return ast_format_unregister(vox_f.name);
00159 }
00160
00161 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Dialogic VOX (ADPCM) File Format",
00162 .load = load_module,
00163 .unload = unload_module,
00164 .load_pri = AST_MODPRI_APP_DEPEND
00165 );