#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 "msgsm.h"
Include dependency graph for format_wav_gsm.c:
Go to the source code of this file.
Data Structures | |
struct | ast_filestream |
Defines | |
#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 (Proprietary GSM)" |
static char * | exts = "WAV|wav49" |
static int | glistcnt = 0 |
char | msgsm_silence [] |
static char * | name = "wav49" |
Microsoft WAV format (Proprietary GSM)
Definition in file format_wav_gsm.c.
|
Definition at line 90 of file format_wav_gsm.c. |
|
Definition at line 91 of file format_wav_gsm.c. |
|
Definition at line 92 of file format_wav_gsm.c. |
|
Definition at line 93 of file format_wav_gsm.c. |
|
|
|
Definition at line 112 of file format_wav_gsm.c. References ast_log(), fmt, format, LOG_WARNING, ltohl, ltohs, and type. 00113 { 00114 int type, size, formtype; 00115 int fmt, hsize, fact; 00116 short format, chans; 00117 int freq; 00118 int data; 00119 if (fread(&type, 1, 4, f) != 4) { 00120 ast_log(LOG_WARNING, "Read failed (type)\n"); 00121 return -1; 00122 } 00123 if (fread(&size, 1, 4, f) != 4) { 00124 ast_log(LOG_WARNING, "Read failed (size)\n"); 00125 return -1; 00126 } 00127 size = ltohl(size); 00128 if (fread(&formtype, 1, 4, f) != 4) { 00129 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00130 return -1; 00131 } 00132 if (memcmp(&type, "RIFF", 4)) { 00133 ast_log(LOG_WARNING, "Does not begin with RIFF\n"); 00134 return -1; 00135 } 00136 if (memcmp(&formtype, "WAVE", 4)) { 00137 ast_log(LOG_WARNING, "Does not contain WAVE\n"); 00138 return -1; 00139 } 00140 if (fread(&fmt, 1, 4, f) != 4) { 00141 ast_log(LOG_WARNING, "Read failed (fmt)\n"); 00142 return -1; 00143 } 00144 if (memcmp(&fmt, "fmt ", 4)) { 00145 ast_log(LOG_WARNING, "Does not say fmt\n"); 00146 return -1; 00147 } 00148 if (fread(&hsize, 1, 4, f) != 4) { 00149 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00150 return -1; 00151 } 00152 if (ltohl(hsize) != 20) { 00153 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize)); 00154 return -1; 00155 } 00156 if (fread(&format, 1, 2, f) != 2) { 00157 ast_log(LOG_WARNING, "Read failed (format)\n"); 00158 return -1; 00159 } 00160 if (ltohs(format) != 49) { 00161 ast_log(LOG_WARNING, "Not a GSM file %d\n", ltohs(format)); 00162 return -1; 00163 } 00164 if (fread(&chans, 1, 2, f) != 2) { 00165 ast_log(LOG_WARNING, "Read failed (format)\n"); 00166 return -1; 00167 } 00168 if (ltohs(chans) != 1) { 00169 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans)); 00170 return -1; 00171 } 00172 if (fread(&freq, 1, 4, f) != 4) { 00173 ast_log(LOG_WARNING, "Read failed (freq)\n"); 00174 return -1; 00175 } 00176 if (ltohl(freq) != 8000) { 00177 ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq)); 00178 return -1; 00179 } 00180 /* Ignore the byte frequency */ 00181 if (fread(&freq, 1, 4, f) != 4) { 00182 ast_log(LOG_WARNING, "Read failed (X_1)\n"); 00183 return -1; 00184 } 00185 /* Ignore the two weird fields */ 00186 if (fread(&freq, 1, 4, f) != 4) { 00187 ast_log(LOG_WARNING, "Read failed (X_2/X_3)\n"); 00188 return -1; 00189 } 00190 /* Ignore the byte frequency */ 00191 if (fread(&freq, 1, 4, f) != 4) { 00192 ast_log(LOG_WARNING, "Read failed (Y_1)\n"); 00193 return -1; 00194 } 00195 /* Check for the word fact */ 00196 if (fread(&fact, 1, 4, f) != 4) { 00197 ast_log(LOG_WARNING, "Read failed (fact)\n"); 00198 return -1; 00199 } 00200 if (memcmp(&fact, "fact", 4)) { 00201 ast_log(LOG_WARNING, "Does not say fact\n"); 00202 return -1; 00203 } 00204 /* Ignore the "fact value" */ 00205 if (fread(&fact, 1, 4, f) != 4) { 00206 ast_log(LOG_WARNING, "Read failed (fact header)\n"); 00207 return -1; 00208 } 00209 if (fread(&fact, 1, 4, f) != 4) { 00210 ast_log(LOG_WARNING, "Read failed (fact value)\n"); 00211 return -1; 00212 } 00213 /* Check for the word data */ 00214 if (fread(&data, 1, 4, f) != 4) { 00215 ast_log(LOG_WARNING, "Read failed (data)\n"); 00216 return -1; 00217 } 00218 if (memcmp(&data, "data", 4)) { 00219 ast_log(LOG_WARNING, "Does not say data\n"); 00220 return -1; 00221 } 00222 /* Ignore the data length */ 00223 if (fread(&data, 1, 4, f) != 4) { 00224 ast_log(LOG_WARNING, "Read failed (data)\n"); 00225 return -1; 00226 } 00227 return 0; 00228 }
|
|
Provides a description of the module.
Definition at line 580 of file format_wav_gsm.c. References desc. 00581 { 00582 return desc; 00583 }
|
|
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 586 of file format_wav_gsm.c. References ASTERISK_GPL_KEY. 00587 { 00588 return ASTERISK_GPL_KEY; 00589 }
|
|
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 554 of file format_wav_gsm.c. References AST_FORMAT_GSM, ast_format_register(), exts, name, wav_close(), wav_getcomment(), wav_open(), wav_read(), wav_rewrite(), wav_seek(), wav_tell(), wav_trunc(), and wav_write(). 00555 { 00556 return ast_format_register(name, exts, AST_FORMAT_GSM, 00557 wav_open, 00558 wav_rewrite, 00559 wav_write, 00560 wav_seek, 00561 wav_trunc, 00562 wav_tell, 00563 wav_read, 00564 wav_close, 00565 wav_getcomment); 00566 00567 00568 }
|
|
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 570 of file format_wav_gsm.c. References ast_format_unregister(), and name. 00571 { 00572 return ast_format_unregister(name); 00573 }
|
|
Definition at line 230 of file format_wav_gsm.c. References ast_log(), htoll, and LOG_WARNING. 00231 { 00232 off_t cur,end,bytes; 00233 int datalen,filelen; 00234 00235 cur = ftell(f); 00236 fseek(f, 0, SEEK_END); 00237 end = ftell(f); 00238 /* in a gsm WAV, data starts 60 bytes in */ 00239 bytes = end - 60; 00240 datalen = htoll((bytes + 1) & ~0x1); 00241 filelen = htoll(52 + ((bytes + 1) & ~0x1)); 00242 if (cur < 0) { 00243 ast_log(LOG_WARNING, "Unable to find our position\n"); 00244 return -1; 00245 } 00246 if (fseek(f, 4, SEEK_SET)) { 00247 ast_log(LOG_WARNING, "Unable to set our position\n"); 00248 return -1; 00249 } 00250 if (fwrite(&filelen, 1, 4, f) != 4) { 00251 ast_log(LOG_WARNING, "Unable to set write file size\n"); 00252 return -1; 00253 } 00254 if (fseek(f, 56, SEEK_SET)) { 00255 ast_log(LOG_WARNING, "Unable to set our position\n"); 00256 return -1; 00257 } 00258 if (fwrite(&datalen, 1, 4, f) != 4) { 00259 ast_log(LOG_WARNING, "Unable to set write datalen\n"); 00260 return -1; 00261 } 00262 if (fseek(f, cur, SEEK_SET)) { 00263 ast_log(LOG_WARNING, "Unable to return to position\n"); 00264 return -1; 00265 } 00266 return 0; 00267 }
|
|
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 575 of file format_wav_gsm.c. References glistcnt. 00576 { 00577 return glistcnt; 00578 }
|
|
Definition at line 408 of file format_wav_gsm.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), free, LOG_WARNING, and s. 00409 { 00410 char zero = 0; 00411 if (ast_mutex_lock(&wav_lock)) { 00412 ast_log(LOG_WARNING, "Unable to lock wav list\n"); 00413 return; 00414 } 00415 glistcnt--; 00416 ast_mutex_unlock(&wav_lock); 00417 ast_update_use_count(); 00418 /* Pad to even length */ 00419 fseek(s->f, 0, SEEK_END); 00420 if (ftell(s->f) & 0x1) 00421 fwrite(&zero, 1, 1, s->f); 00422 fclose(s->f); 00423 free(s); 00424 s = NULL; 00425 }
|
|
Definition at line 549 of file format_wav_gsm.c.
|
|
Definition at line 350 of file format_wav_gsm.c. References AST_FORMAT_GSM, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), check_header(), free, LOG_WARNING, and malloc. 00351 { 00352 /* We don't have any header to read or anything really, but 00353 if we did, it would go here. We also might want to check 00354 and be sure it's a valid file. */ 00355 struct ast_filestream *tmp; 00356 if ((tmp = malloc(sizeof(struct ast_filestream)))) { 00357 memset(tmp, 0, sizeof(struct ast_filestream)); 00358 if (check_header(f)) { 00359 free(tmp); 00360 return NULL; 00361 } 00362 if (ast_mutex_lock(&wav_lock)) { 00363 ast_log(LOG_WARNING, "Unable to lock wav list\n"); 00364 free(tmp); 00365 return NULL; 00366 } 00367 tmp->f = f; 00368 tmp->fr.data = tmp->gsm; 00369 tmp->fr.frametype = AST_FRAME_VOICE; 00370 tmp->fr.subclass = AST_FORMAT_GSM; 00371 /* datalen will vary for each frame */ 00372 tmp->fr.src = name; 00373 tmp->fr.mallocd = 0; 00374 tmp->secondhalf = 0; 00375 glistcnt++; 00376 ast_mutex_unlock(&wav_lock); 00377 ast_update_use_count(); 00378 } 00379 return tmp; 00380 }
|
|
Definition at line 427 of file format_wav_gsm.c. References AST_FORMAT_GSM, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), conv65(), LOG_WARNING, and s. 00428 { 00429 int res; 00430 char msdata[66]; 00431 /* Send a frame from the file to the appropriate channel */ 00432 00433 s->fr.frametype = AST_FRAME_VOICE; 00434 s->fr.subclass = AST_FORMAT_GSM; 00435 s->fr.offset = AST_FRIENDLY_OFFSET; 00436 s->fr.samples = 160; 00437 s->fr.datalen = 33; 00438 s->fr.mallocd = 0; 00439 if (s->secondhalf) { 00440 /* Just return a frame based on the second GSM frame */ 00441 s->fr.data = s->gsm + 33; 00442 } else { 00443 if ((res = fread(msdata, 1, 65, s->f)) != 65) { 00444 if (res && (res != 1)) 00445 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); 00446 return NULL; 00447 } 00448 /* Convert from MS format to two real GSM frames */ 00449 conv65(msdata, s->gsm); 00450 s->fr.data = s->gsm; 00451 } 00452 s->secondhalf = !s->secondhalf; 00453 *whennext = 160; 00454 return &s->fr; 00455 }
|
|
Definition at line 382 of file format_wav_gsm.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), free, LOG_WARNING, malloc, and write_header(). 00383 { 00384 /* We don't have any header to read or anything really, but 00385 if we did, it would go here. We also might want to check 00386 and be sure it's a valid file. */ 00387 struct ast_filestream *tmp; 00388 if ((tmp = malloc(sizeof(struct ast_filestream)))) { 00389 memset(tmp, 0, sizeof(struct ast_filestream)); 00390 if (write_header(f)) { 00391 free(tmp); 00392 return NULL; 00393 } 00394 if (ast_mutex_lock(&wav_lock)) { 00395 ast_log(LOG_WARNING, "Unable to lock wav list\n"); 00396 free(tmp); 00397 return NULL; 00398 } 00399 tmp->f = f; 00400 glistcnt++; 00401 ast_mutex_unlock(&wav_lock); 00402 ast_update_use_count(); 00403 } else 00404 ast_log(LOG_WARNING, "Out of memory\n"); 00405 return tmp; 00406 }
|
|
Definition at line 502 of file format_wav_gsm.c. References ast_filestream::f, offset, and SEEK_FORCECUR. 00503 { 00504 off_t offset=0,distance,cur,min,max; 00505 min = 60; 00506 cur = ftell(fs->f); 00507 fseek(fs->f, 0, SEEK_END); 00508 max = ftell(fs->f); 00509 /* I'm getting sloppy here, I'm only going to go to even splits of the 2 00510 * frames, if you want tighter cuts use format_gsm, format_pcm, or format_wav */ 00511 distance = (sample_offset/320) * 65; 00512 if(whence == SEEK_SET) 00513 offset = distance + min; 00514 else if(whence == SEEK_CUR || whence == SEEK_FORCECUR) 00515 offset = distance + cur; 00516 else if(whence == SEEK_END) 00517 offset = max - distance; 00518 /* always protect against seeking past end of header */ 00519 offset = (offset < min)?min:offset; 00520 if (whence != SEEK_FORCECUR) { 00521 offset = (offset > max)?max:offset; 00522 } else if (offset > max) { 00523 int i; 00524 fseek(fs->f, 0, SEEK_END); 00525 for (i=0; i< (offset - max) / 65; i++) { 00526 fwrite(msgsm_silence, 1, 65, fs->f); 00527 } 00528 } 00529 fs->secondhalf = 0; 00530 return fseek(fs->f, offset, SEEK_SET); 00531 }
|
|
Definition at line 540 of file format_wav_gsm.c. References ast_filestream::f, and offset. 00541 { 00542 off_t offset; 00543 offset = ftell(fs->f); 00544 /* since this will most likely be used later in play or record, lets stick 00545 * to that level of resolution, just even frames boundaries */ 00546 return (offset - 52)/65*320; 00547 }
|
|
Definition at line 533 of file format_wav_gsm.c. References ast_filestream::f, and update_header(). 00534 { 00535 if (ftruncate(fileno(fs->f), ftell(fs->f))) 00536 return -1; 00537 return update_header(fs->f); 00538 }
|
|
Definition at line 457 of file format_wav_gsm.c. References AST_FORMAT_GSM, AST_FRAME_VOICE, ast_log(), conv66(), ast_frame::data, ast_frame::datalen, ast_filestream::f, ast_frame::frametype, ast_filestream::gsm, LOG_WARNING, ast_filestream::secondhalf, ast_frame::subclass, and update_header(). 00458 { 00459 int res; 00460 char msdata[66]; 00461 int len =0; 00462 int alreadyms=0; 00463 if (f->frametype != AST_FRAME_VOICE) { 00464 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00465 return -1; 00466 } 00467 if (f->subclass != AST_FORMAT_GSM) { 00468 ast_log(LOG_WARNING, "Asked to write non-GSM frame (%d)!\n", f->subclass); 00469 return -1; 00470 } 00471 if (!(f->datalen % 65)) 00472 alreadyms = 1; 00473 while(len < f->datalen) { 00474 if (alreadyms) { 00475 fs->secondhalf = 0; 00476 if ((res = fwrite(f->data + len, 1, 65, fs->f)) != 65) { 00477 ast_log(LOG_WARNING, "Bad write (%d/65): %s\n", res, strerror(errno)); 00478 return -1; 00479 } 00480 update_header(fs->f); 00481 len += 65; 00482 } else { 00483 if (fs->secondhalf) { 00484 memcpy(fs->gsm + 33, f->data + len, 33); 00485 conv66(fs->gsm, msdata); 00486 if ((res = fwrite(msdata, 1, 65, fs->f)) != 65) { 00487 ast_log(LOG_WARNING, "Bad write (%d/65): %s\n", res, strerror(errno)); 00488 return -1; 00489 } 00490 update_header(fs->f); 00491 } else { 00492 /* Copy the data and do nothing */ 00493 memcpy(fs->gsm, f->data + len, 33); 00494 } 00495 fs->secondhalf = !fs->secondhalf; 00496 len += 33; 00497 } 00498 } 00499 return 0; 00500 }
|
|
Definition at line 269 of file format_wav_gsm.c. References ast_log(), fmt, htoll, htols, and LOG_WARNING. 00270 { 00271 unsigned int hz=htoll(8000); 00272 unsigned int bhz = htoll(1625); 00273 unsigned int hs = htoll(20); 00274 unsigned short fmt = htols(49); 00275 unsigned short chans = htols(1); 00276 unsigned int fhs = htoll(4); 00277 unsigned int x_1 = htoll(65); 00278 unsigned short x_2 = htols(2); 00279 unsigned short x_3 = htols(320); 00280 unsigned int y_1 = htoll(20160); 00281 unsigned int size = htoll(0); 00282 /* Write a GSM header, ignoring sizes which will be filled in later */ 00283 if (fwrite("RIFF", 1, 4, f) != 4) { 00284 ast_log(LOG_WARNING, "Unable to write header\n"); 00285 return -1; 00286 } 00287 if (fwrite(&size, 1, 4, f) != 4) { 00288 ast_log(LOG_WARNING, "Unable to write header\n"); 00289 return -1; 00290 } 00291 if (fwrite("WAVEfmt ", 1, 8, f) != 8) { 00292 ast_log(LOG_WARNING, "Unable to write header\n"); 00293 return -1; 00294 } 00295 if (fwrite(&hs, 1, 4, f) != 4) { 00296 ast_log(LOG_WARNING, "Unable to write header\n"); 00297 return -1; 00298 } 00299 if (fwrite(&fmt, 1, 2, f) != 2) { 00300 ast_log(LOG_WARNING, "Unable to write header\n"); 00301 return -1; 00302 } 00303 if (fwrite(&chans, 1, 2, f) != 2) { 00304 ast_log(LOG_WARNING, "Unable to write header\n"); 00305 return -1; 00306 } 00307 if (fwrite(&hz, 1, 4, f) != 4) { 00308 ast_log(LOG_WARNING, "Unable to write header\n"); 00309 return -1; 00310 } 00311 if (fwrite(&bhz, 1, 4, f) != 4) { 00312 ast_log(LOG_WARNING, "Unable to write header\n"); 00313 return -1; 00314 } 00315 if (fwrite(&x_1, 1, 4, f) != 4) { 00316 ast_log(LOG_WARNING, "Unable to write header\n"); 00317 return -1; 00318 } 00319 if (fwrite(&x_2, 1, 2, f) != 2) { 00320 ast_log(LOG_WARNING, "Unable to write header\n"); 00321 return -1; 00322 } 00323 if (fwrite(&x_3, 1, 2, f) != 2) { 00324 ast_log(LOG_WARNING, "Unable to write header\n"); 00325 return -1; 00326 } 00327 if (fwrite("fact", 1, 4, f) != 4) { 00328 ast_log(LOG_WARNING, "Unable to write header\n"); 00329 return -1; 00330 } 00331 if (fwrite(&fhs, 1, 4, f) != 4) { 00332 ast_log(LOG_WARNING, "Unable to write header\n"); 00333 return -1; 00334 } 00335 if (fwrite(&y_1, 1, 4, f) != 4) { 00336 ast_log(LOG_WARNING, "Unable to write header\n"); 00337 return -1; 00338 } 00339 if (fwrite("data", 1, 4, f) != 4) { 00340 ast_log(LOG_WARNING, "Unable to write header\n"); 00341 return -1; 00342 } 00343 if (fwrite(&size, 1, 4, f) != 4) { 00344 ast_log(LOG_WARNING, "Unable to write header\n"); 00345 return -1; 00346 } 00347 return 0; 00348 }
|
|
Definition at line 86 of file format_wav_gsm.c. |
|
Definition at line 87 of file format_wav_gsm.c. |
|
Definition at line 83 of file format_wav_gsm.c. |
|
Definition at line 58 of file format_wav_gsm.c. |
|
Definition at line 85 of file format_wav_gsm.c. |