Merge FreeBSD locking fixes (bug #1411)
[asterisk/asterisk.git] / formats / format_wav.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Work with WAV in the proprietary Microsoft format.
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13  
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>
22 #include <stdlib.h>
23 #include <sys/time.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <pthread.h>
29 #ifdef __linux__
30 #include <endian.h>
31 #else
32 #include <machine/endian.h>
33 #endif
34
35 /* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
36
37 /* Portions of the conversion code are by guido@sienanet.it */
38
39 struct ast_filestream {
40         void *reserved[AST_RESERVED_POINTERS];
41         /* This is what a filestream means to us */
42         int fd; /* Descriptor */
43         int bytes;
44         int needsgain;
45         struct ast_frame fr;                            /* Frame information */
46         char waste[AST_FRIENDLY_OFFSET];        /* Buffer for sending frames, etc */
47         char empty;                                                     /* Empty character */
48         short buf[160]; 
49         int foffset;
50         int lasttimeout;
51         int maxlen;
52         struct timeval last;
53 };
54
55
56 AST_MUTEX_DEFINE_STATIC(wav_lock);
57 static int glistcnt = 0;
58
59 static char *name = "wav";
60 static char *desc = "Microsoft WAV format (8000hz Signed Linear)";
61 static char *exts = "wav";
62
63 #define BLOCKSIZE 160
64
65 #define GAIN 2          /* 2^GAIN is the multiple to increase the volume by */
66
67 #if __BYTE_ORDER == __LITTLE_ENDIAN
68 #define htoll(b) (b)
69 #define htols(b) (b)
70 #define ltohl(b) (b)
71 #define ltohs(b) (b)
72 #else
73 #if __BYTE_ORDER == __BIG_ENDIAN
74 #define htoll(b)  \
75           (((((b)      ) & 0xFF) << 24) | \
76                ((((b) >>  8) & 0xFF) << 16) | \
77                    ((((b) >> 16) & 0xFF) <<  8) | \
78                    ((((b) >> 24) & 0xFF)      ))
79 #define htols(b) \
80           (((((b)      ) & 0xFF) << 8) | \
81                    ((((b) >> 8) & 0xFF)      ))
82 #define ltohl(b) htoll(b)
83 #define ltohs(b) htols(b)
84 #else
85 #error "Endianess not defined"
86 #endif
87 #endif
88
89
90 static int check_header(int fd)
91 {
92         int type, size, formtype;
93         int fmt, hsize;
94         short format, chans, bysam, bisam;
95         int bysec;
96         int freq;
97         int data;
98         if (read(fd, &type, 4) != 4) {
99                 ast_log(LOG_WARNING, "Read failed (type)\n");
100                 return -1;
101         }
102         if (read(fd, &size, 4) != 4) {
103                 ast_log(LOG_WARNING, "Read failed (size)\n");
104                 return -1;
105         }
106         size = ltohl(size);
107         if (read(fd, &formtype, 4) != 4) {
108                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
109                 return -1;
110         }
111         if (memcmp(&type, "RIFF", 4)) {
112                 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
113                 return -1;
114         }
115         if (memcmp(&formtype, "WAVE", 4)) {
116                 ast_log(LOG_WARNING, "Does not contain WAVE\n");
117                 return -1;
118         }
119         if (read(fd, &fmt, 4) != 4) {
120                 ast_log(LOG_WARNING, "Read failed (fmt)\n");
121                 return -1;
122         }
123         if (memcmp(&fmt, "fmt ", 4)) {
124                 ast_log(LOG_WARNING, "Does not say fmt\n");
125                 return -1;
126         }
127         if (read(fd, &hsize, 4) != 4) {
128                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
129                 return -1;
130         }
131         if (ltohl(hsize) < 16) {
132                 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize));
133                 return -1;
134         }
135         if (read(fd, &format, 2) != 2) {
136                 ast_log(LOG_WARNING, "Read failed (format)\n");
137                 return -1;
138         }
139         if (ltohs(format) != 1) {
140                 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format));
141                 return -1;
142         }
143         if (read(fd, &chans, 2) != 2) {
144                 ast_log(LOG_WARNING, "Read failed (format)\n");
145                 return -1;
146         }
147         if (ltohs(chans) != 1) {
148                 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
149                 return -1;
150         }
151         if (read(fd, &freq, 4) != 4) {
152                 ast_log(LOG_WARNING, "Read failed (freq)\n");
153                 return -1;
154         }
155         if (ltohl(freq) != 8000) {
156                 ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq));
157                 return -1;
158         }
159         /* Ignore the byte frequency */
160         if (read(fd, &bysec, 4) != 4) {
161                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
162                 return -1;
163         }
164         /* Check bytes per sample */
165         if (read(fd, &bysam, 2) != 2) {
166                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
167                 return -1;
168         }
169         if (ltohs(bysam) != 2) {
170                 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
171                 return -1;
172         }
173         if (read(fd, &bisam, 2) != 2) {
174                 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
175                 return -1;
176         }
177         // Skip any additional header
178         if ( lseek(fd,ltohl(hsize)-16,SEEK_CUR) == -1 ) {
179                 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 );
180                 return -1;
181         }
182         // Skip any facts and get the first data block
183         for(;;)
184         { 
185             char buf[4];
186             
187             /* Begin data chunk */
188             if (read(fd, &buf, 4) != 4) {
189                 ast_log(LOG_WARNING, "Read failed (data)\n");
190                 return -1;
191             }
192             /* Data has the actual length of data in it */
193             if (read(fd, &data, 4) != 4) {
194                 ast_log(LOG_WARNING, "Read failed (data)\n");
195                 return -1;
196             }
197             data = ltohl(data);
198             if( memcmp(buf, "data", 4) == 0 ) break;
199             if( memcmp(buf, "fact", 4) != 0 ) {
200                 ast_log(LOG_WARNING, "Unknown block - not fact or data\n");
201                 return -1;
202             }
203             if ( lseek(fd,data,SEEK_CUR) == -1 ) {
204                 ast_log(LOG_WARNING, "Failed to skip fact block: %d\n", data );
205                 return -1;
206             }
207         }
208 #if 0
209         curpos = lseek(fd, 0, SEEK_CUR);
210         truelength = lseek(fd, 0, SEEK_END);
211         lseek(fd, curpos, SEEK_SET);
212         truelength -= curpos;
213 #endif  
214         return data;
215 }
216
217 static int update_header(int fd)
218 {
219         off_t cur,end;
220         int datalen,filelen,bytes;
221         
222         
223         cur = lseek(fd, 0, SEEK_CUR);
224         end = lseek(fd, 0, SEEK_END);
225         /* data starts 44 bytes in */
226         bytes = end - 44;
227         datalen = htoll(bytes);
228         /* chunk size is bytes of data plus 36 bytes of header */
229         filelen = htoll(36 + bytes);
230         
231         if (cur < 0) {
232                 ast_log(LOG_WARNING, "Unable to find our position\n");
233                 return -1;
234         }
235         if (lseek(fd, 4, SEEK_SET) != 4) {
236                 ast_log(LOG_WARNING, "Unable to set our position\n");
237                 return -1;
238         }
239         if (write(fd, &filelen, 4) != 4) {
240                 ast_log(LOG_WARNING, "Unable to set write file size\n");
241                 return -1;
242         }
243         if (lseek(fd, 40, SEEK_SET) != 40) {
244                 ast_log(LOG_WARNING, "Unable to set our position\n");
245                 return -1;
246         }
247         if (write(fd, &datalen, 4) != 4) {
248                 ast_log(LOG_WARNING, "Unable to set write datalen\n");
249                 return -1;
250         }
251         if (lseek(fd, cur, SEEK_SET) != cur) {
252                 ast_log(LOG_WARNING, "Unable to return to position\n");
253                 return -1;
254         }
255         return 0;
256 }
257
258 static int write_header(int fd)
259 {
260         unsigned int hz=htoll(8000);
261         unsigned int bhz = htoll(16000);
262         unsigned int hs = htoll(16);
263         unsigned short fmt = htols(1);
264         unsigned short chans = htols(1);
265         unsigned short bysam = htols(2);
266         unsigned short bisam = htols(16);
267         unsigned int size = htoll(0);
268         /* Write a wav header, ignoring sizes which will be filled in later */
269         lseek(fd,0,SEEK_SET);
270         if (write(fd, "RIFF", 4) != 4) {
271                 ast_log(LOG_WARNING, "Unable to write header\n");
272                 return -1;
273         }
274         if (write(fd, &size, 4) != 4) {
275                 ast_log(LOG_WARNING, "Unable to write header\n");
276                 return -1;
277         }
278         if (write(fd, "WAVEfmt ", 8) != 8) {
279                 ast_log(LOG_WARNING, "Unable to write header\n");
280                 return -1;
281         }
282         if (write(fd, &hs, 4) != 4) {
283                 ast_log(LOG_WARNING, "Unable to write header\n");
284                 return -1;
285         }
286         if (write(fd, &fmt, 2) != 2) {
287                 ast_log(LOG_WARNING, "Unable to write header\n");
288                 return -1;
289         }
290         if (write(fd, &chans, 2) != 2) {
291                 ast_log(LOG_WARNING, "Unable to write header\n");
292                 return -1;
293         }
294         if (write(fd, &hz, 4) != 4) {
295                 ast_log(LOG_WARNING, "Unable to write header\n");
296                 return -1;
297         }
298         if (write(fd, &bhz, 4) != 4) {
299                 ast_log(LOG_WARNING, "Unable to write header\n");
300                 return -1;
301         }
302         if (write(fd, &bysam, 2) != 2) {
303                 ast_log(LOG_WARNING, "Unable to write header\n");
304                 return -1;
305         }
306         if (write(fd, &bisam, 2) != 2) {
307                 ast_log(LOG_WARNING, "Unable to write header\n");
308                 return -1;
309         }
310         if (write(fd, "data", 4) != 4) {
311                 ast_log(LOG_WARNING, "Unable to write header\n");
312                 return -1;
313         }
314         if (write(fd, &size, 4) != 4) {
315                 ast_log(LOG_WARNING, "Unable to write header\n");
316                 return -1;
317         }
318         return 0;
319 }
320
321 static struct ast_filestream *wav_open(int fd)
322 {
323         /* We don't have any header to read or anything really, but
324            if we did, it would go here.  We also might want to check
325            and be sure it's a valid file.  */
326         struct ast_filestream *tmp;
327         if ((tmp = malloc(sizeof(struct ast_filestream)))) {
328                 memset(tmp, 0, sizeof(struct ast_filestream));
329                 if ((tmp->maxlen = check_header(fd)) < 0) {
330                         free(tmp);
331                         return NULL;
332                 }
333                 if (ast_mutex_lock(&wav_lock)) {
334                         ast_log(LOG_WARNING, "Unable to lock wav list\n");
335                         free(tmp);
336                         return NULL;
337                 }
338                 tmp->fd = fd;
339                 tmp->needsgain = 1;
340                 tmp->fr.data = tmp->buf;
341                 tmp->fr.frametype = AST_FRAME_VOICE;
342                 tmp->fr.subclass = AST_FORMAT_SLINEAR;
343                 /* datalen will vary for each frame */
344                 tmp->fr.src = name;
345                 tmp->fr.mallocd = 0;
346                 tmp->bytes = 0;
347                 glistcnt++;
348                 ast_mutex_unlock(&wav_lock);
349                 ast_update_use_count();
350         }
351         return tmp;
352 }
353
354 static struct ast_filestream *wav_rewrite(int fd, char *comment)
355 {
356         /* We don't have any header to read or anything really, but
357            if we did, it would go here.  We also might want to check
358            and be sure it's a valid file.  */
359         struct ast_filestream *tmp;
360         if ((tmp = malloc(sizeof(struct ast_filestream)))) {
361                 memset(tmp, 0, sizeof(struct ast_filestream));
362                 if (write_header(fd)) {
363                         free(tmp);
364                         return NULL;
365                 }
366                 if (ast_mutex_lock(&wav_lock)) {
367                         ast_log(LOG_WARNING, "Unable to lock wav list\n");
368                         free(tmp);
369                         return NULL;
370                 }
371                 tmp->fd = fd;
372                 glistcnt++;
373                 ast_mutex_unlock(&wav_lock);
374                 ast_update_use_count();
375         } else
376                 ast_log(LOG_WARNING, "Out of memory\n");
377         return tmp;
378 }
379
380 static void wav_close(struct ast_filestream *s)
381 {
382         char zero = 0;
383         if (ast_mutex_lock(&wav_lock)) {
384                 ast_log(LOG_WARNING, "Unable to lock wav list\n");
385                 return;
386         }
387         glistcnt--;
388         ast_mutex_unlock(&wav_lock);
389         ast_update_use_count();
390         /* Pad to even length */
391         if (s->bytes & 0x1)
392                 write(s->fd, &zero, 1);
393         close(s->fd);
394         free(s);
395         s = NULL;
396 }
397
398 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
399 {
400         int res;
401         int delay;
402         int x;
403         short tmp[sizeof(s->buf) / 2];
404         int bytes = sizeof(tmp);
405         off_t here;
406         /* Send a frame from the file to the appropriate channel */
407         here = lseek(s->fd, 0, SEEK_CUR);
408         if ((s->maxlen - here) < bytes)
409                 bytes = s->maxlen - here;
410         if (bytes < 0)
411                 bytes = 0;
412 /*      ast_log(LOG_DEBUG, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
413         
414         if ( (res = read(s->fd, tmp, bytes)) <= 0 ) {
415                 if (res) {
416                         ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
417                 }
418                 return NULL;
419         }
420
421 #if __BYTE_ORDER == __BIG_ENDIAN
422         for( x = 0; x < sizeof(tmp)/2; x++) tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
423 #endif
424
425         if (s->needsgain) {
426                 for (x=0;x<sizeof(tmp)/2;x++)
427                         if (tmp[x] & ((1 << GAIN) - 1)) {
428                                 /* If it has data down low, then it's not something we've artificially increased gain
429                                    on, so we don't need to gain adjust it */
430                                 s->needsgain = 0;
431                         }
432         }
433         if (s->needsgain) {
434                 for (x=0;x<sizeof(tmp)/2;x++) {
435                         s->buf[x] = tmp[x] >> GAIN;
436                 }
437         } else {
438                 memcpy(s->buf, tmp, sizeof(s->buf));
439         }
440                         
441         delay = res / 2;
442         s->fr.frametype = AST_FRAME_VOICE;
443         s->fr.subclass = AST_FORMAT_SLINEAR;
444         s->fr.offset = AST_FRIENDLY_OFFSET;
445         s->fr.datalen = res;
446         s->fr.data = s->buf;
447         s->fr.mallocd = 0;
448         s->fr.samples = delay;
449         *whennext = delay;
450         return &s->fr;
451 }
452
453 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
454 {
455         int res = 0;
456         int x;
457         short tmp[8000], *tmpi;
458         float tmpf;
459         if (f->frametype != AST_FRAME_VOICE) {
460                 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
461                 return -1;
462         }
463         if (f->subclass != AST_FORMAT_SLINEAR) {
464                 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass);
465                 return -1;
466         }
467         if (f->datalen > sizeof(tmp)) {
468                 ast_log(LOG_WARNING, "Data length is too long\n");
469                 return -1;
470         }
471         if (!f->datalen)
472                 return -1;
473
474 #if 0
475         printf("Data Length: %d\n", f->datalen);
476 #endif  
477
478         if (fs->buf) {
479                 tmpi = f->data;
480                 /* Volume adjust here to accomodate */
481                 for (x=0;x<f->datalen/2;x++) {
482                         tmpf = ((float)tmpi[x]) * ((float)(1 << GAIN));
483                         if (tmpf > 32767.0)
484                                 tmpf = 32767.0;
485                         if (tmpf < -32768.0)
486                                 tmpf = -32768.0;
487                         tmp[x] = tmpf;
488                         tmp[x] &= ~((1 << GAIN) - 1);
489
490 #if __BYTE_ORDER == __BIG_ENDIAN
491                         tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
492 #endif
493
494                 }
495                 if ((write (fs->fd, tmp, f->datalen) != f->datalen) ) {
496                         ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
497                         return -1;
498                 }
499         } else {
500                 ast_log(LOG_WARNING, "Cannot write data to file.\n");
501                 return -1;
502         }
503         
504         fs->bytes += f->datalen;
505         update_header(fs->fd);
506                 
507         return 0;
508
509 }
510
511 static int wav_seek(struct ast_filestream *fs, long sample_offset, int whence)
512 {
513         off_t min,max,cur;
514         long offset=0,samples;
515         
516         samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
517         min = 44; /* wav header is 44 bytes */
518         cur = lseek(fs->fd, 0, SEEK_CUR);
519         max = lseek(fs->fd, 0, SEEK_END);
520         if (whence == SEEK_SET)
521                 offset = samples + min;
522         else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
523                 offset = samples + cur;
524         else if (whence == SEEK_END)
525                 offset = max - samples;
526         if (whence != SEEK_FORCECUR) {
527                 offset = (offset > max)?max:offset;
528         }
529         // always protect the header space.
530         offset = (offset < min)?min:offset;
531         return lseek(fs->fd,offset,SEEK_SET);
532 }
533
534 static int wav_trunc(struct ast_filestream *fs)
535 {
536         if(ftruncate(fs->fd, lseek(fs->fd,0,SEEK_CUR)))
537                 return -1;
538         return update_header(fs->fd);
539 }
540
541 static long wav_tell(struct ast_filestream *fs)
542 {
543         off_t offset;
544         offset = lseek(fs->fd, 0, SEEK_CUR);
545         /* subtract header size to get samples, then divide by 2 for 16 bit samples */
546         return (offset - 44)/2;
547 }
548
549 static char *wav_getcomment(struct ast_filestream *s)
550 {
551         return NULL;
552 }
553
554 int load_module()
555 {
556         return ast_format_register(name, exts, AST_FORMAT_SLINEAR,
557                                                                 wav_open,
558                                                                 wav_rewrite,
559                                                                 wav_write,
560                                                                 wav_seek,
561                                                                 wav_trunc,
562                                                                 wav_tell,
563                                                                 wav_read,
564                                                                 wav_close,
565                                                                 wav_getcomment);
566                                                                 
567                                                                 
568 }
569
570 int unload_module()
571 {
572         return ast_format_unregister(name);
573 }       
574
575 int usecount()
576 {
577         int res;
578         if (ast_mutex_lock(&wav_lock)) {
579                 ast_log(LOG_WARNING, "Unable to lock wav list\n");
580                 return -1;
581         }
582         res = glistcnt;
583         ast_mutex_unlock(&wav_lock);
584         return res;
585 }
586
587 char *description()
588 {
589         return desc;
590 }
591
592
593 char *key()
594 {
595         return ASTERISK_GPL_KEY;
596 }