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