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