2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Anthony Minessale
5 * Anthony Minessale (anthmct@yahoo.com)
7 * See http://www.asterisk.org for more information about
8 * the Asterisk project. Please do not directly contact
9 * any of the maintainers of this project for assistance;
10 * the project provides a web site, mailing lists and IRC
11 * channels for your use.
13 * This program is free software, distributed under the terms of
14 * the GNU General Public License Version 2. See the LICENSE file
15 * at the top of the source tree.
20 * \brief RAW SLINEAR Format
21 * \arg File name extensions: sln, raw
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
38 #include "asterisk/lock.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/file.h"
41 #include "asterisk/logger.h"
42 #include "asterisk/sched.h"
43 #include "asterisk/module.h"
44 #include "asterisk/endian.h"
46 #define BUF_SIZE 320 /* 320 samples */
48 struct ast_filestream {
49 void *reserved[AST_RESERVED_POINTERS];
50 /* This is what a filestream means to us */
51 FILE *f; /* Descriptor */
52 struct ast_channel *owner;
53 struct ast_frame fr; /* Frame information */
54 char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
55 char empty; /* Empty character */
56 unsigned char buf[BUF_SIZE]; /* Output Buffer */
61 AST_MUTEX_DEFINE_STATIC(slinear_lock);
62 static int glistcnt = 0;
64 static char *name = "sln";
65 static char *desc = "Raw Signed Linear Audio support (SLN)";
66 static char *exts = "sln|raw";
68 static struct ast_filestream *slinear_open(FILE *f)
70 /* We don't have any header to read or anything really, but
71 if we did, it would go here. We also might want to check
72 and be sure it's a valid file. */
73 struct ast_filestream *tmp;
74 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
75 memset(tmp, 0, sizeof(struct ast_filestream));
76 if (ast_mutex_lock(&slinear_lock)) {
77 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
82 tmp->fr.data = tmp->buf;
83 tmp->fr.frametype = AST_FRAME_VOICE;
84 tmp->fr.subclass = AST_FORMAT_SLINEAR;
85 /* datalen will vary for each frame */
89 ast_mutex_unlock(&slinear_lock);
90 ast_update_use_count();
95 static struct ast_filestream *slinear_rewrite(FILE *f, const char *comment)
97 /* We don't have any header to read or anything really, but
98 if we did, it would go here. We also might want to check
99 and be sure it's a valid file. */
100 struct ast_filestream *tmp;
101 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
102 memset(tmp, 0, sizeof(struct ast_filestream));
103 if (ast_mutex_lock(&slinear_lock)) {
104 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
110 ast_mutex_unlock(&slinear_lock);
111 ast_update_use_count();
113 ast_log(LOG_WARNING, "Out of memory\n");
117 static void slinear_close(struct ast_filestream *s)
119 if (ast_mutex_lock(&slinear_lock)) {
120 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
124 ast_mutex_unlock(&slinear_lock);
125 ast_update_use_count();
131 static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext)
135 /* Send a frame from the file to the appropriate channel */
137 s->fr.frametype = AST_FRAME_VOICE;
138 s->fr.subclass = AST_FORMAT_SLINEAR;
139 s->fr.offset = AST_FRIENDLY_OFFSET;
142 if ((res = fread(s->buf, 1, BUF_SIZE, s->f)) < 1) {
144 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
147 s->fr.samples = res/2;
149 delay = s->fr.samples;
154 static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
157 if (f->frametype != AST_FRAME_VOICE) {
158 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
161 if (f->subclass != AST_FORMAT_SLINEAR) {
162 ast_log(LOG_WARNING, "Asked to write non-slinear frame (%d)!\n", f->subclass);
165 if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
166 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
172 static int slinear_seek(struct ast_filestream *fs, long sample_offset, int whence)
174 off_t offset=0,min,cur,max;
179 fseek(fs->f, 0, SEEK_END);
181 if (whence == SEEK_SET)
182 offset = sample_offset;
183 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
184 offset = sample_offset + cur;
185 else if (whence == SEEK_END)
186 offset = max - sample_offset;
187 if (whence != SEEK_FORCECUR) {
188 offset = (offset > max)?max:offset;
190 /* always protect against seeking past begining. */
191 offset = (offset < min)?min:offset;
192 return fseek(fs->f, offset, SEEK_SET);
195 static int slinear_trunc(struct ast_filestream *fs)
197 return ftruncate(fileno(fs->f), ftell(fs->f));
200 static long slinear_tell(struct ast_filestream *fs)
203 offset = ftell(fs->f);
207 static char *slinear_getcomment(struct ast_filestream *s)
214 return ast_format_register(name, exts, AST_FORMAT_SLINEAR,
230 return ast_format_unregister(name);
246 return ASTERISK_GPL_KEY;