e5f2c759fdc3247633e5f1bc021c9dcd992388a7
[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 length=%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                                         printf("left=%d\n",*left);
221                                 } else
222                                 if (bytes==2 && channels==2)
223                                 {
224                                         if (codec)
225                                                 *codec = CODEC_STEREO;
226                                         if (length)
227                                                 *length = ((signed long)chunk)>>2;
228                                         if (left)
229                                                 *left = ((signed long)chunk)>>2;
230                                 } else
231                                 if (bytes==1 && channels==1)
232                                 {
233                                         if (codec)
234                                                 *codec = CODEC_8BIT;
235                                         if (length)
236                                                 *length = (signed long)chunk;
237                                         if (left)
238                                                 *left = (signed long)chunk;
239                                 } else
240                                 {
241                                         close(fh);
242                                         errno = 0;
243                                         PERROR("File %s Is not MONO8, MONO16 nor STEREO16.\n", filename);
244                                         return(-1);
245                                 }
246                                 return(fh);
247                         } else
248                         {
249 //                              PDEBUG(DEBUG_PORT, "Unknown chunk '%c%c%c%c'\n",buffer[0],buffer[1],buffer[2],buffer[3]);
250                                 while(chunk > sizeof(buffer))
251                                 {
252                                         read(fh, buffer, sizeof(buffer));
253                                         chunk -=  sizeof(buffer);
254                                 }
255                                 if (chunk)
256                                         read(fh, buffer, chunk);
257                         }
258                         
259                 }
260                 if (!gotfmt)
261                 {
262                         close(fh);
263                         errno = 0;
264                         PERROR("File %s No fmt chunk found in file.\n", filename);
265                         return(-1);
266                 }
267                 close(fh);
268                 errno = 0;
269                 PERROR("File %s No data chunk found in file.\n", filename);
270                 return(-1);
271         }
272
273         return(-1);
274 }
275
276
277 /*
278  * read from tone, check size
279  * the len must be the number of samples, NOT for the bytes to read!!
280  * the data returned is law-code
281  */
282 int read_tone(int fh, unsigned char *buffer, int codec, int len, signed long size, signed long *left, int speed)
283 {
284         int l;
285         int offset;
286         signed short buffer16[len], *buf16 = buffer16;
287         signed short buffer32[len<<1], *buf32 = buffer32;
288         unsigned char buffer8[len], *buf8 = buffer8;
289         signed long sample;
290         int i = 0;
291 //printf("left=%ld\n",*left);
292
293         /* if no *left is given (law has unknown length) */
294         if (!left)
295                 goto unknown_length;
296
297         if (speed!=1)
298         {
299                 offset = ((len&(~4)) * (speed-1));
300                 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)*/
301                 *left -= offset; /* correct the current bytes left */
302                 if (*left < 0)
303                 {
304                         /* eof */
305                         *left = 0;
306                         return(0);
307                 }
308                 if (*left >= size)
309                 {
310                         /* eof */
311                         *left = size;
312                         return(0);
313                 }
314         }
315
316         if (*left == 0)
317                 return(0);
318
319         if (*left < len)
320                 len = *left;
321         unknown_length:
322         switch(codec)
323         {
324                 case CODEC_LAW:
325                 l = read(fh, buffer, len); /* as is */
326                 break;
327
328                 case CODEC_MONO:
329                         l = read(fh, buf16, len<<1);
330                         if (l>0)
331                         {
332                                 l = l>>1;
333                                 while(i < l)
334                                 {
335                                         sample = *buf16++;
336                                         if (sample < -32767)
337                                                 sample = -32767;
338                                         if (sample > 32767)
339                                                 sample = 32767;
340                                         *buffer++ = audio_s16_to_law[sample & 0xffff];
341                                         i++;
342                                 }
343                         }
344                 break;
345
346                 case CODEC_STEREO:
347                 {
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                         l = read(fh, buf8, len);
369                         if (l>0)
370                         {
371                                 while(i < l)
372                                 {
373                                         *buffer++ = audio_s16_to_law[(((*buf8++)<<8)-0x8000) & 0xffff];
374                                         i++;
375                                 }
376                         }
377                 }
378                 break;
379
380                 default:
381                 FATAL("codec %d is not supported.\n", codec);
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, sizeof(struct tonesettone));
410                         memuse--;
411                 }
412                 temp = toneset_temp;
413                 toneset_temp = toneset_temp->next;
414                 FREE(temp, sizeof(struct toneset));
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 *)MALLOC(sizeof(struct toneset));
469                 memuse++;
470                 memory += sizeof(struct toneset);
471                 SCPY((*toneset_nextpointer)->directory, p);
472                 tonesettone_nextpointer = &(*toneset_nextpointer)->first;
473
474                 SPRINT(path, "%s/%s", INSTALL_DATA, p);
475                 dir = opendir(path);
476                 if (dir == NULL)
477                 {
478                         PERROR("Tone set not found: '%s'\n", path);
479                         return(0);
480                 }
481
482                 while((dirent=readdir(dir)))
483                 {
484                         SPRINT(name, "%s", dirent->d_name);
485
486                         /* remove .isdn and .wave */
487                         if (strlen(name) >= 4)
488                         {
489                                 if (!strcmp(name+strlen(name)-4, ".wav"))
490                                         name[strlen(name)-4] = '\0';
491                         }
492                         if (strlen(name) >= 5)
493                         {
494                                 if (!strcmp(name+strlen(name)-5, ".isdn"))
495                                         name[strlen(name)-5] = '\0';
496                         }
497
498                         SPRINT(filename, "%s/%s", path, name);
499
500                         /* skip . / .. */
501                         if (!strcmp(dirent->d_name, "."))
502                                 continue;
503                         if (!strcmp(dirent->d_name, ".."))
504                                 continue;
505
506                         /* open file */
507                         fh = open_tone(filename, &tone_codec, &tone_size, &tone_left);
508                         if (fh < 0)
509                         {
510                                 PERROR("Cannot open file: '%s'\n", filename);
511                                 continue;
512                         }
513                         fduse++;
514
515                         if (tone_size < 0)
516                         {
517                                 PERROR("File has 0-length: '%s'\n", filename);
518                                 close(fh);
519                                 fduse--;
520                                 continue;
521                         }
522
523                         /* Allocate tone */
524                         *tonesettone_nextpointer = (struct tonesettone *)MALLOC(sizeof(struct tonesettone)+tone_size);
525                         memuse++;
526 //printf("tone:%s, %ld bytes\n", name, tone_size);
527                         memory += sizeof(struct tonesettone)+tone_size;
528                         samples ++;
529
530                         /* load tone */
531                         read_tone(fh, (*tonesettone_nextpointer)->data, tone_codec, tone_size, tone_size, &tone_left, 1);
532                         (*tonesettone_nextpointer)->size = tone_size;
533                         (*tonesettone_nextpointer)->codec = (tone_codec==CODEC_LAW)?CODEC_LAW:CODEC_MONO;
534                         SCPY((*tonesettone_nextpointer)->name, name);
535
536                         close(fh);
537                         fduse--;
538                                  
539                         tonesettone_nextpointer = &((*tonesettone_nextpointer)->next);
540                 }
541
542                 toneset_nextpointer = &((*toneset_nextpointer)->next);
543                 p = p_next;
544         }
545
546         printf("PBX: Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
547         PDEBUG(DEBUG_PORT, "Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
548
549         return(1);
550
551
552
553 /*
554  * opens the fetched tone (if available)
555  */
556 void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length, signed long *left)
557 {
558         struct toneset *toneset;
559         struct tonesettone *tonesettone;
560
561         /* if anything fetched */
562         if (!toneset_first)
563                 return(NULL);
564
565         /* find set */
566         toneset = toneset_first;
567         while(toneset)
568         {
569 //printf("1. comparing '%s' with '%s'\n", toneset->directory, dir);
570                 if (!strcmp(toneset->directory, dir))
571                         break;
572                 toneset = toneset->next;
573         }
574         if (!toneset)
575                 return(NULL);
576
577         /* find tone */
578         tonesettone = toneset->first;
579         while(tonesettone)
580         {
581 //printf("2. comparing '%s' with '%s'\n", tonesettone->name, file);
582                 if (!strcmp(tonesettone->name, file))
583                         break;
584                 tonesettone = tonesettone->next;
585         }
586         if (!tonesettone)
587                 return(NULL);
588
589         /* return information */
590         if (length)
591                 *length = tonesettone->size;
592         if (left)
593                 *left = tonesettone->size;
594         if (codec)
595                 *codec = tonesettone->codec;
596 //printf("size=%ld, data=%08x\n", tonesettone->size, tonesettone->data);
597         return(tonesettone->data);
598 }
599
600
601 /*
602  * read from fetched tone, check size
603  * the len must be the number of samples, NOT for the bytes to read!!
604  */
605 int read_tone_fetched(void **fetched, void *buffer, int len, signed long size, signed long *left, int speed)
606 {
607         int l;
608 //printf("left=%ld\n",*left);
609
610         /* if no *left is given (law has unknown length) */
611         if (!left)
612                 return(0);
613
614         if (*left == 0)
615                 return(0);
616
617         if (*left < len)
618                 len = *left;
619
620         memcpy(buffer, *fetched, len);
621         *((char **)fetched) += len;
622         l = len;
623
624         if (l>0 && left)
625                 *left -= l;
626         return(l);
627 }
628