Merge "loader: Refactor resource_name_match."
[asterisk/asterisk.git] / formats / format_wav.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Work with WAV in the proprietary Microsoft format.
22  * Microsoft WAV format (8000hz Signed Linear)
23  * \arg File name extension: wav (lower case)
24  * \ingroup formats
25  */
26  
27 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 #include "asterisk/mod_format.h"
34 #include "asterisk/module.h"
35 #include "asterisk/endian.h"
36 #include "asterisk/format_cache.h"
37 #include "asterisk/format.h"
38 #include "asterisk/codec.h"
39
40 /* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
41
42 /* Portions of the conversion code are by guido@sienanet.it */
43
44 #define WAV_BUF_SIZE    320
45
46 #define WAV_HEADER_SIZE 44
47
48 struct wav_desc {       /* format-specific parameters */
49         int hz;
50         int bytes;
51         int lasttimeout;
52         int maxlen;
53         struct timeval last;
54 };
55
56 #define BLOCKSIZE 160
57
58 #if __BYTE_ORDER == __LITTLE_ENDIAN
59 #define htoll(b) (b)
60 #define htols(b) (b)
61 #define ltohl(b) (b)
62 #define ltohs(b) (b)
63 #else
64 #if __BYTE_ORDER == __BIG_ENDIAN
65 #define htoll(b) \
66         (((((b)      ) & 0xFF) << 24) | \
67         ((( (b) >>  8) & 0xFF) << 16) | \
68         ((( (b) >> 16) & 0xFF) <<  8) | \
69         ((( (b) >> 24) & 0xFF)      ))
70 #define htols(b) \
71         (((((b)      ) & 0xFF) <<  8) | \
72         ((( (b) >>  8) & 0xFF)      ))
73 #define ltohl(b) htoll(b)
74 #define ltohs(b) htols(b)
75 #else
76 #error "Endianess not defined"
77 #endif
78 #endif
79
80
81 static int check_header_fmt(FILE *f, int hsize, int hz)
82 {
83         unsigned short format, chans, bysam, bisam;
84         unsigned int freq, bysec;
85         if (hsize < 16) {
86                 ast_log(LOG_WARNING, "Unexpected header size %d\n", hsize);
87                 return -1;
88         }
89         if (fread(&format, 1, 2, f) != 2) {
90                 ast_log(LOG_WARNING, "Read failed (format)\n");
91                 return -1;
92         }
93         if (ltohs(format) != 1) {
94                 ast_log(LOG_WARNING, "Not a supported wav file format (%d). Only PCM encoded, 16 bit, mono, 8kHz/16kHz files are supported with a lowercase '.wav' extension.\n", ltohs(format));
95                 return -1;
96         }
97         if (fread(&chans, 1, 2, f) != 2) {
98                 ast_log(LOG_WARNING, "Read failed (format)\n");
99                 return -1;
100         }
101         if (ltohs(chans) != 1) {
102                 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
103                 return -1;
104         }
105         if (fread(&freq, 1, 4, f) != 4) {
106                 ast_log(LOG_WARNING, "Read failed (freq)\n");
107                 return -1;
108         }
109         freq = ltohl(freq);
110         if ((freq != 8000 && freq != 16000) || freq != hz) {
111                 ast_log(LOG_WARNING, "Unexpected frequency mismatch %d (expecting %d)\n", freq, hz);
112                 return -1;
113         }
114         /* Ignore the byte frequency */
115         if (fread(&bysec, 1, 4, f) != 4) {
116                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
117                 return -1;
118         }
119         /* Check bytes per sample */
120         if (fread(&bysam, 1, 2, f) != 2) {
121                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
122                 return -1;
123         }
124         if (ltohs(bysam) != 2) {
125                 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
126                 return -1;
127         }
128         if (fread(&bisam, 1, 2, f) != 2) {
129                 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
130                 return -1;
131         }
132         /* Skip any additional header */
133         if (fseek(f,hsize-16,SEEK_CUR) == -1 ) {
134                 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", hsize-16 );
135                 return -1;
136         }
137         return 0;
138 }
139
140 static int check_header(FILE *f, int hz)
141 {
142         int type, size, formtype;
143         int data;
144         if (fread(&type, 1, 4, f) != 4) {
145                 ast_log(LOG_WARNING, "Read failed (type)\n");
146                 return -1;
147         }
148         if (fread(&size, 1, 4, f) != 4) {
149                 ast_log(LOG_WARNING, "Read failed (size)\n");
150                 return -1;
151         }
152 #if __BYTE_ORDER == __BIG_ENDIAN
153         size = ltohl(size);
154 #endif
155         if (fread(&formtype, 1, 4, f) != 4) {
156                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
157                 return -1;
158         }
159         if (memcmp(&type, "RIFF", 4)) {
160                 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
161                 return -1;
162         }
163         if (memcmp(&formtype, "WAVE", 4)) {
164                 ast_log(LOG_WARNING, "Does not contain WAVE\n");
165                 return -1;
166         }
167         /* Skip any facts and get the first data block */
168         for(;;)
169         { 
170                 char buf[4];
171                 
172                 /* Begin data chunk */
173                 if (fread(&buf, 1, 4, f) != 4) {
174                         ast_log(LOG_WARNING, "Read failed (block header format)\n");
175                         return -1;
176                 }
177                 /* Data has the actual length of data in it */
178                 if (fread(&data, 1, 4, f) != 4) {
179                         ast_log(LOG_WARNING, "Read failed (block '%.4s' header length)\n", buf);
180                         return -1;
181                 }
182 #if __BYTE_ORDER == __BIG_ENDIAN
183                 data = ltohl(data);
184 #endif
185                 if (memcmp(&buf, "fmt ", 4) == 0) {
186                         if (check_header_fmt(f, data, hz))
187                                 return -1;
188                         continue;
189                 }
190                 if(memcmp(buf, "data", 4) == 0 ) 
191                         break;
192                 ast_log(LOG_DEBUG, "Skipping unknown block '%.4s'\n", buf);
193                 if (fseek(f,data,SEEK_CUR) == -1 ) {
194                         ast_log(LOG_WARNING, "Failed to skip '%.4s' block: %d\n", buf, data);
195                         return -1;
196                 }
197         }
198 #if 0
199         curpos = lseek(fd, 0, SEEK_CUR);
200         truelength = lseek(fd, 0, SEEK_END);
201         lseek(fd, curpos, SEEK_SET);
202         truelength -= curpos;
203 #endif  
204         return data;
205 }
206
207 static int update_header(FILE *f)
208 {
209         off_t cur,end;
210         int datalen,filelen,bytes;
211         
212         cur = ftello(f);
213         fseek(f, 0, SEEK_END);
214         end = ftello(f);
215         /* data starts 44 bytes in */
216         bytes = end - 44;
217         datalen = htoll(bytes);
218         /* chunk size is bytes of data plus 36 bytes of header */
219         filelen = htoll(36 + bytes);
220         
221         if (cur < 0) {
222                 ast_log(LOG_WARNING, "Unable to find our position\n");
223                 return -1;
224         }
225         if (fseek(f, 4, SEEK_SET)) {
226                 ast_log(LOG_WARNING, "Unable to set our position\n");
227                 return -1;
228         }
229         if (fwrite(&filelen, 1, 4, f) != 4) {
230                 ast_log(LOG_WARNING, "Unable to set write file size\n");
231                 return -1;
232         }
233         if (fseek(f, 40, SEEK_SET)) {
234                 ast_log(LOG_WARNING, "Unable to set our position\n");
235                 return -1;
236         }
237         if (fwrite(&datalen, 1, 4, f) != 4) {
238                 ast_log(LOG_WARNING, "Unable to set write datalen\n");
239                 return -1;
240         }
241         if (fseeko(f, cur, SEEK_SET)) {
242                 ast_log(LOG_WARNING, "Unable to return to position\n");
243                 return -1;
244         }
245         return 0;
246 }
247
248 static int write_header(FILE *f, int writehz)
249 {
250         unsigned int hz;
251         unsigned int bhz;
252         unsigned int hs = htoll(16);
253         unsigned short fmt = htols(1);
254         unsigned short chans = htols(1);
255         unsigned short bysam = htols(2);
256         unsigned short bisam = htols(16);
257         unsigned int size = htoll(0);
258
259         if (writehz == 16000) {
260                 hz = htoll(16000);
261                 bhz = htoll(32000);
262         } else {
263                 hz = htoll(8000);
264                 bhz = htoll(16000);
265         }
266         /* Write a wav header, ignoring sizes which will be filled in later */
267         fseek(f,0,SEEK_SET);
268         if (fwrite("RIFF", 1, 4, f) != 4) {
269                 ast_log(LOG_WARNING, "Unable to write header\n");
270                 return -1;
271         }
272         if (fwrite(&size, 1, 4, f) != 4) {
273                 ast_log(LOG_WARNING, "Unable to write header\n");
274                 return -1;
275         }
276         if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
277                 ast_log(LOG_WARNING, "Unable to write header\n");
278                 return -1;
279         }
280         if (fwrite(&hs, 1, 4, f) != 4) {
281                 ast_log(LOG_WARNING, "Unable to write header\n");
282                 return -1;
283         }
284         if (fwrite(&fmt, 1, 2, f) != 2) {
285                 ast_log(LOG_WARNING, "Unable to write header\n");
286                 return -1;
287         }
288         if (fwrite(&chans, 1, 2, f) != 2) {
289                 ast_log(LOG_WARNING, "Unable to write header\n");
290                 return -1;
291         }
292         if (fwrite(&hz, 1, 4, f) != 4) {
293                 ast_log(LOG_WARNING, "Unable to write header\n");
294                 return -1;
295         }
296         if (fwrite(&bhz, 1, 4, f) != 4) {
297                 ast_log(LOG_WARNING, "Unable to write header\n");
298                 return -1;
299         }
300         if (fwrite(&bysam, 1, 2, f) != 2) {
301                 ast_log(LOG_WARNING, "Unable to write header\n");
302                 return -1;
303         }
304         if (fwrite(&bisam, 1, 2, f) != 2) {
305                 ast_log(LOG_WARNING, "Unable to write header\n");
306                 return -1;
307         }
308         if (fwrite("data", 1, 4, f) != 4) {
309                 ast_log(LOG_WARNING, "Unable to write header\n");
310                 return -1;
311         }
312         if (fwrite(&size, 1, 4, f) != 4) {
313                 ast_log(LOG_WARNING, "Unable to write header\n");
314                 return -1;
315         }
316         return 0;
317 }
318
319 static int wav_open(struct ast_filestream *s)
320 {
321         /* We don't have any header to read or anything really, but
322            if we did, it would go here.  We also might want to check
323            and be sure it's a valid file.  */
324         struct wav_desc *tmp = s->_private;
325         unsigned int sample_rate = ast_format_get_sample_rate(s->fmt->format);
326
327         tmp->maxlen = check_header(s->f, sample_rate);
328         if (tmp->maxlen < 0) {
329                 return -1;
330         }
331
332         tmp->hz = sample_rate;
333         return 0;
334 }
335
336 static int wav_rewrite(struct ast_filestream *s, const char *comment)
337 {
338         /* We don't have any header to read or anything really, but
339            if we did, it would go here.  We also might want to check
340            and be sure it's a valid file.  */
341
342         struct wav_desc *tmp = (struct wav_desc *)s->_private;
343         tmp->hz = ast_format_get_sample_rate(s->fmt->format);
344         if (write_header(s->f,tmp->hz))
345                 return -1;
346         return 0;
347 }
348
349 static void wav_close(struct ast_filestream *s)
350 {
351         char zero = 0;
352         struct wav_desc *fs = (struct wav_desc *)s->_private;
353
354         if (s->mode == O_RDONLY) {
355                 return;
356         }
357
358         if (s->filename) {
359                 update_header(s->f);
360         }
361
362         /* Pad to even length */
363         if (fs->bytes & 0x1) {
364                 if (fwrite(&zero, 1, 1, s->f) != 1) {
365                         ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
366                 }
367         }
368 }
369
370 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
371 {
372         size_t res;
373         int samples;    /* actual samples read */
374 #if __BYTE_ORDER == __BIG_ENDIAN
375         int x;
376         short *tmp;
377 #endif
378         int bytes;
379         off_t here;
380         /* Send a frame from the file to the appropriate channel */
381         struct wav_desc *fs = (struct wav_desc *)s->_private;
382
383         bytes = (fs->hz == 16000 ? (WAV_BUF_SIZE * 2) : WAV_BUF_SIZE);
384
385         here = ftello(s->f);
386         if (fs->maxlen - here < bytes)          /* truncate if necessary */
387                 bytes = fs->maxlen - here;
388         if (bytes <= 0) {
389                 return NULL;
390         }
391 /*      ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
392         AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
393
394         if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) == 0) {
395                 if (res) {
396                         ast_log(LOG_WARNING, "Short read of %s data (expected %d bytes, read %zu): %s\n",
397                                         ast_format_get_name(s->fr.subclass.format), s->fr.datalen, res,
398                                         strerror(errno));
399                 }
400                 return NULL;
401         }
402         s->fr.datalen = res;
403         s->fr.samples = samples = res / 2;
404
405 #if __BYTE_ORDER == __BIG_ENDIAN
406         tmp = (short *)(s->fr.data.ptr);
407         /* file format is little endian so we need to swap */
408         for( x = 0; x < samples; x++)
409                 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
410 #endif
411
412         *whennext = samples;
413         return &s->fr;
414 }
415
416 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
417 {
418 #if __BYTE_ORDER == __BIG_ENDIAN
419         int x;
420         short tmp[16000], *tmpi;
421 #endif
422         struct wav_desc *s = (struct wav_desc *)fs->_private;
423         int res;
424
425         if (!f->datalen)
426                 return -1;
427
428 #if __BYTE_ORDER == __BIG_ENDIAN
429         /* swap and write */
430         if (f->datalen > sizeof(tmp)) {
431                 ast_log(LOG_WARNING, "Data length is too long\n");
432                 return -1;
433         }
434         tmpi = f->data.ptr;
435         for (x=0; x < f->datalen/2; x++) 
436                 tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8);
437
438         if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
439 #else
440         /* just write */
441         if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) {
442 #endif
443                 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
444                 return -1;
445         }
446
447         s->bytes += f->datalen;
448                 
449         return 0;
450
451 }
452
453 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
454 {
455         off_t min = WAV_HEADER_SIZE, max, cur, offset = 0, samples;
456
457         samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
458
459         if ((cur = ftello(fs->f)) < 0) {
460                 ast_log(AST_LOG_WARNING, "Unable to determine current position in wav filestream %p: %s\n", fs, strerror(errno));
461                 return -1;
462         }
463
464         if (fseeko(fs->f, 0, SEEK_END) < 0) {
465                 ast_log(AST_LOG_WARNING, "Unable to seek to end of wav filestream %p: %s\n", fs, strerror(errno));
466                 return -1;
467         }
468
469         if ((max = ftello(fs->f)) < 0) {
470                 ast_log(AST_LOG_WARNING, "Unable to determine max position in wav filestream %p: %s\n", fs, strerror(errno));
471                 return -1;
472         }
473
474         if (whence == SEEK_SET) {
475                 offset = samples + min;
476         } else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) {
477                 offset = samples + cur;
478         } else if (whence == SEEK_END) {
479                 offset = max - samples;
480         }
481         if (whence != SEEK_FORCECUR) {
482                 offset = (offset > max)?max:offset;
483         }
484         /* always protect the header space. */
485         offset = (offset < min)?min:offset;
486         return fseeko(fs->f, offset, SEEK_SET);
487 }
488
489 static int wav_trunc(struct ast_filestream *fs)
490 {
491         int fd;
492         off_t cur;
493
494         if ((fd = fileno(fs->f)) < 0) {
495                 ast_log(AST_LOG_WARNING, "Unable to determine file descriptor for wav filestream %p: %s\n", fs, strerror(errno));
496                 return -1;
497         }
498         if ((cur = ftello(fs->f)) < 0) {
499                 ast_log(AST_LOG_WARNING, "Unable to determine current position in wav filestream %p: %s\n", fs, strerror(errno));
500                 return -1;
501         }
502         /* Truncate file to current length */
503         if (ftruncate(fd, cur)) {
504                 return -1;
505         }
506         return update_header(fs->f);
507 }
508
509 static off_t wav_tell(struct ast_filestream *fs)
510 {
511         off_t offset;
512         offset = ftello(fs->f);
513         /* subtract header size to get samples, then divide by 2 for 16 bit samples */
514         return (offset - 44)/2;
515 }
516
517 static struct ast_format_def wav16_f = {
518         .name = "wav16",
519         .exts = "wav16",
520         .open = wav_open,
521         .rewrite = wav_rewrite,
522         .write = wav_write,
523         .seek = wav_seek,
524         .trunc = wav_trunc,
525         .tell = wav_tell,
526         .read = wav_read,
527         .close = wav_close,
528         .buf_size = (WAV_BUF_SIZE * 2) + AST_FRIENDLY_OFFSET,
529         .desc_size = sizeof(struct wav_desc),
530 };
531
532 static struct ast_format_def wav_f = {
533         .name = "wav",
534         .exts = "wav",
535         .open = wav_open,
536         .rewrite = wav_rewrite,
537         .write = wav_write,
538         .seek = wav_seek,
539         .trunc = wav_trunc,
540         .tell = wav_tell,
541         .read = wav_read,
542         .close = wav_close,
543         .buf_size = WAV_BUF_SIZE + AST_FRIENDLY_OFFSET,
544         .desc_size = sizeof(struct wav_desc),
545 };
546
547 static int unload_module(void)
548 {
549         return ast_format_def_unregister(wav_f.name)
550                 || ast_format_def_unregister(wav16_f.name);
551 }
552
553 static int load_module(void)
554 {
555         wav_f.format = ast_format_slin;
556         wav16_f.format = ast_format_slin16;
557         if (ast_format_def_register(&wav_f)
558                 || ast_format_def_register(&wav16_f)) {
559                 unload_module();
560                 return AST_MODULE_LOAD_DECLINE;
561         }
562         return AST_MODULE_LOAD_SUCCESS;
563 }
564
565 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Microsoft WAV/WAV16 format (8kHz/16kHz Signed Linear)",
566         .support_level = AST_MODULE_SUPPORT_CORE,
567         .load = load_module,
568         .unload = unload_module,
569         .load_pri = AST_MODPRI_APP_DEPEND
570 );