use double-quotes instead of angle-brackets for non-system include files (bug #4058)
[asterisk/asterisk.git] / formats / format_sln.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * RAW SLINEAR Format
5  * Anthony Minessale (anthmct@yahoo.com)
6  * Derived from format_pcm.c in the asterisk distro
7  *
8  * This program is free software, distributed under the terms of
9  * the GNU General Public License
10  */
11  
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 "asterisk/endian.h"
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <stdlib.h>
22 #include <sys/time.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <string.h>
27
28 #define BUF_SIZE 320            /* 320 samples */
29
30 struct ast_filestream {
31         void *reserved[AST_RESERVED_POINTERS];
32         /* This is what a filestream means to us */
33         int fd; /* Descriptor */
34         struct ast_channel *owner;
35         struct ast_frame fr;                            /* Frame information */
36         char waste[AST_FRIENDLY_OFFSET];        /* Buffer for sending frames, etc */
37         char empty;                                                     /* Empty character */
38         unsigned char buf[BUF_SIZE];                            /* Output Buffer */
39         struct timeval last;
40 };
41
42
43 AST_MUTEX_DEFINE_STATIC(slinear_lock);
44 static int glistcnt = 0;
45
46 static char *name = "sln";
47 static char *desc = "Raw Signed Linear Audio support (SLN)";
48 static char *exts = "sln|raw";
49
50 static struct ast_filestream *slinear_open(int fd)
51 {
52         /* We don't have any header to read or anything really, but
53            if we did, it would go here.  We also might want to check
54            and be sure it's a valid file.  */
55         struct ast_filestream *tmp;
56         if ((tmp = malloc(sizeof(struct ast_filestream)))) {
57                 memset(tmp, 0, sizeof(struct ast_filestream));
58                 if (ast_mutex_lock(&slinear_lock)) {
59                         ast_log(LOG_WARNING, "Unable to lock slinear list\n");
60                         free(tmp);
61                         return NULL;
62                 }
63                 tmp->fd = fd;
64                 tmp->fr.data = tmp->buf;
65                 tmp->fr.frametype = AST_FRAME_VOICE;
66                 tmp->fr.subclass = AST_FORMAT_SLINEAR;
67                 /* datalen will vary for each frame */
68                 tmp->fr.src = name;
69                 tmp->fr.mallocd = 0;
70                 glistcnt++;
71                 ast_mutex_unlock(&slinear_lock);
72                 ast_update_use_count();
73         }
74         return tmp;
75 }
76
77 static struct ast_filestream *slinear_rewrite(int fd, const char *comment)
78 {
79         /* We don't have any header to read or anything really, but
80            if we did, it would go here.  We also might want to check
81            and be sure it's a valid file.  */
82         struct ast_filestream *tmp;
83         if ((tmp = malloc(sizeof(struct ast_filestream)))) {
84                 memset(tmp, 0, sizeof(struct ast_filestream));
85                 if (ast_mutex_lock(&slinear_lock)) {
86                         ast_log(LOG_WARNING, "Unable to lock slinear list\n");
87                         free(tmp);
88                         return NULL;
89                 }
90                 tmp->fd = fd;
91                 glistcnt++;
92                 ast_mutex_unlock(&slinear_lock);
93                 ast_update_use_count();
94         } else
95                 ast_log(LOG_WARNING, "Out of memory\n");
96         return tmp;
97 }
98
99 static void slinear_close(struct ast_filestream *s)
100 {
101         if (ast_mutex_lock(&slinear_lock)) {
102                 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
103                 return;
104         }
105         glistcnt--;
106         ast_mutex_unlock(&slinear_lock);
107         ast_update_use_count();
108         close(s->fd);
109         free(s);
110         s = NULL;
111 }
112
113 static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext)
114 {
115         int res;
116         int delay;
117         /* Send a frame from the file to the appropriate channel */
118
119         s->fr.frametype = AST_FRAME_VOICE;
120         s->fr.subclass = AST_FORMAT_SLINEAR;
121         s->fr.offset = AST_FRIENDLY_OFFSET;
122         s->fr.mallocd = 0;
123         s->fr.data = s->buf;
124         if ((res = read(s->fd, s->buf, BUF_SIZE)) < 1) {
125                 if (res)
126                         ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
127                 return NULL;
128         }
129         s->fr.samples = res/2;
130         s->fr.datalen = res;
131         delay = s->fr.samples;
132         *whennext = delay;
133         return &s->fr;
134 }
135
136 static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
137 {
138         int res;
139         if (f->frametype != AST_FRAME_VOICE) {
140                 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
141                 return -1;
142         }
143         if (f->subclass != AST_FORMAT_SLINEAR) {
144                 ast_log(LOG_WARNING, "Asked to write non-slinear frame (%d)!\n", f->subclass);
145                 return -1;
146         }
147         if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) {
148                         ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
149                         return -1;
150         }
151         return 0;
152 }
153
154 static int slinear_seek(struct ast_filestream *fs, long sample_offset, int whence)
155 {
156         off_t offset=0,min,cur,max;
157
158         min = 0;
159         cur = lseek(fs->fd, 0, SEEK_CUR);
160         max = lseek(fs->fd, 0, SEEK_END);
161         if (whence == SEEK_SET)
162                 offset = sample_offset;
163         else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
164                 offset = sample_offset + cur;
165         else if (whence == SEEK_END)
166                 offset = max - sample_offset;
167         if (whence != SEEK_FORCECUR) {
168                 offset = (offset > max)?max:offset;
169         }
170         /* always protect against seeking past begining. */
171         offset = (offset < min)?min:offset;
172         return lseek(fs->fd, offset, SEEK_SET);
173 }
174
175 static int slinear_trunc(struct ast_filestream *fs)
176 {
177         return ftruncate(fs->fd, lseek(fs->fd,0,SEEK_CUR));
178 }
179
180 static long slinear_tell(struct ast_filestream *fs)
181 {
182         off_t offset;
183         offset = lseek(fs->fd, 0, SEEK_CUR);
184         return offset;
185 }
186
187 static char *slinear_getcomment(struct ast_filestream *s)
188 {
189         return NULL;
190 }
191
192 int load_module()
193 {
194         return ast_format_register(name, exts, AST_FORMAT_SLINEAR,
195                                                                 slinear_open,
196                                                                 slinear_rewrite,
197                                                                 slinear_write,
198                                                                 slinear_seek,
199                                                                 slinear_trunc,
200                                                                 slinear_tell,
201                                                                 slinear_read,
202                                                                 slinear_close,
203                                                                 slinear_getcomment);
204                                                                 
205                                                                 
206 }
207
208 int unload_module()
209 {
210         return ast_format_unregister(name);
211 }       
212
213 int usecount()
214 {
215         int res;
216         if (ast_mutex_lock(&slinear_lock)) {
217                 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
218                 return -1;
219         }
220         res = glistcnt;
221         ast_mutex_unlock(&slinear_lock);
222         return res;
223 }
224
225 char *description()
226 {
227         return desc;
228 }
229
230
231 char *key()
232 {
233         return ASTERISK_GPL_KEY;
234 }