fixes & improvements
[lcr.git] / tones.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** PBX4Linux                                                                 **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** opening and reading tone                                                  **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <dirent.h>
20 #include <errno.h>
21 #include "main.h"
22
23 /* 
24 notes about codecs:
25
26 CODEC_OFF is a none accepted value
27 CODEC_LAW is 8 bit (1 byte) data 8khz
28 other codecs are 16 bit (2 bytes) data 8khz
29 the read_tone() will return law or 16bit mono. the read_tone will convert all other formats to 16bit mono.
30
31 */ 
32
33
34 /*
35  * open the tone (don't increase fhuse, since it is done after calling this function)
36  * NOTE: length and left will be set to the number of samples, NOT bytes
37  */
38 struct fmt {
39         unsigned short  stereo; /* 1 = pcm, 2 = adpcm */
40         unsigned short  channels; /* number of channels */
41         unsigned long   sample_rate; /* sample rate */
42         unsigned long   data_rate; /* data rate */
43         unsigned short  bytes_sample; /* bytes per sample (all channels) */
44         unsigned short  bits_sample; /* bits per sample (one channel) */
45 };
46 int open_tone(char *file, int *codec, signed long *length, signed long *left)
47 {
48         int fh;
49         char filename[256];        
50         char linkname[256];        
51         unsigned char buffer[256];
52         struct fmt *fmt;
53         int channels, bytes;
54         unsigned long size, chunk;
55         int gotfmt = 0;
56         struct stat _stat;
57         int linksize;
58         int l;
59         char *p;
60
61
62         /* try to open the law file */
63         SPRINT(filename, "%s.isdn", file);
64         if ((fh = open(filename, O_RDONLY)) >= 0)
65         {
66                 /* stat tone */
67                 l = 0;
68                 while(42)
69                 {
70                         if (l >= 10)
71                         {
72                                 close(fh);
73                                 PERROR("Link chain too deep: '%s'\n", filename);
74                                 return(-1);
75                         }
76                         if (lstat(filename, &_stat) == -1)
77                         {
78                                 close(fh);
79                                 PERROR("Cannot stat file: '%s'\n", filename);
80                                 return(-1);
81                         }
82                         if (!S_ISLNK(_stat.st_mode))
83                         {
84                                 break;
85                         }
86                         if ((linksize=readlink(filename, linkname, sizeof(linkname))) > 0)
87                         {
88                                 linkname[linksize] = '\0';
89                         } else
90                         {
91                                 close(fh);
92                                 PERROR("Cannot read link information: '%s'\n", filename);
93                                 return(-1);
94                         }
95                         if (linkname[0] == '/') /* absolute link */
96                         {
97                                 SCPY(filename, linkname);
98                         } else /* relative link */
99                         {
100                                 /* remove filename */
101                                 p = filename;
102                                 while(strchr(p, '/'))
103                                 {
104                                         p = strchr(p, '/')+1;
105                                 }
106                                 *p = 0;
107                                 /* concat the link */
108                                 SCAT(filename, linkname);
109                         }
110 //printf("follow link: %s\n", filename);
111                         l++;
112                 }
113                 if (length)
114                         *length = _stat.st_size;
115                 if (left)
116                         *left = _stat.st_size;
117                 if (codec)
118                         *codec = CODEC_LAW;
119                 return(fh);
120         }
121
122         /* try to open the wave file */
123         SPRINT(filename, "%s.wav", file);
124         if ((fh = open(filename, O_RDONLY)) >= 0)
125         {
126                 /* get wave header */
127                 read(fh, buffer, 8);
128                 size=(buffer[4]) + (buffer[5]<<8) + (buffer[6]<<16) + (buffer[7]<<24);
129                 if (!!strncmp((char *)buffer, "RIFF", 4))
130                 {
131                         close(fh);
132                         errno = 0;
133                         PERROR("%s is no riff file!\n", filename);
134                         return(-1);
135                 }
136 //              printf("%c%c%c%c size=%ld\n",buffer[0],buffer[1],buffer[2],buffer[3],size);
137                 read(fh, buffer, 4);
138                 size -= 4;
139                 if (!!strncmp((char *)buffer, "WAVE", 4))
140                 {
141                         close(fh);
142                         errno = 0;
143                         PERROR("%s is no wave file!\n", filename);
144                         return(-1);
145                 }
146                 while(size)
147                 {
148                         if (size>0 && size<8)
149                         {
150                                 close(fh);
151                                 errno = 0;
152                                 PERROR("Remaining file size %ld not large enough for next chunk.\n",size);
153                                 return(-1);
154                         }
155                         read(fh, buffer, 8);
156                         chunk=(buffer[4]) + (buffer[5]<<8) + (buffer[6]<<16) + (buffer[7]<<24);
157                         size -= (8+chunk);
158 //                      printf("%c%c%c%c lenght=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],chunk);
159                         if (size < 0)
160                         {
161                                 close(fh);
162                                 errno = 0;
163                                 PERROR("Chunk '%c%c%c%c' is larger than remainig file size (length=%ld)\n",buffer[0],buffer[1],buffer[2],buffer[3], chunk);
164                                 return(-1);
165                         }
166                         if (!strncmp((char *)buffer, "fmt ", 4))
167                         {
168                                 if (chunk != 16)
169                                 {
170                                         close(fh);
171                                         errno = 0;
172                                         PERROR("File %s Fmt chunk illegal size.\n", filename);
173                                         return(-1);
174                                 }
175                                 read(fh, buffer, chunk);
176                                 fmt = (struct fmt *)buffer;
177                                 if (fmt->channels<1 || fmt->channels>2)
178                                 {
179                                         close(fh);
180                                         errno = 0;
181                                         PERROR("File %s Only support one or two channels file.\n", filename);
182                                         return(-1);
183                                 }
184                                 channels = fmt->channels;
185 //                              printf("Channels: %d\n", channels);
186                                 if (fmt->sample_rate != 8000)
187                                 {
188                                         PERROR("Warning: File %s has sample rate of %ld.\n", filename, fmt->sample_rate);
189                                 }
190 //                              printf("Sample Rate: %ld\n", fmt->sample_rate);
191                                 if (fmt->bits_sample!=8 && fmt->bits_sample!=16)
192                                 {
193                                         close(fh);
194                                         errno = 0;
195                                         PERROR("File %s has neigher 8 nor 16 bit samples.\n", filename);
196                                         return(-1);
197                                 }
198                                 bytes = (fmt->bits_sample==16)?2:1;
199 //                              printf("Bit-Resolution: %d\n", bytes*16-16);
200                                 gotfmt = 1;
201                         } else
202                         if (!strncmp((char *)buffer, "data", 4))
203                         {
204                                 if (!gotfmt)
205                                 {
206                                         close(fh);
207                                         errno = 0;
208                                         PERROR("File %s No fmt chunk found before data chunk.\n", filename);
209                                         return(-1);
210                                 }
211 //                              printf("Length: %ld samples (%ld.%03ld seconds)\n", chunk/bytes/channels, chunk/bytes/channels/8000, ((chunk/bytes/channels)%8000)*1000/8000);
212                                 if (bytes==2 && channels==1)
213                                 {
214                                         if (codec)
215                                                 *codec = CODEC_MONO;
216                                         if (length)
217                                                 *length = ((signed long)chunk)>>1;
218                                         if (left)
219                                                 *left = ((signed long)chunk)>>1;
220                                 } else
221                                 if (bytes==2 && channels==2)
222                                 {
223                                         if (codec)
224                                                 *codec = CODEC_STEREO;
225                                         if (length)
226                                                 *length = ((signed long)chunk)>>2;
227                                         if (left)
228                                                 *left = ((signed long)chunk)>>2;
229                                 } else
230                                 if (bytes==1 && channels==1)
231                                 {
232                                         if (codec)
233                                                 *codec = CODEC_8BIT;
234                                         if (length)
235                                                 *length = (signed long)chunk;
236                                         if (left)
237                                                 *left = (signed long)chunk;
238                                 } else
239                                 {
240                                         close(fh);
241                                         errno = 0;
242                                         PERROR("File %s Is not MONO8, MONO16 nor STEREO16.\n", filename);
243                                         return(-1);
244                                 }
245                                 return(fh);
246                         } else
247                         {
248 //                              PDEBUG(DEBUG_PORT, "Unknown chunk '%c%c%c%c'\n",buffer[0],buffer[1],buffer[2],buffer[3]);
249                                 while(chunk > sizeof(buffer))
250                                 {
251                                         read(fh, buffer, sizeof(buffer));
252                                         chunk -=  sizeof(buffer);
253                                 }
254                                 if (chunk)
255                                         read(fh, buffer, chunk);
256                         }
257                         
258                 }
259                 if (!gotfmt)
260                 {
261                         close(fh);
262                         errno = 0;
263                         PERROR("File %s No fmt chunk found in file.\n", filename);
264                         return(-1);
265                 }
266                 close(fh);
267                 errno = 0;
268                 PERROR("File %s No data chunk found in file.\n", filename);
269                 return(-1);
270         }
271
272         return(-1);
273 }
274
275
276 /*
277  * read from tone, check size
278  * the len must be the number of samples, NOT for the bytes to read!!
279  * the data returned is law-code
280  */
281 int read_tone(int fh, unsigned char *buffer, int codec, int len, signed long size, signed long *left, int speed)
282 {
283         int l;
284         int offset;
285         signed short buffer16[len], *buf16 = buffer16;
286         signed short buffer32[len<<1], *buf32 = buffer32;
287         unsigned char buffer8[len], *buf8 = buffer8;
288         signed long sample;
289         int i = 0;
290 //printf("left=%ld\n",*left);
291
292         /* if no *left is given (law has unknown length) */
293         if (!left)
294                 goto unknown_length;
295
296         if (speed!=1)
297         {
298                 offset = ((len&(~4)) * (speed-1));
299                 lseek(fh, offset, SEEK_CUR); /* step fowards, backwards (len must be round to 4 bytes, to be sure, that 16bit stereo will not drift out of sync)*/
300                 *left -= offset; /* correct the current bytes left */
301                 if (*left < 0)
302                 {
303                         /* eof */
304                         *left = 0;
305                         return(0);
306                 }
307                 if (*left >= size)
308                 {
309                         /* eof */
310                         *left = size;
311                         return(0);
312                 }
313         }
314
315         if (*left == 0)
316                 return(0);
317
318         if (*left < len)
319                 len = *left;
320         unknown_length:
321         switch(codec)
322         {
323                 case CODEC_LAW:
324                 l = read(fh, buffer, len); /* as is */
325                 break;
326
327                 case CODEC_MONO:
328                         l = read(fh, buf16, len<<1);
329                         if (l>0)
330                         {
331                                 l = l>>1;
332                                 while(i < l)
333                                 {
334                                         sample = *buf16++;
335                                         if (sample < -32767)
336                                                 sample = -32767;
337                                         if (sample > 32767)
338                                                 sample = 32767;
339                                         *buffer++ = audio_s16_to_law[sample & 0xffff];
340                                         i++;
341                                 }
342                         }
343                 break;
344
345                 case CODEC_STEREO:
346                 {
347                         l = read(fh, buf32, len<<2);
348                         if (l>0)
349                         {
350                                 l = l>>2;
351                                 while(i < l)
352                                 {
353                                         sample = (*buf32++) + (*buf32++);
354                                         if (sample < -32767)
355                                                 sample = -32767;
356                                         if (sample > 32767)
357                                                 sample = 32767;
358                                         *buffer++ = audio_s16_to_law[sample & 0xffff];
359                                         i++;
360                                 }
361                         }
362                 }
363                 break;
364
365                 case CODEC_8BIT:
366                 {
367                         l = read(fh, buf8, len);
368                         if (l>0)
369                         {
370                                 while(i < l)
371                                 {
372                                         *buffer++ = audio_s16_to_law[(((*buf8++)<<8)-0x8000) & 0xffff];
373                                         i++;
374                                 }
375                         }
376                 }
377                 break;
378
379                 default:
380                 FATAL("codec %d is not supported.\n", codec);
381         }
382
383         if (l>0 && left)
384                 *left -= l;
385         return(l);
386 }
387
388
389 struct toneset *toneset_first = NULL;
390
391 /*
392  * free fetched tones
393  */
394 void free_tones(void)
395 {
396         struct toneset *toneset_temp;
397         struct tonesettone *tonesettone_temp;
398         void *temp;
399
400         toneset_temp = toneset_first;
401         while(toneset_temp)
402         {
403                 tonesettone_temp = toneset_temp->first;
404                 while(tonesettone_temp)
405                 {
406                         temp = tonesettone_temp;
407                         tonesettone_temp = tonesettone_temp->next;
408                         FREE(temp, sizeof(struct tonesettone));
409                         memuse--;
410                 }
411                 temp = toneset_temp;
412                 toneset_temp = toneset_temp->next;
413                 FREE(temp, sizeof(struct toneset));
414                 memuse--;
415         }
416         toneset_first = NULL;
417 }
418
419 /*
420  * fetch tones as specified in options.conf
421  */
422 int fetch_tones(void)
423 {
424         DIR *dir;
425         struct dirent *dirent;
426         struct toneset **toneset_nextpointer;
427         struct tonesettone **tonesettone_nextpointer;
428         char *p, *p_next;
429         char path[256];
430         char filename[256], name[256];
431         int fh;
432         int tone_codec;
433         signed long tone_size, tone_left;
434         unsigned long memory = 0;
435         int samples = 0;
436
437         /* if disabled */
438         if (!options.fetch_tones)
439                 return(1);
440
441         toneset_nextpointer = &toneset_first;
442         p = options.fetch_tones;
443         if (*p == '\0')
444                 return(1);
445
446         while (*p)
447         {
448                 p_next = p;
449                 while(*p_next)
450                 {
451                         if (*p_next == ',')
452                         {
453                                 *p_next = '\0';
454                                 p_next++;
455                                 break;
456                         }
457                         p_next++;
458                 }
459
460                 /* remove trailing / */
461                 if (*p) if (p[strlen(p)-1] == '/')
462                         p[strlen(p)-1] = '\0';
463
464                 printf("PBX: Fetching tones '%s'\n", p);
465                 PDEBUG(DEBUG_PORT, "fetching tones directory '%s'\n", p);
466
467                 *toneset_nextpointer = (struct toneset *)MALLOC(sizeof(struct toneset));
468                 memuse++;
469                 memory += sizeof(struct toneset);
470                 SCPY((*toneset_nextpointer)->directory, p);
471                 tonesettone_nextpointer = &(*toneset_nextpointer)->first;
472
473                 SPRINT(path, "%s/%s", INSTALL_DATA, p);
474                 dir = opendir(path);
475                 if (dir == NULL)
476                 {
477                         PERROR("Tone set not found: '%s'\n", path);
478                         return(0);
479                 }
480
481                 while((dirent=readdir(dir)))
482                 {
483                         SPRINT(name, "%s", dirent->d_name);
484
485                         /* remove .isdn and .wave */
486                         if (strlen(name) >= 4)
487                         {
488                                 if (!strcmp(name+strlen(name)-4, ".wav"))
489                                         name[strlen(name)-4] = '\0';
490                         }
491                         if (strlen(name) >= 5)
492                         {
493                                 if (!strcmp(name+strlen(name)-5, ".isdn"))
494                                         name[strlen(name)-5] = '\0';
495                         }
496
497                         SPRINT(filename, "%s/%s", path, name);
498
499                         /* skip . / .. */
500                         if (!strcmp(dirent->d_name, "."))
501                                 continue;
502                         if (!strcmp(dirent->d_name, ".."))
503                                 continue;
504
505                         /* open file */
506                         fh = open_tone(filename, &tone_codec, &tone_size, &tone_left);
507                         if (fh < 0)
508                         {
509                                 PERROR("Cannot open file: '%s'\n", filename);
510                                 continue;
511                         }
512                         fduse++;
513
514                         if (tone_size < 0)
515                         {
516                                 PERROR("File has 0-length: '%s'\n", filename);
517                                 close(fh);
518                                 fduse--;
519                                 continue;
520                         }
521
522                         /* Allocate tone */
523                         *tonesettone_nextpointer = (struct tonesettone *)MALLOC(sizeof(struct tonesettone)+tone_size);
524                         memuse++;
525 //printf("tone:%s, %ld bytes\n", name, tone_size);
526                         memory += sizeof(struct tonesettone)+tone_size;
527                         samples ++;
528
529                         /* load tone */
530                         read_tone(fh, (*tonesettone_nextpointer)->data, tone_codec, tone_size, tone_size, &tone_left, 1);
531                         (*tonesettone_nextpointer)->size = tone_size;
532                         (*tonesettone_nextpointer)->codec = (tone_codec==CODEC_LAW)?CODEC_LAW:CODEC_MONO;
533                         SCPY((*tonesettone_nextpointer)->name, name);
534
535                         close(fh);
536                         fduse--;
537                                  
538                         tonesettone_nextpointer = &((*tonesettone_nextpointer)->next);
539                 }
540
541                 toneset_nextpointer = &((*toneset_nextpointer)->next);
542                 p = p_next;
543         }
544
545         printf("PBX: Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
546         PDEBUG(DEBUG_PORT, "Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
547
548         return(1);
549
550
551
552 /*
553  * opens the fetched tone (if available)
554  */
555 void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length, signed long *left)
556 {
557         struct toneset *toneset;
558         struct tonesettone *tonesettone;
559
560         /* if anything fetched */
561         if (!toneset_first)
562                 return(NULL);
563
564         /* find set */
565         toneset = toneset_first;
566         while(toneset)
567         {
568 //printf("1. comparing '%s' with '%s'\n", toneset->directory, dir);
569                 if (!strcmp(toneset->directory, dir))
570                         break;
571                 toneset = toneset->next;
572         }
573         if (!toneset)
574                 return(NULL);
575
576         /* find tone */
577         tonesettone = toneset->first;
578         while(tonesettone)
579         {
580 //printf("2. comparing '%s' with '%s'\n", tonesettone->name, file);
581                 if (!strcmp(tonesettone->name, file))
582                         break;
583                 tonesettone = tonesettone->next;
584         }
585         if (!tonesettone)
586                 return(NULL);
587
588         /* return information */
589         if (length)
590                 *length = tonesettone->size;
591         if (left)
592                 *left = tonesettone->size;
593         if (codec)
594                 *codec = tonesettone->codec;
595 //printf("size=%ld, data=%08x\n", tonesettone->size, tonesettone->data);
596         return(tonesettone->data);
597 }
598
599
600 /*
601  * read from fetched tone, check size
602  * the len must be the number of samples, NOT for the bytes to read!!
603  */
604 int read_tone_fetched(void **fetched, void *buffer, int len, signed long size, signed long *left, int speed)
605 {
606         int l;
607 //printf("left=%ld\n",*left);
608
609         /* if no *left is given (law has unknown length) */
610         if (!left)
611                 return(0);
612
613         if (*left == 0)
614                 return(0);
615
616         if (*left < len)
617                 len = *left;
618
619         memcpy(buffer, *fetched, len);
620         *((char **)fetched) += len;
621         l = len;
622
623         if (l>0 && left)
624                 *left -= l;
625         return(l);
626 }
627