only for backup, still in coding state - no compile!!!
[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  */
280 int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed long *left, int speed)
281 {
282         int l;
283         int offset;
284 //printf("left=%ld\n",*left);
285
286         /* if no *left is given (law has unknown length) */
287         if (!left)
288                 goto unknown_length;
289
290         if (speed!=1)
291         {
292                 offset = ((len&(~4)) * (speed-1));
293                 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)*/
294                 *left -= offset; /* correct the current bytes left */
295                 if (*left < 0)
296                 {
297                         /* eof */
298                         *left = 0;
299                         return(0);
300                 }
301                 if (*left >= size)
302                 {
303                         /* eof */
304                         *left = size;
305                         return(0);
306                 }
307         }
308
309         if (*left == 0)
310                 return(0);
311
312         if (*left < len)
313                 len = *left;
314         unknown_length:
315         switch(codec)
316         {
317                 case CODEC_LAW:
318                 l = read(fh, buffer, len); /* as is */
319                 break;
320
321                 case CODEC_MONO:
322                 l = read(fh, buffer, len<<1); /* as is */
323                 if (l>0)
324                         l = l>>1;
325                 break;
326
327                 case CODEC_STEREO:
328                 {
329                         signed short buffer32[len<<1], *buf32 = buffer32;
330                         signed short *buf16 = (signed short *)buffer;
331                         signed long sample;
332                         int i = 0;
333                         l = read(fh, buf32, len<<2);
334                         if (l>0)
335                         {
336                                 l = l>>2;
337                                 while(i < l)
338                                 {
339                                         sample = (*buf32++) + (*buf32++);
340                                         if (sample < -32767)
341                                                 sample = -32767;
342                                         if (sample > 32767)
343                                                 sample = 32767;
344                                         *buf16++ = sample;
345                                         i++;
346                                 }
347                         }
348                 }
349                 break;
350
351                 case CODEC_8BIT:
352                 {
353                         unsigned char buffer8[len], *buf8 = buffer8;
354                         signed short *buf16 = (signed short *)buffer;
355                         int i = 0;
356                         l = read(fh, buf8, len);
357                         if (l>0)
358                         {
359                                 while(i < l)
360                                 {
361                                         *buf16++ = (((*buf8++) << 8) - 0x8000) & 0xffff;
362                                         i++;
363                                 }
364                         }
365                 }
366                 break;
367
368                 default:
369                 PERROR("codec %d is not specified or supported, exitting...\n", codec);
370                 exit(-1);
371         }
372
373         if (l>0 && left)
374                 *left -= l;
375         return(l);
376 }
377
378
379 struct toneset *toneset_first = NULL;
380
381 /*
382  * free fetched tones
383  */
384 void free_tones(void)
385 {
386         struct toneset *toneset_temp;
387         struct tonesettone *tonesettone_temp;
388         void *temp;
389
390         toneset_temp = toneset_first;
391         while(toneset_temp)
392         {
393                 tonesettone_temp = toneset_temp->first;
394                 while(tonesettone_temp)
395                 {
396                         temp = tonesettone_temp;
397                         tonesettone_temp = tonesettone_temp->next;
398                         free(temp);
399                         memuse--;
400                 }
401                 temp = toneset_temp;
402                 toneset_temp = toneset_temp->next;
403                 free(temp);
404                 memuse--;
405         }
406         toneset_first = NULL;
407 }
408
409 /*
410  * fetch tones as specified in options.conf
411  */
412 int fetch_tones(void)
413 {
414         DIR *dir;
415         struct dirent *dirent;
416         struct toneset **toneset_nextpointer;
417         struct tonesettone **tonesettone_nextpointer;
418         char *p, *p_next;
419         char path[256];
420         char filename[256], name[256];
421         int fh;
422         int tone_codec;
423         signed long tone_size, tone_left, real_size;
424         unsigned long memory = 0;
425         int samples = 0;
426
427         /* if disabled */
428         if (!options.fetch_tones)
429                 return(1);
430
431         toneset_nextpointer = &toneset_first;
432         p = options.fetch_tones;
433         if (*p == '\0')
434                 return(1);
435
436         while (*p)
437         {
438                 p_next = p;
439                 while(*p_next)
440                 {
441                         if (*p_next == ',')
442                         {
443                                 *p_next = '\0';
444                                 p_next++;
445                                 break;
446                         }
447                         p_next++;
448                 }
449
450                 /* remove trailing / */
451                 if (*p) if (p[strlen(p)-1] == '/')
452                         p[strlen(p)-1] = '\0';
453
454                 printf("PBX: Fetching tones '%s'\n", p);
455                 PDEBUG(DEBUG_PORT, "fetching tones directory '%s'\n", p);
456
457                 *toneset_nextpointer = (struct toneset *)calloc(1, sizeof(struct toneset));
458                 if (*toneset_nextpointer == NULL)
459                 {
460                         PERROR("No memory for tone set: '%s'\n",p);
461                         return(0);
462                 }
463                 memuse++;
464                 memory += sizeof(struct toneset);
465                 memset(*toneset_nextpointer, 0 , sizeof(struct toneset));
466                 SCPY((*toneset_nextpointer)->directory, p);
467                 tonesettone_nextpointer = &(*toneset_nextpointer)->first;
468
469                 SPRINT(path, "%s/%s", INSTALL_DATA, p);
470                 dir = opendir(path);
471                 if (dir == NULL)
472                 {
473                         PERROR("Tone set not found: '%s'\n", path);
474                         return(0);
475                 }
476
477                 while((dirent=readdir(dir)))
478                 {
479                         SPRINT(name, "%s", dirent->d_name);
480
481                         /* remove .isdn and .wave */
482                         if (strlen(name) >= 4)
483                         {
484                                 if (!strcmp(name+strlen(name)-4, ".wav"))
485                                         name[strlen(name)-4] = '\0';
486                         }
487                         if (strlen(name) >= 5)
488                         {
489                                 if (!strcmp(name+strlen(name)-5, ".isdn"))
490                                         name[strlen(name)-5] = '\0';
491                         }
492
493                         SPRINT(filename, "%s/%s", path, name);
494
495                         /* skip . / .. */
496                         if (!strcmp(dirent->d_name, "."))
497                                 continue;
498                         if (!strcmp(dirent->d_name, ".."))
499                                 continue;
500
501                         /* open file */
502                         fh = open_tone(filename, &tone_codec, &tone_size, &tone_left);
503                         if (fh < 0)
504                         {
505                                 PERROR("Cannot open file: '%s'\n", filename);
506                                 continue;
507                         }
508                         fduse++;
509
510                         if (tone_size < 0)
511                         {
512                                 PERROR("File has 0-length: '%s'\n", filename);
513                                 close(fh);
514                                 fduse--;
515                                 continue;
516                         }
517
518                         /* real size */
519                         switch(tone_codec)
520                         {
521                                 case CODEC_LAW:
522                                 real_size = tone_size;
523                                 break;
524
525                                 case CODEC_MONO:
526                                 real_size = tone_size << 1;
527                                 break;
528
529                                 case CODEC_STEREO:
530                                 real_size = tone_size << 1;
531                                 break;
532
533                                 case CODEC_8BIT:
534                                 real_size = tone_size << 1;
535                                 break;
536
537                                 default:
538                                 PERROR("codec %d is not specified or supported, exitting...\n", tone_codec);
539                                 exit(-1);
540                         }
541
542                         /* allocate tone */
543                         *tonesettone_nextpointer = (struct tonesettone *)calloc(1, sizeof(struct tonesettone)+real_size);
544                         if (*toneset_nextpointer == NULL)
545                         {
546                                 PERROR("No memory for tone set: '%s'\n",p);
547                                 close(fh);
548                                 fduse--;
549                                 return(0);
550                         }
551                         memuse++;
552 //printf("tone:%s, %ld bytes\n", name, tone_size);
553                         memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+real_size);
554                         memory += sizeof(struct tonesettone)+real_size;
555                         samples ++;
556
557                         /* load tone */
558                         read_tone(fh, (*tonesettone_nextpointer)->data, tone_codec, tone_size, tone_size, &tone_left, 1);
559                         (*tonesettone_nextpointer)->size = tone_size;
560                         (*tonesettone_nextpointer)->codec = (tone_codec==CODEC_LAW)?CODEC_LAW:CODEC_MONO;
561                         SCPY((*tonesettone_nextpointer)->name, name);
562
563                         close(fh);
564                         fduse--;
565                                  
566                         tonesettone_nextpointer = &((*tonesettone_nextpointer)->next);
567                 }
568
569                 toneset_nextpointer = &((*toneset_nextpointer)->next);
570                 p = p_next;
571         }
572
573         printf("PBX: Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
574         PDEBUG(DEBUG_PORT, "Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
575
576         return(1);
577
578
579
580 /*
581  * opens the fetched tone (if available)
582  */
583 void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length, signed long *left)
584 {
585         struct toneset *toneset;
586         struct tonesettone *tonesettone;
587
588         /* if anything fetched */
589         if (!toneset_first)
590                 return(NULL);
591
592         /* find set */
593         toneset = toneset_first;
594         while(toneset)
595         {
596 //printf("1. comparing '%s' with '%s'\n", toneset->directory, dir);
597                 if (!strcmp(toneset->directory, dir))
598                         break;
599                 toneset = toneset->next;
600         }
601         if (!toneset)
602                 return(NULL);
603
604         /* find tone */
605         tonesettone = toneset->first;
606         while(tonesettone)
607         {
608 //printf("2. comparing '%s' with '%s'\n", tonesettone->name, file);
609                 if (!strcmp(tonesettone->name, file))
610                         break;
611                 tonesettone = tonesettone->next;
612         }
613         if (!tonesettone)
614                 return(NULL);
615
616         /* return information */
617         if (length)
618                 *length = tonesettone->size;
619         if (left)
620                 *left = tonesettone->size;
621         if (codec)
622                 *codec = tonesettone->codec;
623 //printf("size=%ld, data=%08x\n", tonesettone->size, tonesettone->data);
624         return(tonesettone->data);
625 }
626
627
628 /*
629  * read from fetched tone, check size
630  * the len must be the number of samples, NOT for the bytes to read!!
631  */
632 int read_tone_fetched(void **fetched, void *buffer, int codec, int len, signed long size, signed long *left, int speed)
633 {
634         int l;
635 //printf("left=%ld\n",*left);
636
637         /* if no *left is given (law has unknown length) */
638         if (!left)
639                 return(0);
640
641         if (*left == 0)
642                 return(0);
643
644         if (*left < len)
645                 len = *left;
646         switch(codec)
647         {
648                 case CODEC_LAW:
649                 memcpy(buffer, *fetched, len);
650                 *((char **)fetched) += len;
651                 l = len;
652                 break;
653
654                 case CODEC_MONO:
655                 memcpy(buffer, *fetched, len<<1);
656                 *((char **)fetched) += len<<1;
657                 l = len;
658                 break;
659
660                 default:
661                 PERROR("codec %d is not specified or supported, exitting...\n", codec);
662                 exit(-1);
663         }
664
665         if (l>0 && left)
666                 *left -= l;
667         return(l);
668 }
669