Avoid cppcheck warnings; removing unused vars and a bit of cleanup.
[asterisk/asterisk.git] / formats / format_wav_gsm.c
index d2fa1c0..35d4339 100644 (file)
  * e-mail attachments mainly.
  * \ingroup formats
  */
-#include <unistd.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
 
+/*** MODULEINFO
+       <support_level>core</support_level>
+ ***/
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "asterisk/lock.h"
-#include "asterisk/channel.h"
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/sched.h"
+#include "asterisk/mod_format.h"
 #include "asterisk/module.h"
 #include "asterisk/endian.h"
 
@@ -56,12 +47,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define        GSM_FRAME_SIZE  33
 #define        MSGSM_FRAME_SIZE        65
-#define        MSGSM_DATA_OFS          60      /* offset of data bytes */
+#define        MSGSM_DATA_OFFSET               60      /* offset of data bytes */
 #define        GSM_SAMPLES             160     /* samples in a GSM block */
 #define        MSGSM_SAMPLES           (2*GSM_SAMPLES) /* samples in an MSGSM block */
 
 /* begin binary data: */
-char msgsm_silence[] = /* 65 */
+static char msgsm_silence[] = /* 65 */
 {0x48,0x17,0xD6,0x84,0x02,0x80,0x24,0x49,0x92,0x24,0x89,0x02,0x80,0x24,0x49
 ,0x92,0x24,0x89,0x02,0x80,0x24,0x49,0x92,0x24,0x89,0x02,0x80,0x24,0x49,0x92
 ,0x24,0x09,0x82,0x74,0x61,0x4D,0x28,0x00,0x48,0x92,0x24,0x49,0x92,0x28,0x00
@@ -163,7 +154,7 @@ static int check_header(FILE *f)
                return -1;
        }
        if (ltohl(freq) != DEFAULT_SAMPLE_RATE) {
-               ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq));
+               ast_log(LOG_WARNING, "Unexpected frequency %d\n", ltohl(freq));
                return -1;
        }
        /* Ignore the byte frequency */
