00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "asterisk.h"
00028
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00030
00031 #include <unistd.h>
00032 #include <netinet/in.h>
00033 #include <arpa/inet.h>
00034 #include <stdlib.h>
00035 #include <sys/time.h>
00036 #include <stdio.h>
00037 #include <errno.h>
00038 #include <string.h>
00039
00040 #include "asterisk/lock.h"
00041 #include "asterisk/channel.h"
00042 #include "asterisk/file.h"
00043 #include "asterisk/logger.h"
00044 #include "asterisk/sched.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/endian.h"
00047
00048
00049
00050
00051
00052 #define WAV_BUF_SIZE 320
00053
00054 struct wav_desc {
00055 int bytes;
00056 int lasttimeout;
00057 int maxlen;
00058 struct timeval last;
00059 };
00060
00061 #define BLOCKSIZE 160
00062
00063 #define GAIN 0
00064
00065
00066 #if __BYTE_ORDER == __LITTLE_ENDIAN
00067 #define htoll(b) (b)
00068 #define htols(b) (b)
00069 #define ltohl(b) (b)
00070 #define ltohs(b) (b)
00071 #else
00072 #if __BYTE_ORDER == __BIG_ENDIAN
00073 #define htoll(b) \
00074 (((((b) ) & 0xFF) << 24) | \
00075 ((((b) >> 8) & 0xFF) << 16) | \
00076 ((((b) >> 16) & 0xFF) << 8) | \
00077 ((((b) >> 24) & 0xFF) ))
00078 #define htols(b) \
00079 (((((b) ) & 0xFF) << 8) | \
00080 ((((b) >> 8) & 0xFF) ))
00081 #define ltohl(b) htoll(b)
00082 #define ltohs(b) htols(b)
00083 #else
00084 #error "Endianess not defined"
00085 #endif
00086 #endif
00087
00088
00089 static int check_header(FILE *f)
00090 {
00091 int type, size, formtype;
00092 int fmt, hsize;
00093 short format, chans, bysam, bisam;
00094 int bysec;
00095 int freq;
00096 int data;
00097 if (fread(&type, 1, 4, f) != 4) {
00098 ast_log(LOG_WARNING, "Read failed (type)\n");
00099 return -1;
00100 }
00101 if (fread(&size, 1, 4, f) != 4) {
00102 ast_log(LOG_WARNING, "Read failed (size)\n");
00103 return -1;
00104 }
00105 size = ltohl(size);
00106 if (fread(&formtype, 1, 4, f) != 4) {
00107 ast_log(LOG_WARNING, "Read failed (formtype)\n");
00108 return -1;
00109 }
00110 if (memcmp(&type, "RIFF", 4)) {
00111 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
00112 return -1;
00113 }
00114 if (memcmp(&formtype, "WAVE", 4)) {
00115 ast_log(LOG_WARNING, "Does not contain WAVE\n");
00116 return -1;
00117 }
00118 if (fread(&fmt, 1, 4, f) != 4) {
00119 ast_log(LOG_WARNING, "Read failed (fmt)\n");
00120 return -1;
00121 }
00122 if (memcmp(&fmt, "fmt ", 4)) {
00123 ast_log(LOG_WARNING, "Does not say fmt\n");
00124 return -1;
00125 }
00126 if (fread(&hsize, 1, 4, f) != 4) {
00127 ast_log(LOG_WARNING, "Read failed (formtype)\n");
00128 return -1;
00129 }
00130 if (ltohl(hsize) < 16) {
00131 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize));
00132 return -1;
00133 }
00134 if (fread(&format, 1, 2, f) != 2) {
00135 ast_log(LOG_WARNING, "Read failed (format)\n");
00136 return -1;
00137 }
00138 if (ltohs(format) != 1) {
00139 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format));
00140 return -1;
00141 }
00142 if (fread(&chans, 1, 2, f) != 2) {
00143 ast_log(LOG_WARNING, "Read failed (format)\n");
00144 return -1;
00145 }
00146 if (ltohs(chans) != 1) {
00147 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
00148 return -1;
00149 }
00150 if (fread(&freq, 1, 4, f) != 4) {
00151 ast_log(LOG_WARNING, "Read failed (freq)\n");
00152 return -1;
00153 }
00154 if (ltohl(freq) != DEFAULT_SAMPLE_RATE) {
00155 ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq));
00156 return -1;
00157 }
00158
00159 if (fread(&bysec, 1, 4, f) != 4) {
00160 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
00161 return -1;
00162 }
00163
00164 if (fread(&bysam, 1, 2, f) != 2) {
00165 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
00166 return -1;
00167 }
00168 if (ltohs(bysam) != 2) {
00169 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
00170 return -1;
00171 }
00172 if (fread(&bisam, 1, 2, f) != 2) {
00173 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
00174 return -1;
00175 }
00176
00177 if (fseek(f,ltohl(hsize)-16,SEEK_CUR) == -1 ) {
00178 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 );
00179 return -1;
00180 }
00181
00182 for(;;)
00183 {
00184 char buf[4];
00185
00186
00187 if (fread(&buf, 1, 4, f) != 4) {
00188 ast_log(LOG_WARNING, "Read failed (data)\n");
00189 return -1;
00190 }
00191
00192 if (fread(&data, 1, 4, f) != 4) {
00193 ast_log(LOG_WARNING, "Read failed (data)\n");
00194 return -1;
00195 }
00196 data = ltohl(data);
00197 if(memcmp(buf, "data", 4) == 0 )
00198 break;
00199 if(memcmp(buf, "fact", 4) != 0 ) {
00200 ast_log(LOG_WARNING, "Unknown block - not fact or data\n");
00201 return -1;
00202 }
00203 if (fseek(f,data,SEEK_CUR) == -1 ) {
00204 ast_log(LOG_WARNING, "Failed to skip fact block: %d\n", data );
00205 return -1;
00206 }
00207 }
00208 #if 0
00209 curpos = lseek(fd, 0, SEEK_CUR);
00210 truelength = lseek(fd, 0, SEEK_END);
00211 lseek(fd, curpos, SEEK_SET);
00212 truelength -= curpos;
00213 #endif
00214 return data;
00215 }
00216
00217 static int update_header(FILE *f)
00218 {
00219 off_t cur,end;
00220 int datalen,filelen,bytes;
00221
00222 cur = ftello(f);
00223 fseek(f, 0, SEEK_END);
00224 end = ftello(f);
00225
00226 bytes = end - 44;
00227 datalen = htoll(bytes);
00228
00229 filelen = htoll(36 + bytes);
00230
00231 if (cur < 0) {
00232 ast_log(LOG_WARNING, "Unable to find our position\n");
00233 return -1;
00234 }
00235 if (fseek(f, 4, SEEK_SET)) {
00236 ast_log(LOG_WARNING, "Unable to set our position\n");
00237 return -1;
00238 }
00239 if (fwrite(&filelen, 1, 4, f) != 4) {
00240 ast_log(LOG_WARNING, "Unable to set write file size\n");
00241 return -1;
00242 }
00243 if (fseek(f, 40, SEEK_SET)) {
00244 ast_log(LOG_WARNING, "Unable to set our position\n");
00245 return -1;
00246 }
00247 if (fwrite(&datalen, 1, 4, f) != 4) {
00248 ast_log(LOG_WARNING, "Unable to set write datalen\n");
00249 return -1;
00250 }
00251 if (fseeko(f, cur, SEEK_SET)) {
00252 ast_log(LOG_WARNING, "Unable to return to position\n");
00253 return -1;
00254 }
00255 return 0;
00256 }
00257
00258 static int write_header(FILE *f)
00259 {
00260 unsigned int hz=htoll(8000);
00261 unsigned int bhz = htoll(16000);
00262 unsigned int hs = htoll(16);
00263 unsigned short fmt = htols(1);
00264 unsigned short chans = htols(1);
00265 unsigned short bysam = htols(2);
00266 unsigned short bisam = htols(16);
00267 unsigned int size = htoll(0);
00268
00269 fseek(f,0,SEEK_SET);
00270 if (fwrite("RIFF", 1, 4, f) != 4) {
00271 ast_log(LOG_WARNING, "Unable to write header\n");
00272 return -1;
00273 }
00274 if (fwrite(&size, 1, 4, f) != 4) {
00275 ast_log(LOG_WARNING, "Unable to write header\n");
00276 return -1;
00277 }
00278 if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
00279 ast_log(LOG_WARNING, "Unable to write header\n");
00280 return -1;
00281 }
00282 if (fwrite(&hs, 1, 4, f) != 4) {
00283 ast_log(LOG_WARNING, "Unable to write header\n");
00284 return -1;
00285 }
00286 if (fwrite(&fmt, 1, 2, f) != 2) {
00287 ast_log(LOG_WARNING, "Unable to write header\n");
00288 return -1;
00289 }
00290 if (fwrite(&chans, 1, 2, f) != 2) {
00291 ast_log(LOG_WARNING, "Unable to write header\n");
00292 return -1;
00293 }
00294 if (fwrite(&hz, 1, 4, f) != 4) {
00295 ast_log(LOG_WARNING, "Unable to write header\n");
00296 return -1;
00297 }
00298 if (fwrite(&bhz, 1, 4, f) != 4) {
00299 ast_log(LOG_WARNING, "Unable to write header\n");
00300 return -1;
00301 }
00302 if (fwrite(&bysam, 1, 2, f) != 2) {
00303 ast_log(LOG_WARNING, "Unable to write header\n");
00304 return -1;
00305 }
00306 if (fwrite(&bisam, 1, 2, f) != 2) {
00307 ast_log(LOG_WARNING, "Unable to write header\n");
00308 return -1;
00309 }
00310 if (fwrite("data", 1, 4, f) != 4) {
00311 ast_log(LOG_WARNING, "Unable to write header\n");
00312 return -1;
00313 }
00314 if (fwrite(&size, 1, 4, f) != 4) {
00315 ast_log(LOG_WARNING, "Unable to write header\n");
00316 return -1;
00317 }
00318 return 0;
00319 }
00320
00321 static int wav_open(struct ast_filestream *s)
00322 {
00323
00324
00325
00326 struct wav_desc *tmp = (struct wav_desc *)s->private;
00327 if ((tmp->maxlen = check_header(s->f)) < 0)
00328 return -1;
00329 return 0;
00330 }
00331
00332 static int wav_rewrite(struct ast_filestream *s, const char *comment)
00333 {
00334
00335
00336
00337
00338 if (write_header(s->f))
00339 return -1;
00340 return 0;
00341 }
00342
00343 static void wav_close(struct ast_filestream *s)
00344 {
00345 char zero = 0;
00346 struct wav_desc *fs = (struct wav_desc *)s->private;
00347
00348 if (fs->bytes & 0x1)
00349 fwrite(&zero, 1, 1, s->f);
00350 }
00351
00352 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
00353 {
00354 int res;
00355 int samples;
00356 short *tmp;
00357 int bytes = WAV_BUF_SIZE;
00358 off_t here;
00359
00360 struct wav_desc *fs = (struct wav_desc *)s->private;
00361
00362 here = ftello(s->f);
00363 if (fs->maxlen - here < bytes)
00364 bytes = fs->maxlen - here;
00365 if (bytes < 0)
00366 bytes = 0;
00367
00368 s->fr.frametype = AST_FRAME_VOICE;
00369 s->fr.subclass = AST_FORMAT_SLINEAR;
00370 s->fr.mallocd = 0;
00371 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
00372
00373 if ( (res = fread(s->fr.data, 1, s->fr.datalen, s->f)) <= 0 ) {
00374 if (res)
00375 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00376 return NULL;
00377 }
00378 s->fr.datalen = res;
00379 s->fr.samples = samples = res / 2;
00380
00381 tmp = (short *)(s->fr.data);
00382 #if __BYTE_ORDER == __BIG_ENDIAN
00383
00384 for( x = 0; x < samples; x++)
00385 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
00386 #endif
00387 *whennext = samples;
00388 return &s->fr;
00389 }
00390
00391 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
00392 {
00393 int x;
00394 short tmp[8000], *tmpi;
00395 struct wav_desc *s = (struct wav_desc *)fs->private;
00396 int res;
00397
00398 if (f->frametype != AST_FRAME_VOICE) {
00399 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00400 return -1;
00401 }
00402 if (f->subclass != AST_FORMAT_SLINEAR) {
00403 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass);
00404 return -1;
00405 }
00406 if (f->datalen > sizeof(tmp)) {
00407 ast_log(LOG_WARNING, "Data length is too long\n");
00408 return -1;
00409 }
00410 if (!f->datalen)
00411 return -1;
00412
00413 #if 0
00414 printf("Data Length: %d\n", f->datalen);
00415 #endif
00416
00417 tmpi = f->data;
00418
00419 for (x=0;x<f->datalen/2;x++) {
00420 tmp[x] = tmpi[x];
00421 #if __BYTE_ORDER == __BIG_ENDIAN
00422 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
00423 #endif
00424 }
00425 if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
00426 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
00427 return -1;
00428 }
00429
00430 s->bytes += f->datalen;
00431 update_header(fs->f);
00432
00433 return 0;
00434
00435 }
00436
00437 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00438 {
00439 off_t min, max, cur, offset = 0, samples;
00440
00441 samples = sample_offset * 2;
00442 min = 44;
00443 cur = ftello(fs->f);
00444 fseeko(fs->f, 0, SEEK_END);
00445 max = ftello(fs->f);
00446 if (whence == SEEK_SET)
00447 offset = samples + min;
00448 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00449 offset = samples + cur;
00450 else if (whence == SEEK_END)
00451 offset = max - samples;
00452 if (whence != SEEK_FORCECUR) {
00453 offset = (offset > max)?max:offset;
00454 }
00455
00456 offset = (offset < min)?min:offset;
00457 return fseeko(fs->f, offset, SEEK_SET);
00458 }
00459
00460 static int wav_trunc(struct ast_filestream *fs)
00461 {
00462 if (ftruncate(fileno(fs->f), ftello(fs->f)))
00463 return -1;
00464 return update_header(fs->f);
00465 }
00466
00467 static off_t wav_tell(struct ast_filestream *fs)
00468 {
00469 off_t offset;
00470 offset = ftello(fs->f);
00471
00472 return (offset - 44)/2;
00473 }
00474
00475 static const struct ast_format wav_f = {
00476 .name = "wav",
00477 .exts = "wav",
00478 .format = AST_FORMAT_SLINEAR,
00479 .open = wav_open,
00480 .rewrite = wav_rewrite,
00481 .write = wav_write,
00482 .seek = wav_seek,
00483 .trunc = wav_trunc,
00484 .tell = wav_tell,
00485 .read = wav_read,
00486 .close = wav_close,
00487 .buf_size = WAV_BUF_SIZE + AST_FRIENDLY_OFFSET,
00488 .desc_size = sizeof(struct wav_desc),
00489 };
00490
00491 static int load_module(void)
00492 {
00493 return ast_format_register(&wav_f);
00494 }
00495
00496 static int unload_module(void)
00497 {
00498 return ast_format_unregister(wav_f.name);
00499 }
00500
00501 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Microsoft WAV format (8000Hz Signed Linear)");