#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>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/sched.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
Include dependency graph for format_wav.c:
Go to the source code of this file.
Data Structures | |
struct | ast_filestream |
Defines | |
#define | BLOCKSIZE 160 |
#define | GAIN 2 |
#define | htoll(b) (b) |
#define | htols(b) (b) |
#define | ltohl(b) (b) |
#define | ltohs(b) (b) |
Functions | |
AST_MUTEX_DEFINE_STATIC (wav_lock) | |
static int | check_header (FILE *f) |
char * | description () |
Provides a description of the module. | |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module () |
Initialize the module. | |
int | unload_module () |
Cleanup all module structures, sockets, etc. | |
static int | update_header (FILE *f) |
int | usecount () |
Provides a usecount. | |
static void | wav_close (struct ast_filestream *s) |
static char * | wav_getcomment (struct ast_filestream *s) |
static struct ast_filestream * | wav_open (FILE *f) |
static struct ast_frame * | wav_read (struct ast_filestream *s, int *whennext) |
static struct ast_filestream * | wav_rewrite (FILE *f, const char *comment) |
static int | wav_seek (struct ast_filestream *fs, long sample_offset, int whence) |
static long | wav_tell (struct ast_filestream *fs) |
static int | wav_trunc (struct ast_filestream *fs) |
static int | wav_write (struct ast_filestream *fs, struct ast_frame *f) |
static int | write_header (FILE *f) |
Variables | |
static char * | desc = "Microsoft WAV format (8000hz Signed Linear)" |
static char * | exts = "wav" |
static int | glistcnt = 0 |
static char * | name = "wav" |
Definition in file format_wav.c.
|
Definition at line 76 of file format_wav.c. |
|
Definition at line 78 of file format_wav.c. Referenced by wav_read(), and wav_write(). |
|
Definition at line 81 of file format_wav.c. |
|
Definition at line 82 of file format_wav.c. |
|
Definition at line 83 of file format_wav.c. |
|
Definition at line 84 of file format_wav.c. |
|
|
|
Definition at line 103 of file format_wav.c. References ast_log(), fmt, format, LOG_WARNING, ltohl, ltohs, and type. 00104 { 00105 int type, size, formtype; 00106 int fmt, hsize; 00107 short format, chans, bysam, bisam; 00108 int bysec; 00109 int freq; 00110 int data; 00111 if (fread(&type, 1, 4, f) != 4) { 00112 ast_log(LOG_WARNING, "Read failed (type)\n"); 00113 return -1; 00114 } 00115 if (fread(&size, 1, 4, f) != 4) { 00116 ast_log(LOG_WARNING, "Read failed (size)\n"); 00117 return -1; 00118 } 00119 size = ltohl(size); 00120 if (fread(&formtype, 1, 4, f) != 4) { 00121 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00122 return -1; 00123 } 00124 if (memcmp(&type, "RIFF", 4)) { 00125 ast_log(LOG_WARNING, "Does not begin with RIFF\n"); 00126 return -1; 00127 } 00128 if (memcmp(&formtype, "WAVE", 4)) { 00129 ast_log(LOG_WARNING, "Does not contain WAVE\n"); 00130 return -1; 00131 } 00132 if (fread(&fmt, 1, 4, f) != 4) { 00133 ast_log(LOG_WARNING, "Read failed (fmt)\n"); 00134 return -1; 00135 } 00136 if (memcmp(&fmt, "fmt ", 4)) { 00137 ast_log(LOG_WARNING, "Does not say fmt\n"); 00138 return -1; 00139 } 00140 if (fread(&hsize, 1, 4, f) != 4) { 00141 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00142 return -1; 00143 } 00144 if (ltohl(hsize) < 16) { 00145 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize)); 00146 return -1; 00147 } 00148 if (fread(&format, 1, 2, f) != 2) { 00149 ast_log(LOG_WARNING, "Read failed (format)\n"); 00150 return -1; 00151 } 00152 if (ltohs(format) != 1) { 00153 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format)); 00154 return -1; 00155 } 00156 if (fread(&chans, 1, 2, f) != 2) { 00157 ast_log(LOG_WARNING, "Read failed (format)\n"); 00158 return -1; 00159 } 00160 if (ltohs(chans) != 1) { 00161 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans)); 00162 return -1; 00163 } 00164 if (fread(&freq, 1, 4, f) != 4) { 00165 ast_log(LOG_WARNING, "Read failed (freq)\n"); 00166 return -1; 00167 } 00168 if (ltohl(freq) != 8000) { 00169 ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq)); 00170 return -1; 00171 } 00172 /* Ignore the byte frequency */ 00173 if (fread(&bysec, 1, 4, f) != 4) { 00174 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n"); 00175 return -1; 00176 } 00177 /* Check bytes per sample */ 00178 if (fread(&bysam, 1, 2, f) != 2) { 00179 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n"); 00180 return -1; 00181 } 00182 if (ltohs(bysam) != 2) { 00183 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam)); 00184 return -1; 00185 } 00186 if (fread(&bisam, 1, 2, f) != 2) { 00187 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam)); 00188 return -1; 00189 } 00190 /* Skip any additional header */ 00191 if (fseek(f,ltohl(hsize)-16,SEEK_CUR) == -1 ) { 00192 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 ); 00193 return -1; 00194 } 00195 /* Skip any facts and get the first data block */ 00196 for(;;) 00197 { 00198 char buf[4]; 00199 00200 /* Begin data chunk */ 00201 if (fread(&buf, 1, 4, f) != 4) { 00202 ast_log(LOG_WARNING, "Read failed (data)\n"); 00203 return -1; 00204 } 00205 /* Data has the actual length of data in it */ 00206 if (fread(&data, 1, 4, f) != 4) { 00207 ast_log(LOG_WARNING, "Read failed (data)\n"); 00208 return -1; 00209 } 00210 data = ltohl(data); 00211 if(memcmp(buf, "data", 4) == 0 ) 00212 break; 00213 if(memcmp(buf, "fact", 4) != 0 ) { 00214 ast_log(LOG_WARNING, "Unknown block - not fact or data\n"); 00215 return -1; 00216 } 00217 if (fseek(f,data,SEEK_CUR) == -1 ) { 00218 ast_log(LOG_WARNING, "Failed to skip fact block: %d\n", data ); 00219 return -1; 00220 } 00221 } 00222 #if 0 00223 curpos = lseek(fd, 0, SEEK_CUR); 00224 truelength = lseek(fd, 0, SEEK_END); 00225 lseek(fd, curpos, SEEK_SET); 00226 truelength -= curpos; 00227 #endif 00228 return data; 00229 }
|
|
Provides a description of the module.
Definition at line 596 of file format_wav.c. 00597 { 00598 return desc; 00599 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 602 of file format_wav.c. References ASTERISK_GPL_KEY. 00603 { 00604 return ASTERISK_GPL_KEY; 00605 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 570 of file format_wav.c. References ast_format_register(), AST_FORMAT_SLINEAR, wav_close(), wav_getcomment(), wav_open(), wav_read(), wav_rewrite(), wav_seek(), wav_tell(), wav_trunc(), and wav_write(). 00571 { 00572 return ast_format_register(name, exts, AST_FORMAT_SLINEAR, 00573 wav_open, 00574 wav_rewrite, 00575 wav_write, 00576 wav_seek, 00577 wav_trunc, 00578 wav_tell, 00579 wav_read, 00580 wav_close, 00581 wav_getcomment); 00582 00583 00584 }
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 586 of file format_wav.c. References ast_format_unregister(). 00587 { 00588 return ast_format_unregister(name); 00589 }
|
|
Definition at line 231 of file format_wav.c. References ast_log(), htoll, and LOG_WARNING. 00232 { 00233 off_t cur,end; 00234 int datalen,filelen,bytes; 00235 00236 00237 cur = ftell(f); 00238 fseek(f, 0, SEEK_END); 00239 end = ftell(f); 00240 /* data starts 44 bytes in */ 00241 bytes = end - 44; 00242 datalen = htoll(bytes); 00243 /* chunk size is bytes of data plus 36 bytes of header */ 00244 filelen = htoll(36 + bytes); 00245 00246 if (cur < 0) { 00247 ast_log(LOG_WARNING, "Unable to find our position\n"); 00248 return -1; 00249 } 00250 if (fseek(f, 4, SEEK_SET)) { 00251 ast_log(LOG_WARNING, "Unable to set our position\n"); 00252 return -1; 00253 } 00254 if (fwrite(&filelen, 1, 4, f) != 4) { 00255 ast_log(LOG_WARNING, "Unable to set write file size\n"); 00256 return -1; 00257 } 00258 if (fseek(f, 40, SEEK_SET)) { 00259 ast_log(LOG_WARNING, "Unable to set our position\n"); 00260 return -1; 00261 } 00262 if (fwrite(&datalen, 1, 4, f) != 4) { 00263 ast_log(LOG_WARNING, "Unable to set write datalen\n"); 00264 return -1; 00265 } 00266 if (fseek(f, cur, SEEK_SET)) { 00267 ast_log(LOG_WARNING, "Unable to return to position\n"); 00268 return -1; 00269 } 00270 return 0; 00271 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 591 of file format_wav.c. 00592 { 00593 return glistcnt; 00594 }
|
|
Definition at line 395 of file format_wav.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), free, LOG_WARNING, and s. Referenced by load_module(). 00396 { 00397 char zero = 0; 00398 if (ast_mutex_lock(&wav_lock)) { 00399 ast_log(LOG_WARNING, "Unable to lock wav list\n"); 00400 return; 00401 } 00402 glistcnt--; 00403 ast_mutex_unlock(&wav_lock); 00404 ast_update_use_count(); 00405 /* Pad to even length */ 00406 if (s->bytes & 0x1) 00407 fwrite(&zero, 1, 1, s->f); 00408 fclose(s->f); 00409 free(s); 00410 s = NULL; 00411 }
|
|
Definition at line 565 of file format_wav.c. Referenced by load_module().
|
|
Definition at line 336 of file format_wav.c. References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), check_header(), free, LOG_WARNING, and malloc. Referenced by load_module(). 00337 { 00338 /* We don't have any header to read or anything really, but 00339 if we did, it would go here. We also might want to check 00340 and be sure it's a valid file. */ 00341 struct ast_filestream *tmp; 00342 if ((tmp = malloc(sizeof(struct ast_filestream)))) { 00343 memset(tmp, 0, sizeof(struct ast_filestream)); 00344 if ((tmp->maxlen = check_header(f)) < 0) { 00345 free(tmp); 00346 return NULL; 00347 } 00348 if (ast_mutex_lock(&wav_lock)) { 00349 ast_log(LOG_WARNING, "Unable to lock wav list\n"); 00350 free(tmp); 00351 return NULL; 00352 } 00353 tmp->f = f; 00354 tmp->needsgain = 1; 00355 tmp->fr.data = tmp->buf; 00356 tmp->fr.frametype = AST_FRAME_VOICE; 00357 tmp->fr.subclass = AST_FORMAT_SLINEAR; 00358 /* datalen will vary for each frame */ 00359 tmp->fr.src = name; 00360 tmp->fr.mallocd = 0; 00361 tmp->bytes = 0; 00362 glistcnt++; 00363 ast_mutex_unlock(&wav_lock); 00364 ast_update_use_count(); 00365 } 00366 return tmp; 00367 }
|
|
Definition at line 413 of file format_wav.c. References ast_log(), GAIN, LOG_WARNING, and s. Referenced by load_module(). 00414 { 00415 int res; 00416 int delay; 00417 int x; 00418 short tmp[sizeof(s->buf) / 2]; 00419 int bytes = sizeof(tmp); 00420 off_t here; 00421 /* Send a frame from the file to the appropriate channel */ 00422 here = ftell(s->f); 00423 if ((s->maxlen - here) < bytes) 00424 bytes = s->maxlen - here; 00425 if (bytes < 0) 00426 bytes = 0; 00427 /* ast_log(LOG_DEBUG, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */ 00428 00429 if ( (res = fread(tmp, 1, bytes, s->f)) <= 0 ) { 00430 if (res) { 00431 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); 00432 } 00433 return NULL; 00434 } 00435 00436 #if __BYTE_ORDER == __BIG_ENDIAN 00437 for( x = 0; x < sizeof(tmp)/2; x++) tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00438 #endif 00439 00440 if (s->needsgain) { 00441 for (x=0;x<sizeof(tmp)/2;x++) 00442 if (tmp[x] & ((1 << GAIN) - 1)) { 00443 /* If it has data down low, then it's not something we've artificially increased gain 00444 on, so we don't need to gain adjust it */ 00445 s->needsgain = 0; 00446 } 00447 } 00448 if (s->needsgain) { 00449 for (x=0;x<sizeof(tmp)/2;x++) { 00450 s->buf[x] = tmp[x] >> GAIN; 00451 } 00452 } else { 00453 memcpy(s->buf, tmp, sizeof(s->buf)); 00454 } 00455 00456 delay = res / 2; 00457 s->fr.frametype = AST_FRAME_VOICE; 00458 s->fr.subclass = AST_FORMAT_SLINEAR; 00459 s->fr.offset = AST_FRIENDLY_OFFSET; 00460 s->fr.datalen = res; 00461 s->fr.data = s->buf; 00462 s->fr.mallocd = 0; 00463 s->fr.samples = delay; 00464 *whennext = delay; 00465 return &s->fr; 00466 }
|
|
Definition at line 369 of file format_wav.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), free, LOG_WARNING, malloc, and write_header(). Referenced by load_module(). 00370 { 00371 /* We don't have any header to read or anything really, but 00372 if we did, it would go here. We also might want to check 00373 and be sure it's a valid file. */ 00374 struct ast_filestream *tmp; 00375 if ((tmp = malloc(sizeof(struct ast_filestream)))) { 00376 memset(tmp, 0, sizeof(struct ast_filestream)); 00377 if (write_header(f)) { 00378 free(tmp); 00379 return NULL; 00380 } 00381 if (ast_mutex_lock(&wav_lock)) { 00382 ast_log(LOG_WARNING, "Unable to lock wav list\n"); 00383 free(tmp); 00384 return NULL; 00385 } 00386 tmp->f = f; 00387 glistcnt++; 00388 ast_mutex_unlock(&wav_lock); 00389 ast_update_use_count(); 00390 } else 00391 ast_log(LOG_WARNING, "Out of memory\n"); 00392 return tmp; 00393 }
|
|
Definition at line 526 of file format_wav.c. References ast_filestream::f, offset, ast_frame::samples, and SEEK_FORCECUR. Referenced by load_module(). 00527 { 00528 off_t min,max,cur; 00529 long offset=0,samples; 00530 00531 samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */ 00532 min = 44; /* wav header is 44 bytes */ 00533 cur = ftell(fs->f); 00534 fseek(fs->f, 0, SEEK_END); 00535 max = ftell(fs->f); 00536 if (whence == SEEK_SET) 00537 offset = samples + min; 00538 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) 00539 offset = samples + cur; 00540 else if (whence == SEEK_END) 00541 offset = max - samples; 00542 if (whence != SEEK_FORCECUR) { 00543 offset = (offset > max)?max:offset; 00544 } 00545 /* always protect the header space. */ 00546 offset = (offset < min)?min:offset; 00547 return fseek(fs->f,offset,SEEK_SET); 00548 }
|
|
Definition at line 557 of file format_wav.c. References ast_filestream::f, and offset. Referenced by load_module(). 00558 { 00559 off_t offset; 00560 offset = ftell(fs->f); 00561 /* subtract header size to get samples, then divide by 2 for 16 bit samples */ 00562 return (offset - 44)/2; 00563 }
|
|
Definition at line 550 of file format_wav.c. References ast_filestream::f, and update_header(). Referenced by load_module(). 00551 { 00552 if (ftruncate(fileno(fs->f), ftell(fs->f))) 00553 return -1; 00554 return update_header(fs->f); 00555 }
|
|
Definition at line 468 of file format_wav.c. References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_filestream::buf, ast_frame::data, ast_frame::datalen, ast_filestream::f, ast_frame::frametype, GAIN, LOG_WARNING, and ast_frame::subclass. Referenced by load_module(). 00469 { 00470 int res = 0; 00471 int x; 00472 short tmp[8000], *tmpi; 00473 float tmpf; 00474 if (f->frametype != AST_FRAME_VOICE) { 00475 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00476 return -1; 00477 } 00478 if (f->subclass != AST_FORMAT_SLINEAR) { 00479 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass); 00480 return -1; 00481 } 00482 if (f->datalen > sizeof(tmp)) { 00483 ast_log(LOG_WARNING, "Data length is too long\n"); 00484 return -1; 00485 } 00486 if (!f->datalen) 00487 return -1; 00488 00489 #if 0 00490 printf("Data Length: %d\n", f->datalen); 00491 #endif 00492 00493 if (fs->buf) { 00494 tmpi = f->data; 00495 /* Volume adjust here to accomodate */ 00496 for (x=0;x<f->datalen/2;x++) { 00497 tmpf = ((float)tmpi[x]) * ((float)(1 << GAIN)); 00498 if (tmpf > 32767.0) 00499 tmpf = 32767.0; 00500 if (tmpf < -32768.0) 00501 tmpf = -32768.0; 00502 tmp[x] = tmpf; 00503 tmp[x] &= ~((1 << GAIN) - 1); 00504 00505 #if __BYTE_ORDER == __BIG_ENDIAN 00506 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00507 #endif 00508 00509 } 00510 if ((fwrite(tmp, 1, f->datalen, fs->f) != f->datalen) ) { 00511 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno)); 00512 return -1; 00513 } 00514 } else { 00515 ast_log(LOG_WARNING, "Cannot write data to file.\n"); 00516 return -1; 00517 } 00518 00519 fs->bytes += f->datalen; 00520 update_header(fs->f); 00521 00522 return 0; 00523 00524 }
|
|
Definition at line 273 of file format_wav.c. References ast_log(), fmt, htoll, htols, and LOG_WARNING. 00274 { 00275 unsigned int hz=htoll(8000); 00276 unsigned int bhz = htoll(16000); 00277 unsigned int hs = htoll(16); 00278 unsigned short fmt = htols(1); 00279 unsigned short chans = htols(1); 00280 unsigned short bysam = htols(2); 00281 unsigned short bisam = htols(16); 00282 unsigned int size = htoll(0); 00283 /* Write a wav header, ignoring sizes which will be filled in later */ 00284 fseek(f,0,SEEK_SET); 00285 if (fwrite("RIFF", 1, 4, f) != 4) { 00286 ast_log(LOG_WARNING, "Unable to write header\n"); 00287 return -1; 00288 } 00289 if (fwrite(&size, 1, 4, f) != 4) { 00290 ast_log(LOG_WARNING, "Unable to write header\n"); 00291 return -1; 00292 } 00293 if (fwrite("WAVEfmt ", 1, 8, f) != 8) { 00294 ast_log(LOG_WARNING, "Unable to write header\n"); 00295 return -1; 00296 } 00297 if (fwrite(&hs, 1, 4, f) != 4) { 00298 ast_log(LOG_WARNING, "Unable to write header\n"); 00299 return -1; 00300 } 00301 if (fwrite(&fmt, 1, 2, f) != 2) { 00302 ast_log(LOG_WARNING, "Unable to write header\n"); 00303 return -1; 00304 } 00305 if (fwrite(&chans, 1, 2, f) != 2) { 00306 ast_log(LOG_WARNING, "Unable to write header\n"); 00307 return -1; 00308 } 00309 if (fwrite(&hz, 1, 4, f) != 4) { 00310 ast_log(LOG_WARNING, "Unable to write header\n"); 00311 return -1; 00312 } 00313 if (fwrite(&bhz, 1, 4, f) != 4) { 00314 ast_log(LOG_WARNING, "Unable to write header\n"); 00315 return -1; 00316 } 00317 if (fwrite(&bysam, 1, 2, f) != 2) { 00318 ast_log(LOG_WARNING, "Unable to write header\n"); 00319 return -1; 00320 } 00321 if (fwrite(&bisam, 1, 2, f) != 2) { 00322 ast_log(LOG_WARNING, "Unable to write header\n"); 00323 return -1; 00324 } 00325 if (fwrite("data", 1, 4, f) != 4) { 00326 ast_log(LOG_WARNING, "Unable to write header\n"); 00327 return -1; 00328 } 00329 if (fwrite(&size, 1, 4, f) != 4) { 00330 ast_log(LOG_WARNING, "Unable to write header\n"); 00331 return -1; 00332 } 00333 return 0; 00334 }
|
|
Definition at line 73 of file format_wav.c. |
|
Definition at line 74 of file format_wav.c. |
|
Definition at line 70 of file format_wav.c. |
|
Definition at line 72 of file format_wav.c. |