2 * Asterisk -- A telephony toolkit for Linux.
5 * Anthony Minessale (anthmct@yahoo.com)
6 * Derived from format_pcm.c in the asterisk distro
8 * This program is free software, distributed under the terms of
9 * the GNU General Public License
12 #include <asterisk/lock.h>
13 #include <asterisk/channel.h>
14 #include <asterisk/file.h>
15 #include <asterisk/logger.h>
16 #include <asterisk/sched.h>
17 #include <asterisk/module.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
29 #include <machine/endian.h>
32 #define BUF_SIZE 320 /* 320 samples */
34 struct ast_filestream {
35 void *reserved[AST_RESERVED_POINTERS];
36 /* This is what a filestream means to us */
37 int fd; /* Descriptor */
38 struct ast_channel *owner;
39 struct ast_frame fr; /* Frame information */
40 char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
41 char empty; /* Empty character */
42 unsigned char buf[BUF_SIZE]; /* Output Buffer */
47 AST_MUTEX_DEFINE_STATIC(slinear_lock);
48 static int glistcnt = 0;
50 static char *name = "sln";
51 static char *desc = "Raw Signed Linear Audio support (SLN)";
52 static char *exts = "sln|raw";
54 static struct ast_filestream *slinear_open(int fd)
56 /* We don't have any header to read or anything really, but
57 if we did, it would go here. We also might want to check
58 and be sure it's a valid file. */
59 struct ast_filestream *tmp;
60 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
61 memset(tmp, 0, sizeof(struct ast_filestream));
62 if (ast_mutex_lock(&slinear_lock)) {
63 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
68 tmp->fr.data = tmp->buf;
69 tmp->fr.frametype = AST_FRAME_VOICE;
70 tmp->fr.subclass = AST_FORMAT_SLINEAR;
71 /* datalen will vary for each frame */
75 ast_mutex_unlock(&slinear_lock);
76 ast_update_use_count();
81 static struct ast_filestream *slinear_rewrite(int fd, char *comment)
83 /* We don't have any header to read or anything really, but
84 if we did, it would go here. We also might want to check
85 and be sure it's a valid file. */
86 struct ast_filestream *tmp;
87 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
88 memset(tmp, 0, sizeof(struct ast_filestream));
89 if (ast_mutex_lock(&slinear_lock)) {
90 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
96 ast_mutex_unlock(&slinear_lock);
97 ast_update_use_count();
99 ast_log(LOG_WARNING, "Out of memory\n");
103 static void slinear_close(struct ast_filestream *s)
105 if (ast_mutex_lock(&slinear_lock)) {
106 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
110 ast_mutex_unlock(&slinear_lock);
111 ast_update_use_count();
117 static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext)
121 /* Send a frame from the file to the appropriate channel */
123 s->fr.frametype = AST_FRAME_VOICE;
124 s->fr.subclass = AST_FORMAT_SLINEAR;
125 s->fr.offset = AST_FRIENDLY_OFFSET;
128 if ((res = read(s->fd, s->buf, BUF_SIZE)) < 1) {
130 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
133 s->fr.samples = res/2;
135 delay = s->fr.samples;
140 static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
143 if (f->frametype != AST_FRAME_VOICE) {
144 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
147 if (f->subclass != AST_FORMAT_SLINEAR) {
148 ast_log(LOG_WARNING, "Asked to write non-slinear frame (%d)!\n", f->subclass);
151 if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) {
152 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
158 static int slinear_seek(struct ast_filestream *fs, long sample_offset, int whence)
160 off_t offset=0,min,cur,max;
163 cur = lseek(fs->fd, 0, SEEK_CUR);
164 max = lseek(fs->fd, 0, SEEK_END);
165 if (whence == SEEK_SET)
166 offset = sample_offset;
167 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
168 offset = sample_offset + cur;
169 else if (whence == SEEK_END)
170 offset = max - sample_offset;
171 if (whence != SEEK_FORCECUR) {
172 offset = (offset > max)?max:offset;
174 // always protect against seeking past begining.
175 offset = (offset < min)?min:offset;
176 return lseek(fs->fd, offset, SEEK_SET);
179 static int slinear_trunc(struct ast_filestream *fs)
181 return ftruncate(fs->fd, lseek(fs->fd,0,SEEK_CUR));
184 static long slinear_tell(struct ast_filestream *fs)
187 offset = lseek(fs->fd, 0, SEEK_CUR);
191 static char *slinear_getcomment(struct ast_filestream *s)
198 return ast_format_register(name, exts, AST_FORMAT_SLINEAR,
214 return ast_format_unregister(name);
220 if (ast_mutex_lock(&slinear_lock)) {
221 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
225 ast_mutex_unlock(&slinear_lock);
237 return ASTERISK_GPL_KEY;