backup
[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                 PERROR("codec %d is not supported, exitting...\n", codec);
381                 exit(-1);
382         }
383
384         if (l>0 && left)
385                 *left -= l;
386         return(l);
387 }
388
389
390 struct toneset *toneset_first = NULL;
391
392 /*
393  * free fetched tones
394  */
395 void free_tones(void)
396 {
397         struct toneset *toneset_temp;
398         struct tonesettone *tonesettone_temp;
399         void *temp;
400
401         toneset_temp = toneset_first;
402         while(toneset_temp)
403         {
404                 tonesettone_temp = toneset_temp->first;
405                 while(tonesettone_temp)
406                 {
407                         temp = tonesettone_temp;
408                         tonesettone_temp = tonesettone_temp->next;
409                         free(temp);
410                         memuse--;
411                 }
412                 temp = toneset_temp;
413                 toneset_temp = toneset_temp->next;
414                 free(temp);
415                 memuse--;
416         }
417         toneset_first = NULL;
418 }
419
420 /*
421  * fetch tones as specified in options.conf
422  */
423 int fetch_tones(void)
424 {
425         DIR *dir;
426         struct dirent *dirent;
427         struct toneset **toneset_nextpointer;
428         struct tonesettone **tonesettone_nextpointer;
429         char *p, *p_next;
430         char path[256];
431         char filename[256], name[256];
432         int fh;
433         int tone_codec;
434         signed long tone_size, tone_left;
435         unsigned long memory = 0;
436         int samples = 0;
437
438         /* if disabled */
439         if (!options.fetch_tones)
440                 return(1);
441
442         toneset_nextpointer = &toneset_first;
443         p = options.fetch_tones;
444         if (*p == '\0')
445                 return(1);
446
447         while (*p)
448         {
449                 p_next = p;
450                 while(*p_next)
451                 {
452                         if (*p_next == ',')
453                         {
454                                 *p_next = '\0';
455                                 p_next++;
456                                 break;
457                         }
458                         p_next++;
459                 }
460
461                 /* remove trailing / */
462                 if (*p) if (p[strlen(p)-1] == '/')
463                         p[strlen(p)-1] = '\0';
464
465                 printf("PBX: Fetching tones '%s'\n", p);
466                 PDEBUG(DEBUG_PORT, "fetching tones directory '%s'\n", p);
467
468                 *toneset_nextpointer = (struct toneset *)calloc(1, sizeof(struct toneset));
469                 if (*toneset_nextpointer == NULL)
470                 {
471                         PERROR("No memory for tone set: '%s'\n",p);
472                         return(0);
473                 }
474                 memuse++;
475                 memory += sizeof(struct toneset);
476                 memset(*toneset_nextpointer, 0 , sizeof(struct toneset));
477                 SCPY((*toneset_nextpointer)->directory, p);
478                 tonesettone_nextpointer = &(*toneset_nextpointer)->first;
479
480                 SPRINT(path, "%s/%s", INSTALL_DATA, p);
481                 dir = opendir(path);
482                 if (dir == NULL)
483                 {
484                         PERROR("Tone set not found: '%s'\n", path);
485                         return(0);
486                 }
487
488                 while((dirent=readdir(dir)))
489                 {
490                         SPRINT(name, "%s", dirent->d_name);
491
492                         /* remove .isdn and .wave */
493                         if (strlen(name) >= 4)
494                         {
495                                 if (!strcmp(name+strlen(name)-4, ".wav"))
496                                         name[strlen(name)-4] = '\0';
497                         }
498                         if (strlen(name) >= 5)
499                         {
500                                 if (!strcmp(name+strlen(name)-5, ".isdn"))
501                                         name[strlen(name)-5] = '\0';
502                         }
503
504                         SPRINT(filename, "%s/%s", path, name);
505
506                         /* skip . / .. */
507                         if (!strcmp(dirent->d_name, "."))
508                                 continue;
509                         if (!strcmp(dirent->d_name, ".."))
510                                 continue;
511
512                         /* open file */
513                         fh = open_tone(filename, &tone_codec, &tone_size, &tone_left);
514                         if (fh < 0)
515                         {
516                                 PERROR("Cannot open file: '%s'\n", filename);
517                                 continue;
518                         }
519                         fduse++;
520
521                         if (tone_size < 0)
522                         {
523                                 PERROR("File has 0-length: '%s'\n", filename);
524                                 close(fh);
525                                 fduse--;
526                                 continue;
527                         }
528
529                         /* allocate tone */
530                         *tonesettone_nextpointer = (struct tonesettone *)calloc(1, sizeof(struct tonesettone)+tone_size);
531                         if (*toneset_nextpointer == NULL)
532                         {
533                                 PERROR("No memory for tone set: '%s'\n",p);
534                                 close(fh);
535                                 fduse--;
536                                 return(0);
537                         }
538                         memuse++;
539 //printf("tone:%s, %ld bytes\n", name, tone_size);
540                         memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+tone_size);
541                         memory += sizeof(struct tonesettone)+tone_size;
542                         samples ++;
543
544                         /* load tone */
545                         read_tone(fh, (*tonesettone_nextpointer)->data, tone_codec, tone_size, tone_size, &tone_left, 1);
546                         (*tonesettone_nextpointer)->size = tone_size;
547                         (*tonesettone_nextpointer)->codec = (tone_codec==CODEC_LAW)?CODEC_LAW:CODEC_MONO;
548                         SCPY((*tonesettone_nextpointer)->name, name);
549
550                         close(fh);
551                         fduse--;
552                                  
553                         tonesettone_nextpointer = &((*tonesettone_nextpointer)->next);
554                 }
555
556                 toneset_nextpointer = &((*toneset_nextpointer)->next);
557                 p = p_next;
558         }
559
560         printf("PBX: Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
561         PDEBUG(DEBUG_PORT, "Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
562
563         return(1);
564
565
566
567 /*
568  * opens the fetched tone (if available)
569  */
570 void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length, signed long *left)
571 {
572         struct toneset *toneset;
573         struct tonesettone *tonesettone;
574
575         /* if anything fetched */
576         if (!toneset_first)
577                 return(NULL);
578
579         /* find set */
580         toneset = toneset_first;
581         while(toneset)
582         {
583 //printf("1. comparing '%s' with '%s'\n", toneset->directory, dir);
584                 if (!strcmp(toneset->directory, dir))
585                         break;
586                 toneset = toneset->next;
587         }
588         if (!toneset)
589                 return(NULL);
590
591         /* find tone */
592         tonesettone = toneset->first;
593         while(tonesettone)
594         {
595 //printf("2. comparing '%s' with '%s'\n", tonesettone->name, file);
596                 if (!strcmp(tonesettone->name, file))
597                         break;
598                 tonesettone = tonesettone->next;
599         }
600         if (!tonesettone)
601                 return(NULL);
602
603         /* return information */
604         if (length)
605                 *length = tonesettone->size;
606         if (left)
607                 *left = tonesettone->size;
608         if (codec)
609                 *codec = tonesettone->codec;
610 //printf("size=%ld, data=%08x\n", tonesettone->size, tonesettone->data);
611         return(tonesettone->data);
612 }
613
614
615 /*
616  * read from fetched tone, check size
617  * the len must be the number of samples, NOT for the bytes to read!!
618  */
619 int read_tone_fetched(void **fetched, void *buffer, int len, signed long size, signed long *left, int speed)
620 {
621         int l;
622 //printf("left=%ld\n",*left);
623
624         /* if no *left is given (law has unknown length) */
625         if (!left)
626                 return(0);
627
628         if (*left == 0)
629                 return(0);
630
631         if (*left < len)
632                 len = *left;
633
634         memcpy(buffer, *fetched, len);
635         *((char **)fetched) += len;
636         l = len;
637
638         if (l>0 && left)
639                 *left -= l;
640         return(l);
641 }
642