2 * Asterisk -- A telephony toolkit for Linux.
4 * Save GSM in the proprietary Microsoft format.
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
14 #include <asterisk/channel.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/sched.h>
18 #include <asterisk/module.h>
19 #include <arpa/inet.h>
30 /* Some Ideas for this code came from makewave.c by Jeffery Chilton */
32 /* Portions of the conversion code are by guido@sienanet.it */
34 struct ast_filestream {
35 void *reserved[AST_RESERVED_POINTERS];
36 /* Believe it or not, we must decode/recode to account for the
38 /* This is what a filestream means to us */
39 int fd; /* Descriptor */
41 struct ast_channel *owner;
42 struct ast_frame fr; /* Frame information */
43 char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
44 char empty; /* Empty character */
45 unsigned char gsm[66]; /* Two Real GSM Frames */
47 int secondhalf; /* Are we on the second half */
51 struct ast_filestream *next;
55 static struct ast_filestream *glist = NULL;
56 static pthread_mutex_t wav_lock = PTHREAD_MUTEX_INITIALIZER;
57 static int glistcnt = 0;
59 static char *name = "wav49";
60 static char *desc = "Microsoft WAV format (Proprietary GSM)";
61 static char *exts = "WAV";
63 #if __BYTE_ORDER == __LITTLE_ENDIAN
69 #if __BYTE_ORDER == __BIG_ENDIAN
71 (((((b) ) & 0xFF) << 24) | \
72 ((((b) >> 8) & 0xFF) << 16) | \
73 ((((b) >> 16) & 0xFF) << 8) | \
74 ((((b) >> 24) & 0xFF) ))
76 (((((b) ) & 0xFF) << 8) | \
77 ((((b) >> 8) & 0xFF) ))
78 #define ltohl(b) htoll(b)
79 #define ltohs(b) htols(b)
81 #error "Endianess not defined"
86 static int check_header(int fd)
88 int type, size, formtype;
93 if (read(fd, &type, 4) != 4) {
94 ast_log(LOG_WARNING, "Read failed (type)\n");
97 if (read(fd, &size, 4) != 4) {
98 ast_log(LOG_WARNING, "Read failed (size)\n");
102 if (read(fd, &formtype, 4) != 4) {
103 ast_log(LOG_WARNING, "Read failed (formtype)\n");
106 if (memcmp(&type, "RIFF", 4)) {
107 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
110 if (memcmp(&formtype, "WAVE", 4)) {
111 ast_log(LOG_WARNING, "Does not contain WAVE\n");
114 if (read(fd, &fmt, 4) != 4) {
115 ast_log(LOG_WARNING, "Read failed (fmt)\n");
118 if (memcmp(&fmt, "fmt ", 4)) {
119 ast_log(LOG_WARNING, "Does not say fmt\n");
122 if (read(fd, &hsize, 4) != 4) {
123 ast_log(LOG_WARNING, "Read failed (formtype)\n");
126 if (ltohl(hsize) != 20) {
127 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize));
130 if (read(fd, &format, 2) != 2) {
131 ast_log(LOG_WARNING, "Read failed (format)\n");
134 if (ltohs(format) != 49) {
135 ast_log(LOG_WARNING, "Not a GSM file %d\n", ltohs(format));
138 if (read(fd, &chans, 2) != 2) {
139 ast_log(LOG_WARNING, "Read failed (format)\n");
142 if (ltohs(chans) != 1) {
143 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
146 if (read(fd, &freq, 4) != 4) {
147 ast_log(LOG_WARNING, "Read failed (freq)\n");
150 if (ltohl(freq) != 8000) {
151 ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq));
154 /* Ignore the byte frequency */
155 if (read(fd, &freq, 4) != 4) {
156 ast_log(LOG_WARNING, "Read failed (X_1)\n");
159 /* Ignore the two weird fields */
160 if (read(fd, &freq, 4) != 4) {
161 ast_log(LOG_WARNING, "Read failed (X_2/X_3)\n");
164 /* Ignore the byte frequency */
165 if (read(fd, &freq, 4) != 4) {
166 ast_log(LOG_WARNING, "Read failed (Y_1)\n");
169 /* Check for the word fact */
170 if (read(fd, &fact, 4) != 4) {
171 ast_log(LOG_WARNING, "Read failed (fact)\n");
174 if (memcmp(&fact, "fact", 4)) {
175 ast_log(LOG_WARNING, "Does not say fact\n");
178 /* Ignore the "fact value" */
179 if (read(fd, &fact, 4) != 4) {
180 ast_log(LOG_WARNING, "Read failed (fact header)\n");
183 if (read(fd, &fact, 4) != 4) {
184 ast_log(LOG_WARNING, "Read failed (fact value)\n");
187 /* Check for the word data */
188 if (read(fd, &data, 4) != 4) {
189 ast_log(LOG_WARNING, "Read failed (data)\n");
192 if (memcmp(&data, "data", 4)) {
193 ast_log(LOG_WARNING, "Does not say data\n");
196 /* Ignore the data length */
197 if (read(fd, &data, 4) != 4) {
198 ast_log(LOG_WARNING, "Read failed (data)\n");
204 static int update_header(int fd, int bytes)
207 int datalen = htoll(bytes);
208 int filelen = htoll(52 + ((bytes + 1) & ~0x1));
209 cur = lseek(fd, 0, SEEK_CUR);
211 ast_log(LOG_WARNING, "Unable to find our position\n");
214 if (lseek(fd, 4, SEEK_SET) != 4) {
215 ast_log(LOG_WARNING, "Unable to set our position\n");
218 if (write(fd, &filelen, 4) != 4) {
219 ast_log(LOG_WARNING, "Unable to set write file size\n");
222 if (lseek(fd, 56, SEEK_SET) != 56) {
223 ast_log(LOG_WARNING, "Unable to set our position\n");
226 if (write(fd, &datalen, 4) != 4) {
227 ast_log(LOG_WARNING, "Unable to set write datalen\n");
230 if (lseek(fd, cur, SEEK_SET) != cur) {
231 ast_log(LOG_WARNING, "Unable to return to position\n");
237 static int write_header(int fd)
239 unsigned int hz=htoll(8000);
240 unsigned int bhz = htoll(1625);
241 unsigned int hs = htoll(20);
242 unsigned short fmt = htols(49);
243 unsigned short chans = htols(1);
244 unsigned int fhs = htoll(4);
245 unsigned int x_1 = htoll(65);
246 unsigned short x_2 = htols(2);
247 unsigned short x_3 = htols(320);
248 unsigned int y_1 = htoll(20160);
249 unsigned int size = htoll(0);
250 /* Write a GSM header, ignoring sizes which will be filled in later */
251 if (write(fd, "RIFF", 4) != 4) {
252 ast_log(LOG_WARNING, "Unable to write header\n");
255 if (write(fd, &size, 4) != 4) {
256 ast_log(LOG_WARNING, "Unable to write header\n");
259 if (write(fd, "WAVEfmt ", 8) != 8) {
260 ast_log(LOG_WARNING, "Unable to write header\n");
263 if (write(fd, &hs, 4) != 4) {
264 ast_log(LOG_WARNING, "Unable to write header\n");
267 if (write(fd, &fmt, 2) != 2) {
268 ast_log(LOG_WARNING, "Unable to write header\n");
271 if (write(fd, &chans, 2) != 2) {
272 ast_log(LOG_WARNING, "Unable to write header\n");
275 if (write(fd, &hz, 4) != 4) {
276 ast_log(LOG_WARNING, "Unable to write header\n");
279 if (write(fd, &bhz, 4) != 4) {
280 ast_log(LOG_WARNING, "Unable to write header\n");
283 if (write(fd, &x_1, 4) != 4) {
284 ast_log(LOG_WARNING, "Unable to write header\n");
287 if (write(fd, &x_2, 2) != 2) {
288 ast_log(LOG_WARNING, "Unable to write header\n");
291 if (write(fd, &x_3, 2) != 2) {
292 ast_log(LOG_WARNING, "Unable to write header\n");
295 if (write(fd, "fact", 4) != 4) {
296 ast_log(LOG_WARNING, "Unable to write header\n");
299 if (write(fd, &fhs, 4) != 4) {
300 ast_log(LOG_WARNING, "Unable to write header\n");
303 if (write(fd, &y_1, 4) != 4) {
304 ast_log(LOG_WARNING, "Unable to write header\n");
307 if (write(fd, "data", 4) != 4) {
308 ast_log(LOG_WARNING, "Unable to write header\n");
311 if (write(fd, &size, 4) != 4) {
312 ast_log(LOG_WARNING, "Unable to write header\n");
318 static struct ast_filestream *wav_open(int fd)
320 /* We don't have any header to read or anything really, but
321 if we did, it would go here. We also might want to check
322 and be sure it's a valid file. */
323 struct ast_filestream *tmp;
324 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
325 memset(tmp, 0, sizeof(struct ast_filestream));
326 if (check_header(fd)) {
330 if (pthread_mutex_lock(&wav_lock)) {
331 ast_log(LOG_WARNING, "Unable to lock wav list\n");
339 tmp->fr.data = tmp->gsm;
340 tmp->fr.frametype = AST_FRAME_VOICE;
341 tmp->fr.subclass = AST_FORMAT_GSM;
342 /* datalen will vary for each frame */
346 tmp->lasttimeout = -1;
348 pthread_mutex_unlock(&wav_lock);
349 ast_update_use_count();
354 static struct ast_filestream *wav_rewrite(int fd, char *comment)
356 /* We don't have any header to read or anything really, but
357 if we did, it would go here. We also might want to check
358 and be sure it's a valid file. */
359 struct ast_filestream *tmp;
360 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
361 memset(tmp, 0, sizeof(struct ast_filestream));
362 if (write_header(fd)) {
366 if (pthread_mutex_lock(&wav_lock)) {
367 ast_log(LOG_WARNING, "Unable to lock wav list\n");
375 tmp->lasttimeout = -1;
377 pthread_mutex_unlock(&wav_lock);
378 ast_update_use_count();
380 ast_log(LOG_WARNING, "Out of memory\n");
384 static struct ast_frame *wav_read(struct ast_filestream *s)
389 static void wav_close(struct ast_filestream *s)
391 struct ast_filestream *tmp, *tmpl = NULL;
393 if (pthread_mutex_lock(&wav_lock)) {
394 ast_log(LOG_WARNING, "Unable to lock wav list\n");
401 tmpl->next = tmp->next;
411 s->owner->stream = NULL;
412 if (s->owner->streamid > -1)
413 ast_sched_del(s->owner->sched, s->owner->streamid);
414 s->owner->streamid = -1;
416 pthread_mutex_unlock(&wav_lock);
417 ast_update_use_count();
419 ast_log(LOG_WARNING, "Freeing a filestream we don't seem to own\n");
420 /* Pad to even length */
422 write(s->fd, &zero, 1);
427 static int ast_read_callback(void *data)
432 struct ast_filestream *s = data;
435 /* Send a frame from the file to the appropriate channel */
437 s->fr.frametype = AST_FRAME_VOICE;
438 s->fr.subclass = AST_FORMAT_GSM;
439 s->fr.offset = AST_FRIENDLY_OFFSET;
444 /* Just return a frame based on the second GSM frame */
445 s->fr.data = s->gsm + 33;
447 if ((res = read(s->fd, msdata, 65)) != 65) {
448 if (res && (res != 1))
449 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
450 s->owner->streamid = -1;
453 /* Convert from MS format to two real GSM frames */
454 conv65(msdata, s->gsm);
457 s->secondhalf = !s->secondhalf;
458 /* Lastly, process the frame */
459 if (ast_write(s->owner, &s->fr)) {
460 ast_log(LOG_WARNING, "Failed to write frame\n");
461 s->owner->streamid = -1;
464 if (s->last.tv_usec || s->last.tv_usec) {
466 gettimeofday(&tv, NULL);
467 ms = 1000 * (tv.tv_sec - s->last.tv_sec) +
468 (tv.tv_usec - s->last.tv_usec) / 1000;
469 s->last.tv_sec = tv.tv_sec;
470 s->last.tv_usec = tv.tv_usec;
471 if ((ms - delay) * (ms - delay) > 4) {
472 /* Compensate if we're more than 2 ms off */
473 s->adj -= (ms - delay);
476 fprintf(stdout, "Delay is %d, adjustment is %d, last was %d\n", delay, s->adj, ms);
482 gettimeofday(&s->last, NULL);
483 if (s->lasttimeout != delay) {
484 /* We'll install the next timeout now. */
485 s->owner->streamid = ast_sched_add(s->owner->sched,
486 delay, ast_read_callback, s);
487 s->lasttimeout = delay;
489 /* Just come back again at the same time */
495 static int wav_apply(struct ast_channel *c, struct ast_filestream *s)
497 /* Select our owner for this stream, and get the ball rolling. */
499 ast_read_callback(s);
503 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
507 if (f->frametype != AST_FRAME_VOICE) {
508 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
511 if (f->subclass != AST_FORMAT_GSM) {
512 ast_log(LOG_WARNING, "Asked to write non-GSM frame (%d)!\n", f->subclass);
515 if (fs->secondhalf) {
516 memcpy(fs->gsm + 33, f->data, 33);
517 conv66(fs->gsm, msdata);
518 if ((res = write(fs->fd, msdata, 65)) != 65) {
519 ast_log(LOG_WARNING, "Bad write (%d/65): %s\n", res, strerror(errno));
523 update_header(fs->fd, fs->bytes);
525 /* Copy the data and do nothing */
526 memcpy(fs->gsm, f->data, 33);
528 fs->secondhalf = !fs->secondhalf;
532 static char *wav_getcomment(struct ast_filestream *s)
539 return ast_format_register(name, exts, AST_FORMAT_GSM,
553 struct ast_filestream *tmp, *tmpl;
554 if (pthread_mutex_lock(&wav_lock)) {
555 ast_log(LOG_WARNING, "Unable to lock wav list\n");
561 ast_softhangup(tmp->owner);
566 pthread_mutex_unlock(&wav_lock);
567 return ast_format_unregister(name);
573 if (pthread_mutex_lock(&wav_lock)) {
574 ast_log(LOG_WARNING, "Unable to lock wav list\n");
578 pthread_mutex_unlock(&wav_lock);