2 * Asterisk -- A telephony toolkit for Linux.
4 * Flat, binary, ADPCM vox file format.
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
14 #include <asterisk/lock.h>
15 #include <asterisk/channel.h>
16 #include <asterisk/file.h>
17 #include <asterisk/logger.h>
18 #include <asterisk/sched.h>
19 #include <asterisk/module.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
32 #include <machine/endian.h>
35 #define BUF_SIZE 80 /* 160 samples */
37 struct ast_filestream {
38 void *reserved[AST_RESERVED_POINTERS];
39 /* This is what a filestream means to us */
40 int fd; /* Descriptor */
41 struct ast_frame fr; /* Frame information */
42 char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
43 char empty; /* Empty character */
44 unsigned char buf[BUF_SIZE]; /* Output Buffer */
47 short signal; /* Signal level (file side) */
48 short ssindex; /* Signal ssindex (file side) */
49 unsigned char zero_count; /* counter of consecutive zero samples */
50 unsigned char next_flag;
54 AST_MUTEX_DEFINE_STATIC(vox_lock);
55 static int glistcnt = 0;
57 static char *name = "vox";
58 static char *desc = "Dialogic VOX (ADPCM) File Format";
59 static char *exts = "vox";
61 static struct ast_filestream *vox_open(int fd)
63 /* We don't have any header to read or anything really, but
64 if we did, it would go here. We also might want to check
65 and be sure it's a valid file. */
66 struct ast_filestream *tmp;
67 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
68 memset(tmp, 0, sizeof(struct ast_filestream));
69 if (ast_mutex_lock(&vox_lock)) {
70 ast_log(LOG_WARNING, "Unable to lock vox list\n");
75 tmp->fr.data = tmp->buf;
76 tmp->fr.frametype = AST_FRAME_VOICE;
77 tmp->fr.subclass = AST_FORMAT_ADPCM;
78 /* datalen will vary for each frame */
81 tmp->lasttimeout = -1;
83 ast_mutex_unlock(&vox_lock);
84 ast_update_use_count();
89 static struct ast_filestream *vox_rewrite(int fd, char *comment)
91 /* We don't have any header to read or anything really, but
92 if we did, it would go here. We also might want to check
93 and be sure it's a valid file. */
94 struct ast_filestream *tmp;
95 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
96 memset(tmp, 0, sizeof(struct ast_filestream));
97 if (ast_mutex_lock(&vox_lock)) {
98 ast_log(LOG_WARNING, "Unable to lock vox list\n");
104 ast_mutex_unlock(&vox_lock);
105 ast_update_use_count();
107 ast_log(LOG_WARNING, "Out of memory\n");
111 static void vox_close(struct ast_filestream *s)
113 if (ast_mutex_lock(&vox_lock)) {
114 ast_log(LOG_WARNING, "Unable to lock vox list\n");
118 ast_mutex_unlock(&vox_lock);
119 ast_update_use_count();
125 static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext)
128 /* Send a frame from the file to the appropriate channel */
129 s->fr.frametype = AST_FRAME_VOICE;
130 s->fr.subclass = AST_FORMAT_ADPCM;
131 s->fr.offset = AST_FRIENDLY_OFFSET;
134 if ((res = read(s->fd, s->buf, BUF_SIZE)) < 1) {
136 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
139 s->fr.samples = res * 2;
141 *whennext = s->fr.samples;
145 static int vox_write(struct ast_filestream *fs, struct ast_frame *f)
148 if (f->frametype != AST_FRAME_VOICE) {
149 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
152 if (f->subclass != AST_FORMAT_ADPCM) {
153 ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%d)!\n", f->subclass);
156 if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) {
157 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
163 static char *vox_getcomment(struct ast_filestream *s)
168 static int vox_seek(struct ast_filestream *fs, long sample_offset, int whence)
170 off_t offset=0,min,cur,max,distance;
173 cur = lseek(fs->fd, 0, SEEK_CUR);
174 max = lseek(fs->fd, 0, SEEK_END);
175 /* have to fudge to frame here, so not fully to sample */
176 distance = sample_offset/2;
177 if(whence == SEEK_SET)
179 else if(whence == SEEK_CUR || whence == SEEK_FORCECUR)
180 offset = distance + cur;
181 else if(whence == SEEK_END)
182 offset = max - distance;
183 if (whence != SEEK_FORCECUR) {
184 offset = (offset > max)?max:offset;
185 offset = (offset < min)?min:offset;
187 return lseek(fs->fd, offset, SEEK_SET);
190 static int vox_trunc(struct ast_filestream *fs)
192 return ftruncate(fs->fd, lseek(fs->fd,0,SEEK_CUR));
195 static long vox_tell(struct ast_filestream *fs)
198 offset = lseek(fs->fd, 0, SEEK_CUR);
204 return ast_format_register(name, exts, AST_FORMAT_ADPCM,
220 return ast_format_unregister(name);
226 if (ast_mutex_lock(&vox_lock)) {
227 ast_log(LOG_WARNING, "Unable to lock vox list\n");
231 ast_mutex_unlock(&vox_lock);
243 return ASTERISK_GPL_KEY;