@@ -219,15 +210,16 @@ static int check_header(FILE *f)
 static int update_header(FILE *f)
 {
        off_t cur,end,bytes;
-       int datalen,filelen;
-       
+       int datalen, filelen, samples;
+
        cur = ftello(f);
        fseek(f, 0, SEEK_END);
        end = ftello(f);
        /* in a gsm WAV, data starts 60 bytes in */
-       bytes = end - MSGSM_DATA_OFS;
-       datalen = htoll((bytes + 1) & ~0x1);
-       filelen = htoll(52 + ((bytes + 1) & ~0x1));
+       bytes = end - MSGSM_DATA_OFFSET;
+       samples = htoll(bytes / MSGSM_FRAME_SIZE * MSGSM_SAMPLES);
+       datalen = htoll(bytes);
+       filelen = htoll(MSGSM_DATA_OFFSET - 8 + bytes);
        if (cur < 0) {
                ast_log(LOG_WARNING, "Unable to find our position\n");
                return -1;
@@ -237,7 +229,15 @@ static int update_header(FILE *f)
                return -1;
        }
        if (fwrite(&filelen, 1, 4, f) != 4) {
-               ast_log(LOG_WARNING, "Unable to set write file size\n");
+               ast_log(LOG_WARNING, "Unable to write file size\n");
+               return -1;
+       }
+       if (fseek(f, 48, SEEK_SET)) {
+               ast_log(LOG_WARNING, "Unable to set our position\n");
+               return -1;
+       }
+       if (fwrite(&samples, 1, 4, f) != 4) {
+               ast_log(LOG_WARNING, "Unable to write samples\n");
                return -1;
        }
        if (fseek(f, 56, SEEK_SET)) {
@@ -245,7 +245,7 @@ static int update_header(FILE *f)
                return -1;
        }
        if (fwrite(&datalen, 1, 4, f) != 4) {
-               ast_log(LOG_WARNING, "Unable to set write datalen\n");
+               ast_log(LOG_WARNING, "Unable to write datalen\n");
                return -1;
        }
        if (fseeko(f, cur, SEEK_SET)) {
@@ -257,78 +257,111 @@ static int update_header(FILE *f)
 
 static int write_header(FILE *f)
 {
-       unsigned int hz=htoll(DEFAULT_SAMPLE_RATE);     /* XXX the following are relate to DEFAULT_SAMPLE_RATE ? */
-       unsigned int bhz = htoll(1625);
-       unsigned int hs = htoll(20);
+       /* Samples per second (always 8000 for this format). */
+       unsigned int sample_rate = htoll(8000);
+       /* Bytes per second (always 1625 for this format). */
+       unsigned int byte_sample_rate = htoll(1625);
+       /* This is the size of the "fmt " subchunk */
+       unsigned int fmtsize = htoll(20);
+       /* WAV #49 */
        unsigned short fmt = htols(49);
+       /* Mono = 1 channel */
        unsigned short chans = htols(1);
-       unsigned int fhs = htoll(4);
-       unsigned int x_1 = htoll(65);
-       unsigned short x_2 = htols(2);
-       unsigned short x_3 = htols(320);
-       unsigned int y_1 = htoll(20160);
+       /* Each block of data is exactly 65 bytes in size. */
+       unsigned int block_align = htoll(MSGSM_FRAME_SIZE);
+       /* Not actually 2, but rounded up to the nearest bit */
+       unsigned short bits_per_sample = htols(2);
+       /* Needed for compressed formats */
+       unsigned short extra_format = htols(MSGSM_SAMPLES);
+       /* This is the size of the "fact" subchunk */
+       unsigned int factsize = htoll(4);
+       /* Number of samples in the data chunk */
+       unsigned int num_samples = htoll(0);
+       /* Number of bytes in the data chunk */
        unsigned int size = htoll(0);
        /* Write a GSM header, ignoring sizes which will be filled in later */
+
+       /*  0: Chunk ID */
        if (fwrite("RIFF", 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
+       /*  4: Chunk Size */
        if (fwrite(&size, 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
+       /*  8: Chunk Format */
+       if (fwrite("WAVE", 1, 4, f) != 4) {
+               ast_log(LOG_WARNING, "Unable to write header\n");
+               return -1;
+       }
+       /* 12: Subchunk 1: ID */
+       if (fwrite("fmt ", 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite(&hs, 1, 4, f) != 4) {
+       /* 16: Subchunk 1: Size (minus 8) */
+       if (fwrite(&fmtsize, 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
+       /* 20: Subchunk 1: Audio format (49) */
        if (fwrite(&fmt, 1, 2, f) != 2) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
+       /* 22: Subchunk 1: Number of channels */
        if (fwrite(&chans, 1, 2, f) != 2) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite(&hz, 1, 4, f) != 4) {
+       /* 24: Subchunk 1: Sample rate */
+       if (fwrite(&sample_rate, 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite(&bhz, 1, 4, f) != 4) {
+       /* 28: Subchunk 1: Byte rate */
+       if (fwrite(&byte_sample_rate, 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite(&x_1, 1, 4, f) != 4) {
+       /* 32: Subchunk 1: Block align */
+       if (fwrite(&block_align, 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite(&x_2, 1, 2, f) != 2) {
+       /* 36: Subchunk 1: Bits per sample */
+       if (fwrite(&bits_per_sample, 1, 2, f) != 2) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite(&x_3, 1, 2, f) != 2) {
+       /* 38: Subchunk 1: Extra format bytes */
+       if (fwrite(&extra_format, 1, 2, f) != 2) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
+       /* 40: Subchunk 2: ID */
        if (fwrite("fact", 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite(&fhs, 1, 4, f) != 4) {
+       /* 44: Subchunk 2: Size (minus 8) */
+       if (fwrite(&factsize, 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
-       if (fwrite(&y_1, 1, 4, f) != 4) {
+       /* 48: Subchunk 2: Number of samples */
+       if (fwrite(&num_samples, 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
+       /* 52: Subchunk 3: ID */
        if (fwrite("data", 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
        }
+       /* 56: Subchunk 3: Size */
        if (fwrite(&size, 1, 4, f) != 4) {
                ast_log(LOG_WARNING, "Unable to write header\n");
                return -1;
@@ -341,7 +374,7 @@ static int wav_open(struct ast_filestream *s)
        /* We don't have any header to read or anything really, but
           if we did, it would go here.  We also might want to check
           and be sure it's a valid file.  */
-       struct wavg_desc *fs = (struct wavg_desc *)s->private;
+       struct wavg_desc *fs = (struct wavg_desc *)s->_private;
 
        if (check_header(s->f))
                return -1;
@@ -360,33 +393,24 @@ static int wav_rewrite(struct ast_filestream *s, const char *comment)
        return 0;
 }
 
-static void wav_close(struct ast_filestream *s)
-{
-       char zero = 0;
-       /* Pad to even length */
-       fseek(s->f, 0, SEEK_END);
-       if (ftello(s->f) & 0x1)
-               fwrite(&zero, 1, 1, s->f);
-}
-
 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
 {
        /* Send a frame from the file to the appropriate channel */
-       struct wavg_desc *fs = (struct wavg_desc *)s->private;
+       struct wavg_desc *fs = (struct wavg_desc *)s->_private;
 
        s->fr.frametype = AST_FRAME_VOICE;
-       s->fr.subclass = AST_FORMAT_GSM;
+       ast_format_set(&s->fr.subclass.format, AST_FORMAT_GSM, 0);
        s->fr.offset = AST_FRIENDLY_OFFSET;
        s->fr.samples = GSM_SAMPLES;
        s->fr.mallocd = 0;
        AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, GSM_FRAME_SIZE);
        if (fs->secondhalf) {
                /* Just return a frame based on the second GSM frame */
-               s->fr.data = (char *)s->fr.data + GSM_FRAME_SIZE;
+               s->fr.data.ptr = (char *)s->fr.data.ptr + GSM_FRAME_SIZE;
                s->fr.offset += GSM_FRAME_SIZE;
        } else {
                /* read and convert */
-               char msdata[MSGSM_FRAME_SIZE];
+               unsigned char msdata[MSGSM_FRAME_SIZE];
                int res;
                
                if ((res = fread(msdata, 1, MSGSM_FRAME_SIZE, s->f)) != MSGSM_FRAME_SIZE) {
@@ -395,7 +419,7 @@ static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
                        return NULL;
                }
                /* Convert from MS format to two real GSM frames */
-               conv65(msdata, s->fr.data);
+               conv65(msdata, s->fr.data.ptr);
        }
        fs->secondhalf = !fs->secondhalf;
        *whennext = GSM_SAMPLES;
@@ -406,14 +430,14 @@ static int wav_write(struct ast_filestream *s, struct ast_frame *f)
 {
        int len;
        int size;
-       struct wavg_desc *fs = (struct wavg_desc *)s->private;
+       struct wavg_desc *fs = (struct wavg_desc *)s->_private;
 
        if (f->frametype != AST_FRAME_VOICE) {
                ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
                return -1;
        }
-       if (f->subclass != AST_FORMAT_GSM) {
-               ast_log(LOG_WARNING, "Asked to write non-GSM frame (%d)!\n", f->subclass);
+       if (f->subclass.format.id != AST_FORMAT_GSM) {
+               ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(&f->subclass.format));
                return -1;
        }
        /* XXX this might fail... if the input is a multiple of MSGSM_FRAME_SIZE
@@ -427,20 +451,20 @@ static int wav_write(struct ast_filestream *s, struct ast_frame *f)
        }
        for (len = 0; len < f->datalen ; len += size) {
                int res;
-               char *src, msdata[MSGSM_FRAME_SIZE];
+               unsigned char *src, msdata[MSGSM_FRAME_SIZE];
                if (fs->secondhalf) {   /* second half of raw gsm to be converted */
-                       memcpy(s->buf + GSM_FRAME_SIZE, f->data + len, GSM_FRAME_SIZE);
-                       conv66(s->buf, msdata);
+                       memcpy(s->buf + GSM_FRAME_SIZE, f->data.ptr + len, GSM_FRAME_SIZE);
+                       conv66((unsigned char *) s->buf, msdata);
                        src = msdata;
                        fs->secondhalf = 0;
                } else if (size == GSM_FRAME_SIZE) {    /* first half of raw gsm */
-                       memcpy(s->buf, f->data + len, GSM_FRAME_SIZE);
+                       memcpy(s->buf, f->data.ptr + len, GSM_FRAME_SIZE);
                        src = NULL;     /* nothing to write */
                        fs->secondhalf = 1;
                } else {        /* raw msgsm data */
-                       src = f->data + len;
+                       src = f->data.ptr + len;
                }
-               if (src && (res = fwrite(src, 1, size, s->f)) != size) {
+               if (src && (res = fwrite(src, 1, MSGSM_FRAME_SIZE, s->f)) != MSGSM_FRAME_SIZE) {
                        ast_log(LOG_WARNING, "Bad write (%d/65): %s\n", res, strerror(errno));
                        return -1;
                }
@@ -452,9 +476,9 @@ static int wav_write(struct ast_filestream *s, struct ast_frame *f)
 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
 {
        off_t offset=0, distance, max;
-       struct wavg_desc *s = (struct wavg_desc *)fs->private;
+       struct wavg_desc *s = (struct wavg_desc *)fs->_private;
 
-       off_t min = MSGSM_DATA_OFS;
+       off_t min = MSGSM_DATA_OFFSET;
        off_t cur = ftello(fs->f);
        fseek(fs->f, 0, SEEK_END);
        max = ftello(fs->f);    /* XXX ideally, should round correctly */
@@ -476,7 +500,9 @@ static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
                int i;
                fseek(fs->f, 0, SEEK_END);
                for (i=0; i< (offset - max) / MSGSM_FRAME_SIZE; i++) {
-                       fwrite(msgsm_silence, 1, MSGSM_FRAME_SIZE, fs->f);
+                       if (!fwrite(msgsm_silence, 1, MSGSM_FRAME_SIZE, fs->f)) {
+                               ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
+                       }
                }
        }
        s->secondhalf = 0;
@@ -496,16 +522,12 @@ static off_t wav_tell(struct ast_filestream *fs)
        offset = ftello(fs->f);
        /* since this will most likely be used later in play or record, lets stick
         * to that level of resolution, just even frames boundaries */
-       /* XXX why 52 ? */
-       return (offset - 52)/MSGSM_FRAME_SIZE*MSGSM_SAMPLES;
+       return (offset - MSGSM_DATA_OFFSET)/MSGSM_FRAME_SIZE*MSGSM_SAMPLES;
 }
 
-static struct ast_format_lock me = { .usecnt = -1 };
-
-static const struct ast_format wav49_f = {
+static struct ast_format_def wav49_f = {
        .name = "wav49",
        .exts = "WAV|wav49",
-       .format = AST_FORMAT_GSM,
        .open = wav_open,
        .rewrite = wav_rewrite,
        .write = wav_write,
@@ -513,33 +535,25 @@ static const struct ast_format wav49_f = {
        .trunc = wav_trunc,
        .tell = wav_tell,
        .read = wav_read,
-       .close = wav_close,
        .buf_size = 2*GSM_FRAME_SIZE + AST_FRIENDLY_OFFSET,
        .desc_size = sizeof(struct wavg_desc),
-       .lockp = &me,
 };
 
-int load_module()
+static int load_module(void)
 {
-       return ast_format_register(&wav49_f);
+       ast_format_set(&wav49_f.format, AST_FORMAT_GSM, 0);
+       if (ast_format_def_register(&wav49_f))
+               return AST_MODULE_LOAD_FAILURE;
+       return AST_MODULE_LOAD_SUCCESS;
 }
 
-int unload_module()
-{
-       return ast_format_unregister(wav49_f.name);
-}      
-
-int usecount()
+static int unload_module(void)
 {
-       return me.usecnt;
+       return ast_format_def_unregister(wav49_f.name);
 }
 
-const char *description()
-{
-       return "Microsoft WAV format (Proprietary GSM)";
-}
-
-const char *key()
-{
-       return ASTERISK_GPL_KEY;
-}
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Microsoft WAV format (Proprietary GSM)",
+       .load = load_module,
+       .unload = unload_module,
+       .load_pri = AST_MODPRI_APP_DEPEND
+);