SIP: Fix incoming re-invite
[lcr.git] / tones.c
diff --git a/tones.c b/tones.c
index 5d64125..d562531 100644 (file)
--- a/tones.c
+++ b/tones.c
@@ -9,15 +9,6 @@
 **                                                                           **
 \*****************************************************************************/ 
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <errno.h>
 #include "main.h"
 
 /* 
@@ -38,69 +29,60 @@ the read_tone() will return law or 16bit mono. the read_tone will convert all ot
 struct fmt {
        unsigned short  stereo; /* 1 = pcm, 2 = adpcm */
        unsigned short  channels; /* number of channels */
-       unsigned long   sample_rate; /* sample rate */
-       unsigned long   data_rate; /* data rate */
+       unsigned int   sample_rate; /* sample rate */
+       unsigned int   data_rate; /* data rate */
        unsigned short  bytes_sample; /* bytes per sample (all channels) */
        unsigned short  bits_sample; /* bits per sample (one channel) */
 };
-int open_tone(char *file, int *codec, signed long *length, signed long *left)
+int open_tone(char *file, int *codec, signed int *length, signed int *left)
 {
        int fh;
        char filename[256];        
        char linkname[256];        
        unsigned char buffer[256];
        struct fmt *fmt;
-       int channels, bytes;
-       unsigned long size, chunk;
+       int channels = 0, bytes = 0;
+       unsigned int size, chunk;
        int gotfmt = 0;
        struct stat _stat;
        int linksize;
        int l;
        char *p;
+       int __attribute__((__unused__)) ret;
 
 
        /* try to open the law file */
        SPRINT(filename, "%s.isdn", file);
-       if ((fh = open(filename, O_RDONLY)) >= 0)
-       {
+       if ((fh = open(filename, O_RDONLY)) >= 0) {
                /* stat tone */
                l = 0;
-               while(42)
-               {
-                       if (l >= 10)
-                       {
+               while(42) {
+                       if (l >= 10) {
                                close(fh);
                                PERROR("Link chain too deep: '%s'\n", filename);
                                return(-1);
                        }
-                       if (lstat(filename, &_stat) == -1)
-                       {
+                       if (lstat(filename, &_stat) == -1) {
                                close(fh);
                                PERROR("Cannot stat file: '%s'\n", filename);
                                return(-1);
                        }
-                       if (!S_ISLNK(_stat.st_mode))
-                       {
+                       if (!S_ISLNK(_stat.st_mode)) {
                                break;
                        }
-                       if ((linksize=readlink(filename, linkname, sizeof(linkname))) > 0)
-                       {
+                       if ((linksize=readlink(filename, linkname, sizeof(linkname))) > 0) {
                                linkname[linksize] = '\0';
-                       } else
-                       {
+                       } else {
                                close(fh);
                                PERROR("Cannot read link information: '%s'\n", filename);
                                return(-1);
                        }
                        if (linkname[0] == '/') /* absolute link */
-                       {
                                SCPY(filename, linkname);
-                       } else /* relative link */
-                       {
+                       else { /* relative link */
                                /* remove filename */
                                p = filename;
-                               while(strchr(p, '/'))
-                               {
+                               while(strchr(p, '/')) {
                                        p = strchr(p, '/')+1;
                                }
                                *p = 0;
@@ -121,61 +103,52 @@ int open_tone(char *file, int *codec, signed long *length, signed long *left)
 
        /* try to open the wave file */
        SPRINT(filename, "%s.wav", file);
-       if ((fh = open(filename, O_RDONLY)) >= 0)
-       {
+       if ((fh = open(filename, O_RDONLY)) >= 0) {
                /* get wave header */
-               read(fh, buffer, 8);
+               ret = read(fh, buffer, 8);
                size=(buffer[4]) + (buffer[5]<<8) + (buffer[6]<<16) + (buffer[7]<<24);
-               if (!!strncmp((char *)buffer, "RIFF", 4))
-               {
+               if (!!strncmp((char *)buffer, "RIFF", 4)) {
                        close(fh);
                        errno = 0;
                        PERROR("%s is no riff file!\n", filename);
                        return(-1);
                }
 //             printf("%c%c%c%c size=%ld\n",buffer[0],buffer[1],buffer[2],buffer[3],size);
-               read(fh, buffer, 4);
+               ret = read(fh, buffer, 4);
                size -= 4;
-               if (!!strncmp((char *)buffer, "WAVE", 4))
-               {
+               if (!!strncmp((char *)buffer, "WAVE", 4)) {
                        close(fh);
                        errno = 0;
                        PERROR("%s is no wave file!\n", filename);
                        return(-1);
                }
-               while(size)
-               {
-                       if (size>0 && size<8)
-                       {
+               while(size) {
+                       if (size>0 && size<8) {
                                close(fh);
                                errno = 0;
                                PERROR("Remaining file size %ld not large enough for next chunk.\n",size);
                                return(-1);
                        }
-                       read(fh, buffer, 8);
+                       ret = read(fh, buffer, 8);
                        chunk=(buffer[4]) + (buffer[5]<<8) + (buffer[6]<<16) + (buffer[7]<<24);
                        size -= (8+chunk);
-//                     printf("%c%c%c%c lenght=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],chunk);
-                       if (size < 0)
-                       {
+//                     printf("%c%c%c%c length=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],chunk);
+                       if (size < 0) {
                                close(fh);
                                errno = 0;
                                PERROR("Chunk '%c%c%c%c' is larger than remainig file size (length=%ld)\n",buffer[0],buffer[1],buffer[2],buffer[3], chunk);
                                return(-1);
                        }
-                       if (!strncmp((char *)buffer, "fmt ", 4))
-                       {
-                               if (chunk != 16)
-                               {
+                       if (!strncmp((char *)buffer, "fmt ", 4)) {
+                               if (chunk < 16) {
                                        close(fh);
                                        errno = 0;
                                        PERROR("File %s Fmt chunk illegal size.\n", filename);
                                        return(-1);
                                }
-                               read(fh, buffer, chunk);
+                               ret = read(fh, buffer, chunk);
                                fmt = (struct fmt *)buffer;
-                               if (fmt->channels<1 || fmt->channels>2)
-                               {
+                               if (fmt->channels<1 || fmt->channels>2) {
                                        close(fh);
                                        errno = 0;
                                        PERROR("File %s Only support one or two channels file.\n", filename);
@@ -183,13 +156,11 @@ int open_tone(char *file, int *codec, signed long *length, signed long *left)
                                }
                                channels = fmt->channels;
 //                             printf("Channels: %d\n", channels);
-                               if (fmt->sample_rate != 8000)
-                               {
+                               if (fmt->sample_rate != 8000) {
                                        PERROR("Warning: File %s has sample rate of %ld.\n", filename, fmt->sample_rate);
                                }
 //                             printf("Sample Rate: %ld\n", fmt->sample_rate);
-                               if (fmt->bits_sample!=8 && fmt->bits_sample!=16)
-                               {
+                               if (fmt->bits_sample!=8 && fmt->bits_sample!=16) {
                                        close(fh);
                                        errno = 0;
                                        PERROR("File %s has neigher 8 nor 16 bit samples.\n", filename);
@@ -199,65 +170,57 @@ int open_tone(char *file, int *codec, signed long *length, signed long *left)
 //                             printf("Bit-Resolution: %d\n", bytes*16-16);
                                gotfmt = 1;
                        } else
-                       if (!strncmp((char *)buffer, "data", 4))
-                       {
-                               if (!gotfmt)
-                               {
+                       if (!strncmp((char *)buffer, "data", 4)) {
+                               if (!gotfmt) {
                                        close(fh);
                                        errno = 0;
                                        PERROR("File %s No fmt chunk found before data chunk.\n", filename);
                                        return(-1);
                                }
 //                             printf("Length: %ld samples (%ld.%03ld seconds)\n", chunk/bytes/channels, chunk/bytes/channels/8000, ((chunk/bytes/channels)%8000)*1000/8000);
-                               if (bytes==2 && channels==1)
-                               {
+                               if (bytes==2 && channels==1) {
                                        if (codec)
                                                *codec = CODEC_MONO;
                                        if (length)
-                                               *length = ((signed long)chunk)>>1;
+                                               *length = ((signed int)chunk)>>1;
                                        if (left)
-                                               *left = ((signed long)chunk)>>1;
+                                               *left = ((signed int)chunk)>>1;
+//                                     printf("left=%d\n",*left);
                                } else
-                               if (bytes==2 && channels==2)
-                               {
+                               if (bytes==2 && channels==2) {
                                        if (codec)
                                                *codec = CODEC_STEREO;
                                        if (length)
-                                               *length = ((signed long)chunk)>>2;
+                                               *length = ((signed int)chunk)>>2;
                                        if (left)
-                                               *left = ((signed long)chunk)>>2;
+                                               *left = ((signed int)chunk)>>2;
                                } else
-                               if (bytes==1 && channels==1)
-                               {
+                               if (bytes==1 && channels==1) {
                                        if (codec)
                                                *codec = CODEC_8BIT;
                                        if (length)
-                                               *length = (signed long)chunk;
+                                               *length = (signed int)chunk;
                                        if (left)
-                                               *left = (signed long)chunk;
-                               } else
-                               {
+                                               *left = (signed int)chunk;
+                               } else {
                                        close(fh);
                                        errno = 0;
                                        PERROR("File %s Is not MONO8, MONO16 nor STEREO16.\n", filename);
                                        return(-1);
                                }
                                return(fh);
-                       } else
-                       {
+                       } else {
 //                             PDEBUG(DEBUG_PORT, "Unknown chunk '%c%c%c%c'\n",buffer[0],buffer[1],buffer[2],buffer[3]);
-                               while(chunk > sizeof(buffer))
-                               {
-                                       read(fh, buffer, sizeof(buffer));
+                               while(chunk > sizeof(buffer)) {
+                                       ret = read(fh, buffer, sizeof(buffer));
                                        chunk -=  sizeof(buffer);
                                }
                                if (chunk)
-                                       read(fh, buffer, chunk);
+                                       ret = read(fh, buffer, chunk);
                        }
                        
                }
-               if (!gotfmt)
-               {
+               if (!gotfmt) {
                        close(fh);
                        errno = 0;
                        PERROR("File %s No fmt chunk found in file.\n", filename);
@@ -278,29 +241,31 @@ int open_tone(char *file, int *codec, signed long *length, signed long *left)
  * the len must be the number of samples, NOT for the bytes to read!!
  * the data returned is law-code
  */
-int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed long *left, int speed)
+int read_tone(int fh, unsigned char *buffer, int codec, int len, signed int size, signed int *left, int speed)
 {
-       int l;
+       int l = 0;
        int offset;
+       signed short buffer16[len], *buf16 = buffer16;
+       signed short buffer32[len<<1], *buf32 = buffer32;
+       unsigned char buffer8[len], *buf8 = buffer8;
+       signed int sample;
+       int i = 0;
 //printf("left=%ld\n",*left);
 
        /* if no *left is given (law has unknown length) */
        if (!left)
                goto unknown_length;
 
-       if (speed!=1)
-       {
+       if (speed!=1) {
                offset = ((len&(~4)) * (speed-1));
                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)*/
                *left -= offset; /* correct the current bytes left */
-               if (*left < 0)
-               {
+               if (*left < 0) {
                        /* eof */
                        *left = 0;
                        return(0);
                }
-               if (*left >= size)
-               {
+               if (*left >= size) {
                        /* eof */
                        *left = size;
                        return(0);
@@ -313,22 +278,16 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
        if (*left < len)
                len = *left;
        unknown_length:
-       switch(codec)
-       {
+       switch(codec) {
                case CODEC_LAW:
                l = read(fh, buffer, len); /* as is */
                break;
 
                case CODEC_MONO:
-                       signed short buffer16[len], *buf16 = buffer16;
-                       signed long sample;
-                       int i = 0;
                        l = read(fh, buf16, len<<1);
-                       if (l>0)
-                       {
+                       if (l>0) {
                                l = l>>1;
-                               while(i < l)
-                               {
+                               while(i < l) {
                                        sample = *buf16++;
                                        if (sample < -32767)
                                                sample = -32767;
@@ -341,47 +300,34 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
                break;
 
                case CODEC_STEREO:
-               {
-                       signed short buffer32[len<<1], *buf32 = buffer32;
-                       signed long sample;
-                       int i = 0;
-                       l = read(fh, buf32, len<<2);
-                       if (l>0)
-                       {
-                               l = l>>2;
-                               while(i < l)
-                               {
-                                       sample = (*buf32++) + (*buf32++);
-                                       if (sample < -32767)
-                                               sample = -32767;
-                                       if (sample > 32767)
-                                               sample = 32767;
-                                       *buffer++ = audio_s16_to_law[sample & 0xffff];
-                                       i++;
-                               }
+               l = read(fh, buf32, len<<2);
+               if (l>0) {
+                       l = l>>2;
+                       while(i < l) {
+                               sample = (*buf32++);
+                               sample += (*buf32++);
+                               if (sample < -32767)
+                                       sample = -32767;
+                               if (sample > 32767)
+                                       sample = 32767;
+                               *buffer++ = audio_s16_to_law[sample & 0xffff];
+                               i++;
                        }
                }
                break;
 
                case CODEC_8BIT:
-               {
-                       unsigned char buffer8[len], *buf8 = buffer8;
-                       int i = 0;
-                       l = read(fh, buf8, len);
-                       if (l>0)
-                       {
-                               while(i < l)
-                               {
-                                       *buffer++ = audio_s16_to_law[(((*buf8++)<<8)-0x8000) & 0xffff];
-                                       i++;
-                               }
+               l = read(fh, buf8, len);
+               if (l>0) {
+                       while(i < l) {
+                               *buffer++ = audio_s16_to_law[(((*buf8++)<<8)-0x8000) & 0xffff];
+                               i++;
                        }
                }
                break;
 
                default:
-               PERROR("codec %d is not supported, exitting...\n", codec);
-               exit(-1);
+               FATAL("codec %d is not supported.\n", codec);
        }
 
        if (l>0 && left)
@@ -402,19 +348,17 @@ void free_tones(void)
        void *temp;
 
        toneset_temp = toneset_first;
-       while(toneset_temp)
-       {
+       while(toneset_temp) {
                tonesettone_temp = toneset_temp->first;
-               while(tonesettone_temp)
-               {
+               while(tonesettone_temp) {
                        temp = tonesettone_temp;
                        tonesettone_temp = tonesettone_temp->next;
-                       free(temp);
+                       FREE(temp, sizeof(struct tonesettone));
                        memuse--;
                }
                temp = toneset_temp;
                toneset_temp = toneset_temp->next;
-               free(temp);
+               FREE(temp, sizeof(struct toneset));
                memuse--;
        }
        toneset_first = NULL;
@@ -434,8 +378,8 @@ int fetch_tones(void)
        char filename[256], name[256];
        int fh;
        int tone_codec;
-       signed long tone_size, tone_left;
-       unsigned long memory = 0;
+       signed int tone_size, tone_left;
+       unsigned int memory = 0;
        int samples = 0;
 
        /* if disabled */
@@ -447,13 +391,10 @@ int fetch_tones(void)
        if (*p == '\0')
                return(1);
 
-       while (*p)
-       {
+       while (*p) {
                p_next = p;
-               while(*p_next)
-               {
-                       if (*p_next == ',')
-                       {
+               while(*p_next) {
+                       if (*p_next == ',') {
                                *p_next = '\0';
                                p_next++;
                                break;
@@ -468,38 +409,28 @@ int fetch_tones(void)
                printf("PBX: Fetching tones '%s'\n", p);
                PDEBUG(DEBUG_PORT, "fetching tones directory '%s'\n", p);
 
-               *toneset_nextpointer = (struct toneset *)calloc(1, sizeof(struct toneset));
-               if (*toneset_nextpointer == NULL)
-               {
-                       PERROR("No memory for tone set: '%s'\n",p);
-                       return(0);
-               }
+               *toneset_nextpointer = (struct toneset *)MALLOC(sizeof(struct toneset));
                memuse++;
                memory += sizeof(struct toneset);
-               memset(*toneset_nextpointer, 0 , sizeof(struct toneset));
                SCPY((*toneset_nextpointer)->directory, p);
                tonesettone_nextpointer = &(*toneset_nextpointer)->first;
 
-               SPRINT(path, "%s/%s", INSTALL_DATA, p);
+               SPRINT(path, "%s/%s", SHARE_DATA, p);
                dir = opendir(path);
-               if (dir == NULL)
-               {
+               if (dir == NULL) {
                        PERROR("Tone set not found: '%s'\n", path);
                        return(0);
                }
 
-               while((dirent=readdir(dir)))
-               {
+               while((dirent=readdir(dir))) {
                        SPRINT(name, "%s", dirent->d_name);
 
                        /* remove .isdn and .wave */
-                       if (strlen(name) >= 4)
-                       {
+                       if (strlen(name) >= 4) {
                                if (!strcmp(name+strlen(name)-4, ".wav"))
                                        name[strlen(name)-4] = '\0';
                        }
-                       if (strlen(name) >= 5)
-                       {
+                       if (strlen(name) >= 5) {
                                if (!strcmp(name+strlen(name)-5, ".isdn"))
                                        name[strlen(name)-5] = '\0';
                        }
@@ -514,33 +445,23 @@ int fetch_tones(void)
 
                        /* open file */
                        fh = open_tone(filename, &tone_codec, &tone_size, &tone_left);
-                       if (fh < 0)
-                       {
+                       if (fh < 0) {
                                PERROR("Cannot open file: '%s'\n", filename);
                                continue;
                        }
                        fduse++;
 
-                       if (tone_size < 0)
-                       {
+                       if (tone_size < 0) {
                                PERROR("File has 0-length: '%s'\n", filename);
                                close(fh);
                                fduse--;
                                continue;
                        }
 
-                       /* allocate tone */
-                       *tonesettone_nextpointer = (struct tonesettone *)calloc(1, sizeof(struct tonesettone)+tone_size);
-                       if (*toneset_nextpointer == NULL)
-                       {
-                               PERROR("No memory for tone set: '%s'\n",p);
-                               close(fh);
-                               fduse--;
-                               return(0);
-                       }
+                       /* Allocate tone */
+                       *tonesettone_nextpointer = (struct tonesettone *)MALLOC(sizeof(struct tonesettone)+tone_size);
                        memuse++;
 //printf("tone:%s, %ld bytes\n", name, tone_size);
-                       memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+tone_size);
                        memory += sizeof(struct tonesettone)+tone_size;
                        samples ++;
 
@@ -560,7 +481,7 @@ int fetch_tones(void)
                p = p_next;
        }
 
-       printf("PBX: Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
+       printf("PBX: Memory used for tones: %d bytes (%d samples)\n", memory, samples);
        PDEBUG(DEBUG_PORT, "Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
 
        return(1);
@@ -570,7 +491,7 @@ int fetch_tones(void)
 /*
  * opens the fetched tone (if available)
  */
-void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length, signed long *left)
+void *open_tone_fetched(char *dir, char *file, int *codec, signed int *length, signed int *left)
 {
        struct toneset *toneset;
        struct tonesettone *tonesettone;
@@ -581,8 +502,7 @@ void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length,
 
        /* find set */
        toneset = toneset_first;
-       while(toneset)
-       {
+       while(toneset) {
 //printf("1. comparing '%s' with '%s'\n", toneset->directory, dir);
                if (!strcmp(toneset->directory, dir))
                        break;
@@ -593,8 +513,7 @@ void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length,
 
        /* find tone */
        tonesettone = toneset->first;
-       while(tonesettone)
-       {
+       while(tonesettone) {
 //printf("2. comparing '%s' with '%s'\n", tonesettone->name, file);
                if (!strcmp(tonesettone->name, file))
                        break;
@@ -619,7 +538,7 @@ void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length,
  * read from fetched tone, check size
  * the len must be the number of samples, NOT for the bytes to read!!
  */
-int read_tone_fetched(void **fetched, void *buffer, int len, signed long size, signed long *left, int speed)
+int read_tone_fetched(void **fetched, void *buffer, int len, signed int size, signed int *left, int speed)
 {
        int l;
 //printf("left=%ld\n",*left);