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