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: 328209 $")
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,cur,max,distance;
00082
00083 min = 0;
00084 cur = ftello(fs->f);
00085 fseeko(fs->f, 0, SEEK_END);
00086 max = ftello(fs->f);
00087
00088
00089 distance = sample_offset/2;
00090 if(whence == SEEK_SET)
00091 offset = distance;
00092 else if(whence == SEEK_CUR || whence == SEEK_FORCECUR)
00093 offset = distance + cur;
00094 else if(whence == SEEK_END)
00095 offset = max - distance;
00096 if (whence != SEEK_FORCECUR) {
00097 offset = (offset > max)?max:offset;
00098 offset = (offset < min)?min:offset;
00099 }
00100 return fseeko(fs->f, offset, SEEK_SET);
00101 }
00102
00103 static int vox_trunc(struct ast_filestream *fs)
00104 {
00105 return ftruncate(fileno(fs->f), ftello(fs->f));
00106 }
00107
00108 static off_t vox_tell(struct ast_filestream *fs)
00109 {
00110 off_t offset;
00111 offset = ftello(fs->f) << 1;
00112 return offset;
00113 }
00114
00115 static const struct ast_format vox_f = {
00116 .name = "vox",
00117 .exts = "vox",
00118 .format = AST_FORMAT_ADPCM,
00119 .write = vox_write,
00120 .seek = vox_seek,
00121 .trunc = vox_trunc,
00122 .tell = vox_tell,
00123 .read = vox_read,
00124 .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00125 };
00126
00127 static int load_module(void)
00128 {
00129 if (ast_format_register(&vox_f))
00130 return AST_MODULE_LOAD_FAILURE;
00131 return AST_MODULE_LOAD_SUCCESS;
00132 }
00133
00134 static int unload_module(void)
00135 {
00136 return ast_format_unregister(vox_f.name);
00137 }
00138
00139 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Dialogic VOX (ADPCM) File Format",
00140 .load = load_module,
00141 .unload = unload_module,
00142 .load_pri = AST_MODPRI_APP_DEPEND
00143 );