format_vox.c
Go to the documentation of this file.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 #include "asterisk.h"
00028
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 117802 $")
00030
00031 #include "asterisk/mod_format.h"
00032 #include "asterisk/module.h"
00033 #include "asterisk/endian.h"
00034
00035 #define BUF_SIZE 80
00036 #define VOX_SAMPLES 160
00037
00038 static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext)
00039 {
00040 int res;
00041
00042
00043 s->fr.frametype = AST_FRAME_VOICE;
00044 s->fr.subclass = AST_FORMAT_ADPCM;
00045 s->fr.mallocd = 0;
00046 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
00047 if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
00048 if (res)
00049 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00050 return NULL;
00051 }
00052 *whennext = s->fr.samples = res * 2;
00053 s->fr.datalen = res;
00054 return &s->fr;
00055 }
00056
00057 static int vox_write(struct ast_filestream *s, struct ast_frame *f)
00058 {
00059 int res;
00060 if (f->frametype != AST_FRAME_VOICE) {
00061 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00062 return -1;
00063 }
00064 if (f->subclass != AST_FORMAT_ADPCM) {
00065 ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%d)!\n", f->subclass);
00066 return -1;
00067 }
00068 if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) {
00069 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
00070 return -1;
00071 }
00072 return 0;
00073 }
00074
00075 static int vox_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00076 {
00077 off_t offset=0,min,cur,max,distance;
00078
00079 min = 0;
00080 cur = ftello(fs->f);
00081 fseeko(fs->f, 0, SEEK_END);
00082 max = ftello(fs->f);
00083
00084
00085 distance = sample_offset/2;
00086 if(whence == SEEK_SET)
00087 offset = distance;
00088 else if(whence == SEEK_CUR || whence == SEEK_FORCECUR)
00089 offset = distance + cur;
00090 else if(whence == SEEK_END)
00091 offset = max - distance;
00092 if (whence != SEEK_FORCECUR) {
00093 offset = (offset > max)?max:offset;
00094 offset = (offset < min)?min:offset;
00095 }
00096 return fseeko(fs->f, offset, SEEK_SET);
00097 }
00098
00099 static int vox_trunc(struct ast_filestream *fs)
00100 {
00101 return ftruncate(fileno(fs->f), ftello(fs->f));
00102 }
00103
00104 static off_t vox_tell(struct ast_filestream *fs)
00105 {
00106 off_t offset;
00107 offset = ftello(fs->f) << 1;
00108 return offset;
00109 }
00110
00111 static const struct ast_format vox_f = {
00112 .name = "vox",
00113 .exts = "vox",
00114 .format = AST_FORMAT_ADPCM,
00115 .write = vox_write,
00116 .seek = vox_seek,
00117 .trunc = vox_trunc,
00118 .tell = vox_tell,
00119 .read = vox_read,
00120 .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00121 };
00122
00123 static int load_module(void)
00124 {
00125 if (ast_format_register(&vox_f))
00126 return AST_MODULE_LOAD_FAILURE;
00127 return AST_MODULE_LOAD_SUCCESS;
00128 }
00129
00130 static int unload_module(void)
00131 {
00132 return ast_format_unregister(vox_f.name);
00133 }
00134
00135 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialogic VOX (ADPCM) File Format");