aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>1999-12-16 13:44:30 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>1999-12-16 13:44:30 +0000
commit509765aef52f3ce306a114832ab885ad85522d2e (patch)
tree900d9952178c438c1347376241e306e457817f58
parent70f08a7afb001c7c1608181fa4546c6460890e04 (diff)
Version 0.1.1 from FTP
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@139 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-xBUGS6
-rwxr-xr-xchannels/chan_ixj.c52
-rwxr-xr-xchannels/chan_vofr.c27
-rwxr-xr-xcodecs/mp3/Makefile37
-rwxr-xr-xformats/format_g723.c4
-rwxr-xr-xformats/format_gsm.c298
-rwxr-xr-xformats/format_mp3.c103
-rwxr-xr-xformats/format_wav.c4
-rwxr-xr-xformats/format_wav_gsm.c586
-rwxr-xr-xformats/msgsm.h685
-rwxr-xr-xinclude/asterisk/channel_pvt.h6
-rwxr-xr-xinclude/asterisk/io.h6
-rwxr-xr-xio.c4
13 files changed, 1750 insertions, 68 deletions
diff --git a/BUGS b/BUGS
index 04fbe3e48..495e20da1 100755
--- a/BUGS
+++ b/BUGS
@@ -2,8 +2,10 @@
these bugs are in asterisk, and sometimes they relate to the products
that asterisk uses.
-* The MP3 decoder is completely broken
-
* The translator API may introduce warble in the case of going in both
directions, but I haven't verified that. The trouble should only enter
in the case of mismatched frame lengths.
+
+* In general Asterisk is a very new program, and there are liable to be
+ many bugs yet to be discovered, so if you think you've found one, please
+ be sure to report it.
diff --git a/channels/chan_ixj.c b/channels/chan_ixj.c
index 5f476cdf6..c8cdb91dd 100755
--- a/channels/chan_ixj.c
+++ b/channels/chan_ixj.c
@@ -3,7 +3,7 @@
*
* QuickNet Internet Phone Jack Channel
*
- * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
+ * Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
@@ -60,7 +60,7 @@ static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER;
which are not currently in use. */
static pthread_t monitor_thread = -1;
-static int restart_monitor();
+static int restart_monitor(void);
/* The private structures of the Phone Jack channels are linked for
selecting outgoing channels */
@@ -129,7 +129,8 @@ static int ixj_call(struct ast_channel *ast, char *dest, int timeout)
}
/* When we call, it just works, really, there's no destination... Just
ring the phone and wait for someone to answer */
- ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fd);
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fd);
ioctl(p->fd, IXJCTL_RING_START);
ast->state = AST_STATE_RINGING;
return 0;
@@ -139,7 +140,8 @@ static int ixj_hangup(struct ast_channel *ast)
{
struct ixj_pvt *p;
p = ast->pvt->pvt;
- ast_log(LOG_DEBUG, "ixj_hangup(%s)\n", ast->name);
+ if (option_debug)
+ ast_log(LOG_DEBUG, "ixj_hangup(%s)\n", ast->name);
if (!ast->pvt->pvt) {
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
return 0;
@@ -217,7 +219,8 @@ static int ixj_setup(struct ast_channel *ast)
static int ixj_answer(struct ast_channel *ast)
{
ixj_setup(ast);
- ast_log(LOG_DEBUG, "ixj_answer(%s)\n", ast->name);
+ if (option_debug)
+ ast_log(LOG_DEBUG, "ixj_answer(%s)\n", ast->name);
ast->rings = 0;
ast->state = AST_STATE_UP;
return 0;
@@ -287,6 +290,14 @@ static struct ast_frame *ixj_read(struct ast_channel *ast)
res = read(p->fd, p->buf, IXJ_MAX_BUF);
ast->blocking = 0;
if (res < 0) {
+#if 0
+ if (errno == EAGAIN) {
+ ast_log(LOG_WARNING, "Null frame received\n");
+ p->fr.frametype = AST_FRAME_NULL;
+ p->fr.subclass = 0;
+ return &p->fr;
+ }
+#endif
ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno));
return NULL;
}
@@ -486,6 +497,10 @@ static void ixj_check_exception(struct ixj_pvt *i)
ixj_new(i, AST_STATE_UP);
/* No need to restart monitor, we are the monitor */
if (i->owner) {
+ pthread_mutex_lock(&usecnt_lock);
+ usecnt--;
+ pthread_mutex_unlock(&usecnt_lock);
+ ast_update_use_count();
ixj_setup(i->owner);
}
} else if (ast_exists_extension(NULL, "default", i->ext, 1)) {
@@ -494,10 +509,16 @@ static void ixj_check_exception(struct ixj_pvt *i)
strncpy(i->context, "default", sizeof(i->context));
ixj_new(i, AST_STATE_UP);
if (i->owner) {
+ pthread_mutex_lock(&usecnt_lock);
+ usecnt--;
+ pthread_mutex_unlock(&usecnt_lock);
+ ast_update_use_count();
ixj_setup(i->owner);
}
} else if ((strlen(i->ext) >= ast_pbx_longest_extension(i->context)) &&
(strlen(i->ext) >= ast_pbx_longest_extension("default"))) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "%s is too long\n", i->ext);
/* It's not a valid extension, give a busy signal */
ioctl(i->fd, IXJCTL_BUSY);
}
@@ -512,18 +533,23 @@ static void ixj_check_exception(struct ixj_pvt *i)
if (i->mode == MODE_IMMEDIATE) {
ixj_new(i, AST_STATE_RING);
} else if (i->mode == MODE_DIALTONE) {
-#if 0
- /* XXX Bug in the Phone jack, you can't detect DTMF when playing a tone XXX */
- ioctl(i->fd, IXJCTL_DIALTONE);
-#else
+ pthread_mutex_lock(&usecnt_lock);
+ usecnt++;
+ pthread_mutex_unlock(&usecnt_lock);
+ ast_update_use_count();
/* Play the dialtone */
i->dialtone++;
ioctl(i->fd, IXJCTL_PLAY_STOP);
ioctl(i->fd, IXJCTL_PLAY_CODEC, ULAW);
ioctl(i->fd, IXJCTL_PLAY_START);
-#endif
}
} else {
+ if (i->dialtone) {
+ pthread_mutex_lock(&usecnt_lock);
+ usecnt--;
+ pthread_mutex_unlock(&usecnt_lock);
+ ast_update_use_count();
+ }
memset(i->ext, 0, sizeof(i->ext));
ioctl(i->fd, IXJCTL_CPT_STOP);
ioctl(i->fd, IXJCTL_PLAY_STOP);
@@ -690,11 +716,13 @@ static int restart_monitor()
return 0;
}
-struct ixj_pvt *mkif(char *iface, int mode)
+static struct ixj_pvt *mkif(char *iface, int mode)
{
/* Make a ixj_pvt structure for this interface */
struct ixj_pvt *tmp;
+#if 0
int flags;
+#endif
tmp = malloc(sizeof(struct ixj_pvt));
if (tmp) {
@@ -709,8 +737,10 @@ struct ixj_pvt *mkif(char *iface, int mode)
ioctl(tmp->fd, IXJCTL_RING_STOP);
ioctl(tmp->fd, IXJCTL_CPT_STOP);
tmp->mode = mode;
+#if 0
flags = fcntl(tmp->fd, F_GETFL);
fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
+#endif
tmp->owner = NULL;
tmp->lastformat = -1;
tmp->lastinput = -1;
diff --git a/channels/chan_vofr.c b/channels/chan_vofr.c
index ea17df951..aee44ff2e 100755
--- a/channels/chan_vofr.c
+++ b/channels/chan_vofr.c
@@ -3,7 +3,7 @@
*
* Implementation of Voice over Frame Relay, Adtran Style
*
- * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
+ * Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
@@ -55,7 +55,7 @@ static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER;
which are not currently in use. */
static pthread_t monitor_thread = -1;
-static int restart_monitor();
+static int restart_monitor(void);
/* The private structures of the Adtran VoFR channels are linked for
selecting outgoing channels */
@@ -558,6 +558,9 @@ static struct ast_frame *vofr_read(struct ast_channel *ast)
fr->subclass = 0;
break;
}
+ case VOFR_SIGNAL_RING:
+ ast->rings++;
+ break;
case VOFR_SIGNAL_UNKNOWN:
switch(vh->data[1]) {
case 0x1:
@@ -783,7 +786,21 @@ static int vofr_mini_packet(struct vofr_pvt *i, struct vofr_hdr *pkt, int len)
switch(pkt->data[0]) {
case VOFR_SIGNAL_RING:
/* If we get a RING, we definitely want to start a new thread */
- vofr_new(i, AST_STATE_RING);
+ if (!i->owner)
+ vofr_new(i, AST_STATE_RING);
+ else
+ ast_log(LOG_WARNING, "Got a ring, but there's an owner?\n");
+ break;
+ case VOFR_SIGNAL_OFF_HOOK:
+ /* Network termination, go off hook */
+#if 0
+ ast_log(LOG_DEBUG, "Off hook\n");
+#endif
+ vofr_xmit_signal(i, 0x10, 2);
+ if (!i->owner)
+ vofr_new(i, AST_STATE_UP);
+ else
+ ast_log(LOG_WARNING, "Got an offhook, but there's an owner?\n");
break;
case VOFR_SIGNAL_ON_HOOK:
break;
@@ -896,7 +913,7 @@ static void *do_monitor(void *data)
}
-static int restart_monitor()
+static int restart_monitor(void)
{
/* If we're supposed to be stopped -- stay stopped */
if (monitor_thread == -2)
@@ -926,7 +943,7 @@ static int restart_monitor()
return 0;
}
-struct vofr_pvt *mkif(char *type, char *iface)
+static struct vofr_pvt *mkif(char *type, char *iface)
{
/* Make a vofr_pvt structure for this interface */
struct vofr_pvt *tmp;
diff --git a/codecs/mp3/Makefile b/codecs/mp3/Makefile
new file mode 100755
index 000000000..44ebc39d1
--- /dev/null
+++ b/codecs/mp3/Makefile
@@ -0,0 +1,37 @@
+#
+# LMC section
+
+CFLAGS+= -I../include -Iinclude -O6 -funroll-loops -finline-functions -Wall -Wno-missing-prototypes -Wno-missing-declarations -g
+RANLIB=ranlib
+
+# the XING decoder objs and dependencies:
+# This is kinda nasty, since there's C, C++, and asm, oh my!
+# of course, each needs different compilation methods. grr.
+XINGOBJX86 = src/x86gas.o
+
+XINGOBJS = src/cdct.o src/cupl3.o \
+ src/hwin.o src/iup.o src/l3init.o \
+ src/msis.o src/wavep.o src/csbt.o \
+ src/cwinm.o src/icdct.o src/mdct.o \
+ src/uph.o src/cup.o src/dec8.o \
+ src/isbt.o src/l3dq.o src/mhead.o \
+ src/upsf.o src/iwinm.o
+
+LIBMP3=libmp3.a
+ARFLAGS=cr
+
+XINGLMCOBJC += $(shell if uname -m | grep -q i.86; then echo src/x86gas.o; fi)
+
+#assembly lang code, if we need it
+
+XINGLMCOBJ = $(XINGOBJS)
+
+all: $(LIBMP3)
+
+$(LIBMP3): $(XINGOBJS)
+ $(AR) $(ARFLAGS) $(LIBMP3) $(XINGLMCOBJ)
+ $(RANLIB) $(LIBMP3)
+
+clean:
+ rm -f $(XINGOBJS)
+ rm -f $(LIBMP3)
diff --git a/formats/format_g723.c b/formats/format_g723.c
index 827987049..3824e04e7 100755
--- a/formats/format_g723.c
+++ b/formats/format_g723.c
@@ -3,7 +3,7 @@
*
* Old-style G.723 frame/timestamp format.
*
- * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
+ * Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
@@ -285,7 +285,7 @@ static int g723_write(struct ast_filestream *fs, struct ast_frame *f)
return 0;
}
-char *g723_getcomment(struct ast_filestream *s)
+static char *g723_getcomment(struct ast_filestream *s)
{
return NULL;
}
diff --git a/formats/format_gsm.c b/formats/format_gsm.c
new file mode 100755
index 000000000..6a06627fb
--- /dev/null
+++ b/formats/format_gsm.c
@@ -0,0 +1,298 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Save to raw, headerless GSM data.
+ *
+ * Copyright (C) 1999, Mark Spencer
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+#include <asterisk/channel.h>
+#include <asterisk/file.h>
+#include <asterisk/logger.h>
+#include <asterisk/sched.h>
+#include <asterisk/module.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <endian.h>
+
+/* Some Ideas for this code came from makegsme.c by Jeffery Chilton */
+
+/* Portions of the conversion code are by guido@sienanet.it */
+
+struct ast_filestream {
+ void *reserved[AST_RESERVED_POINTERS];
+ /* Believe it or not, we must decode/recode to account for the
+ weird MS format */
+ /* This is what a filestream means to us */
+ int fd; /* Descriptor */
+ struct ast_channel *owner;
+ struct ast_frame fr; /* Frame information */
+ char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
+ char empty; /* Empty character */
+ unsigned char gsm[33]; /* Two Real GSM Frames */
+ int lasttimeout;
+ struct timeval last;
+ int adj;
+ struct ast_filestream *next;
+};
+
+
+static struct ast_filestream *glist = NULL;
+static pthread_mutex_t gsm_lock = PTHREAD_MUTEX_INITIALIZER;
+static int glistcnt = 0;
+
+static char *name = "gsm";
+static char *desc = "Raw GSM data";
+static char *exts = "gsm";
+
+static struct ast_filestream *gsm_open(int fd)
+{
+ /* 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 ast_filestream *tmp;
+ if ((tmp = malloc(sizeof(struct ast_filestream)))) {
+ memset(tmp, 0, sizeof(struct ast_filestream));
+ if (pthread_mutex_lock(&gsm_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock gsm list\n");
+ free(tmp);
+ return NULL;
+ }
+ tmp->next = glist;
+ glist = tmp;
+ tmp->fd = fd;
+ tmp->owner = NULL;
+ tmp->fr.data = tmp->gsm;
+ tmp->fr.frametype = AST_FRAME_VOICE;
+ tmp->fr.subclass = AST_FORMAT_GSM;
+ /* datalen will vary for each frame */
+ tmp->fr.src = name;
+ tmp->fr.mallocd = 0;
+ tmp->lasttimeout = -1;
+ glistcnt++;
+ pthread_mutex_unlock(&gsm_lock);
+ ast_update_use_count();
+ }
+ return tmp;
+}
+
+static struct ast_filestream *gsm_rewrite(int fd, char *comment)
+{
+ /* 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 ast_filestream *tmp;
+ if ((tmp = malloc(sizeof(struct ast_filestream)))) {
+ memset(tmp, 0, sizeof(struct ast_filestream));
+ if (pthread_mutex_lock(&gsm_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock gsm list\n");
+ free(tmp);
+ return NULL;
+ }
+ tmp->next = glist;
+ glist = tmp;
+ tmp->fd = fd;
+ tmp->owner = NULL;
+ tmp->lasttimeout = -1;
+ glistcnt++;
+ pthread_mutex_unlock(&gsm_lock);
+ ast_update_use_count();
+ } else
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return tmp;
+}
+
+static struct ast_frame *gsm_read(struct ast_filestream *s)
+{
+ return NULL;
+}
+
+static void gsm_close(struct ast_filestream *s)
+{
+ struct ast_filestream *tmp, *tmpl = NULL;
+ if (pthread_mutex_lock(&gsm_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock gsm list\n");
+ return;
+ }
+ tmp = glist;
+ while(tmp) {
+ if (tmp == s) {
+ if (tmpl)
+ tmpl->next = tmp->next;
+ else
+ glist = tmp->next;
+ break;
+ }
+ tmpl = tmp;
+ tmp = tmp->next;
+ }
+ glistcnt--;
+ if (s->owner) {
+ s->owner->stream = NULL;
+ if (s->owner->streamid > -1)
+ ast_sched_del(s->owner->sched, s->owner->streamid);
+ s->owner->streamid = -1;
+ }
+ pthread_mutex_unlock(&gsm_lock);
+ ast_update_use_count();
+ if (!tmp)
+ ast_log(LOG_WARNING, "Freeing a filestream we don't seem to own\n");
+ close(s->fd);
+ free(s);
+}
+
+static int ast_read_callback(void *data)
+{
+ int retval = 0;
+ int res;
+ int delay = 20;
+ struct ast_filestream *s = data;
+ struct timeval tv;
+ /* Send a frame from the file to the appropriate channel */
+
+ s->fr.frametype = AST_FRAME_VOICE;
+ s->fr.subclass = AST_FORMAT_GSM;
+ s->fr.offset = AST_FRIENDLY_OFFSET;
+ s->fr.timelen = 20;
+ s->fr.datalen = 33;
+ s->fr.mallocd = 0;
+ s->fr.data = s->gsm;
+ if ((res = read(s->fd, s->gsm, 33)) != 33) {
+ if (res)
+ ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
+ s->owner->streamid = -1;
+ return 0;
+ }
+ /* Lastly, process the frame */
+ if (ast_write(s->owner, &s->fr)) {
+ ast_log(LOG_WARNING, "Failed to write frame\n");
+ s->owner->streamid = -1;
+ return 0;
+ }
+ if (s->last.tv_usec || s->last.tv_usec) {
+ int ms;
+ gettimeofday(&tv, NULL);
+ ms = 1000 * (tv.tv_sec - s->last.tv_sec) +
+ (tv.tv_usec - s->last.tv_usec) / 1000;
+ s->last.tv_sec = tv.tv_sec;
+ s->last.tv_usec = tv.tv_usec;
+ if ((ms - delay) * (ms - delay) > 4) {
+ /* Compensate if we're more than 2 ms off */
+ s->adj -= (ms - delay);
+ }
+#if 0
+ fprintf(stdout, "Delay is %d, adjustment is %d, last was %d\n", delay, s->adj, ms);
+#endif
+ delay += s->adj;
+ if (delay < 1)
+ delay = 1;
+ } else
+ gettimeofday(&s->last, NULL);
+ if (s->lasttimeout != delay) {
+ /* We'll install the next timeout now. */
+ s->owner->streamid = ast_sched_add(s->owner->sched,
+ delay, ast_read_callback, s);
+ s->lasttimeout = delay;
+ } else {
+ /* Just come back again at the same time */
+ retval = -1;
+ }
+ return retval;
+}
+
+static int gsm_apply(struct ast_channel *c, struct ast_filestream *s)
+{
+ /* Select our owner for this stream, and get the ball rolling. */
+ s->owner = c;
+ ast_read_callback(s);
+ return 0;
+}
+
+static int gsm_write(struct ast_filestream *fs, struct ast_frame *f)
+{
+ int res;
+ 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);
+ return -1;
+ }
+ if (f->datalen != 33) {
+ ast_log(LOG_WARNING, "Invalid data length, %d, should be 33\n", f->datalen);
+ return -1;
+ }
+ if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) {
+ ast_log(LOG_WARNING, "Bad write (%d/33): %s\n", res, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static char *gsm_getcomment(struct ast_filestream *s)
+{
+ return NULL;
+}
+
+int load_module()
+{
+ return ast_format_register(name, exts, AST_FORMAT_GSM,
+ gsm_open,
+ gsm_rewrite,
+ gsm_apply,
+ gsm_write,
+ gsm_read,
+ gsm_close,
+ gsm_getcomment);
+
+
+}
+
+int unload_module()
+{
+ struct ast_filestream *tmp, *tmpl;
+ if (pthread_mutex_lock(&gsm_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock gsm list\n");
+ return -1;
+ }
+ tmp = glist;
+ while(tmp) {
+ if (tmp->owner)
+ ast_softhangup(tmp->owner);
+ tmpl = tmp;
+ tmp = tmp->next;
+ free(tmpl);
+ }
+ pthread_mutex_unlock(&gsm_lock);
+ return ast_format_unregister(name);
+}
+
+int usecount()
+{
+ int res;
+ if (pthread_mutex_lock(&gsm_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock gsm list\n");
+ return -1;
+ }
+ res = glistcnt;
+ pthread_mutex_unlock(&gsm_lock);
+ return res;
+}
+
+char *description()
+{
+ return desc;
+}
+
diff --git a/formats/format_mp3.c b/formats/format_mp3.c
index 811acbe14..85abdbc1b 100755
--- a/formats/format_mp3.c
+++ b/formats/format_mp3.c
@@ -3,7 +3,7 @@
*
* Everybody's favorite format: MP3 Files! Yay!
*
- * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
+ * Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
@@ -26,8 +26,7 @@
#include <sys/time.h>
#include "../channels/adtranvofr.h"
-
-#define MP3_MAX_SIZE 1400
+#define MAX_FRAME_SIZE 1441
struct ast_filestream {
/* First entry MUST be reserved for the channel type */
@@ -36,9 +35,13 @@ struct ast_filestream {
int fd; /* Descriptor */
struct ast_channel *owner;
struct ast_filestream *next;
- struct ast_frame *fr; /* Frame representation of buf */
- char buf[sizeof(struct ast_frame) + MP3_MAX_SIZE + AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
+ struct ast_frame fr; /* Frame representation of buf */
+ char offset[AST_FRIENDLY_OFFSET];
+ unsigned char buf[MAX_FRAME_SIZE * 2];
+ int lasttimeout;
int pos;
+ int adj;
+ struct timeval last;
};
@@ -47,16 +50,10 @@ static pthread_mutex_t mp3_lock = PTHREAD_MUTEX_INITIALIZER;
static int glistcnt = 0;
static char *name = "mp3";
-static char *desc = "MPEG-2 Layer 3 File Format Support";
+static char *desc = "MPEG-1,2 Layer 3 File Format Support";
static char *exts = "mp3|mpeg3";
-#if 0
-#define MP3_FRAMELEN 417
-#else
-#define MP3_FRAMELEN 400
-#endif
-#define MP3_OUTPUTLEN 2304 /* Bytes */
-#define MP3_TIMELEN ((MP3_OUTPUTLEN * 1000 / 16000) )
+#include "../codecs/mp3anal.h"
static struct ast_filestream *mp3_open(int fd)
{
@@ -74,13 +71,10 @@ static struct ast_filestream *mp3_open(int fd)
glist = tmp;
tmp->fd = fd;
tmp->owner = NULL;
- tmp->fr = (struct ast_frame *)tmp->buf;
- tmp->fr->data = tmp->buf + sizeof(struct ast_frame);
- tmp->fr->frametype = AST_FRAME_VOICE;
- tmp->fr->subclass = AST_FORMAT_MP3;
- /* datalen will vary for each frame */
- tmp->fr->src = name;
- tmp->fr->mallocd = 0;
+ tmp->lasttimeout = -1;
+ tmp->last.tv_usec = 0;
+ tmp->last.tv_sec = 0;
+ tmp->adj = 0;
glistcnt++;
pthread_mutex_unlock(&mp3_lock);
ast_update_use_count();
@@ -104,7 +98,6 @@ static struct ast_filestream *mp3_rewrite(int fd, char *comment)
glist = tmp;
tmp->fd = fd;
tmp->owner = NULL;
- tmp->fr = NULL;
glistcnt++;
pthread_mutex_unlock(&mp3_lock);
ast_update_use_count();
@@ -155,28 +148,67 @@ static void mp3_close(struct ast_filestream *s)
static int ast_read_callback(void *data)
{
/* XXX Don't assume frames are this size XXX */
- u_int16_t size=MP3_FRAMELEN;
u_int32_t delay = -1;
int res;
struct ast_filestream *s = data;
- /* Send a frame from the file to the appropriate channel */
- /* Read the data into the buffer */
- s->fr->offset = AST_FRIENDLY_OFFSET;
- s->fr->datalen = size;
- s->fr->data = s->buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
- if ((res = read(s->fd, s->fr->data , size)) != size) {
- ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno));
+ int size;
+ int ms=0;
+ struct timeval tv;
+ if ((res = read(s->fd, s->buf , 4)) != 4) {
+ ast_log(LOG_WARNING, "Short read (%d of 4 bytes) (%s)!\n", res, strerror(errno));
s->owner->streamid = -1;
return 0;
}
- delay = MP3_TIMELEN;
- s->fr->timelen = delay;
+ if (mp3_badheader(s->buf)) {
+ ast_log(LOG_WARNING, "Bad mp3 header\n");
+ return 0;
+ }
+ if ((size = mp3_framelen(s->buf)) < 0) {
+ ast_log(LOG_WARNING, "Unable to calculate frame size\n");
+ return 0;
+ }
+ if ((res = read(s->fd, s->buf + 4 , size - 4)) != size - 4) {
+ ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size - 4, strerror(errno));
+ s->owner->streamid = -1;
+ return 0;
+ }
+ /* Send a frame from the file to the appropriate channel */
+ /* Read the data into the buffer */
+ s->fr.offset = AST_FRIENDLY_OFFSET;
+ s->fr.frametype = AST_FRAME_VOICE;
+ s->fr.subclass = AST_FORMAT_MP3;
+ s->fr.mallocd = 0;
+ s->fr.src = name;
+ s->fr.datalen = size;
+ s->fr.data = s->buf;
+ delay = mp3_samples(s->buf) * 1000 / mp3_samplerate(s->buf);
+ if (s->last.tv_sec || s->last.tv_usec) {
+ /* To keep things running smoothly, we watch how close we're coming */
+ gettimeofday(&tv, NULL);
+ ms = ((tv.tv_usec - s->last.tv_usec) / 1000 + (tv.tv_sec - s->last.tv_sec) * 1000);
+ /* If we're within 2 milliseconds, that's close enough */
+ if ((ms - delay) * (ms - delay) > 4)
+ s->adj -= (ms - delay);
+ }
+ s->fr.timelen = delay;
+#if 0
+ ast_log(LOG_DEBUG, "delay is %d, adjusting by %d, as last was %d\n", delay, s->adj, ms);
+#endif
+ delay += s->adj;
+ if (delay < 1)
+ delay = 1;
/* Lastly, process the frame */
- if (ast_write(s->owner, s->fr)) {
+ if (ast_write(s->owner, &s->fr)) {
ast_log(LOG_WARNING, "Failed to write frame\n");
s->owner->streamid = -1;
return 0;
}
+ gettimeofday(&s->last, NULL);
+ if (s->lasttimeout != delay) {
+ s->owner->streamid = ast_sched_add(s->owner->sched, delay, ast_read_callback, s);
+ s->lasttimeout = delay;
+ return 0;
+ }
return -1;
}
@@ -184,7 +216,6 @@ static int mp3_apply(struct ast_channel *c, struct ast_filestream *s)
{
/* Select our owner for this stream, and get the ball rolling. */
s->owner = c;
- s->owner->streamid = ast_sched_add(s->owner->sched, MP3_TIMELEN, ast_read_callback, s);
ast_read_callback(s);
return 0;
}
@@ -192,10 +223,6 @@ static int mp3_apply(struct ast_channel *c, struct ast_filestream *s)
static int mp3_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
- if (fs->fr) {
- ast_log(LOG_WARNING, "Asked to write on a read stream??\n");
- return -1;
- }
if (f->frametype != AST_FRAME_VOICE) {
ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
return -1;
@@ -211,7 +238,7 @@ static int mp3_write(struct ast_filestream *fs, struct ast_frame *f)
return 0;
}
-char *mp3_getcomment(struct ast_filestream *s)
+static char *mp3_getcomment(struct ast_filestream *s)
{
return NULL;
}
diff --git a/formats/format_wav.c b/formats/format_wav.c
index e3265d379..9ba4fdc22 100755
--- a/formats/format_wav.c
+++ b/formats/format_wav.c
@@ -3,7 +3,7 @@
*
* Microsoft WAV File Format using libaudiofile
*
- * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
+ * Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
@@ -298,7 +298,7 @@ static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
return 0;
}
-char *wav_getcomment(struct ast_filestream *s)
+static char *wav_getcomment(struct ast_filestream *s)
{
return NULL;
}
diff --git a/formats/format_wav_gsm.c b/formats/format_wav_gsm.c
new file mode 100755
index 000000000..b901a4028
--- /dev/null
+++ b/formats/format_wav_gsm.c
@@ -0,0 +1,586 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Save GSM in the proprietary Microsoft format.
+ *
+ * Copyright (C) 1999, Mark Spencer
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+#include <asterisk/channel.h>
+#include <asterisk/file.h>
+#include <asterisk/logger.h>
+#include <asterisk/sched.h>
+#include <asterisk/module.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <endian.h>
+#include "msgsm.h"
+
+/* Some Ideas for this code came from makewave.c by Jeffery Chilton */
+
+/* Portions of the conversion code are by guido@sienanet.it */
+
+struct ast_filestream {
+ void *reserved[AST_RESERVED_POINTERS];
+ /* Believe it or not, we must decode/recode to account for the
+ weird MS format */
+ /* This is what a filestream means to us */
+ int fd; /* Descriptor */
+ int bytes;
+ struct ast_channel *owner;
+ struct ast_frame fr; /* Frame information */
+ char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
+ char empty; /* Empty character */
+ unsigned char gsm[66]; /* Two Real GSM Frames */
+ int foffset;
+ int secondhalf; /* Are we on the second half */
+ int lasttimeout;
+ struct timeval last;
+ int adj;
+ struct ast_filestream *next;
+};
+
+
+static struct ast_filestream *glist = NULL;
+static pthread_mutex_t wav_lock = PTHREAD_MUTEX_INITIALIZER;
+static int glistcnt = 0;
+
+static char *name = "wav49";
+static char *desc = "Microsoft WAV format (Proprietary GSM)";
+static char *exts = "WAV";
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define htoll(b) (b)
+#define htols(b) (b)
+#define ltohl(b) (b)
+#define ltohs(b) (b)
+#else
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define htoll(b) \
+ (((((b) ) & 0xFF) << 24) | \
+ ((((b) >> 8) & 0xFF) << 16) | \
+ ((((b) >> 16) & 0xFF) << 8) | \
+ ((((b) >> 24) & 0xFF) ))
+#define htols(b) \
+ (((((b) ) & 0xFF) << 8) | \
+ ((((b) >> 8) & 0xFF) ))
+#define ltohl(b) htoll(b)
+#define ltohs(b) htols(b)
+#else
+#error "Endianess not defined"
+#endif
+#endif
+
+
+static int check_header(int fd)
+{
+ int type, size, formtype;
+ int fmt, hsize, fact;
+ short format, chans;
+ int freq;
+ int data;
+ if (read(fd, &type, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (type)\n");
+ return -1;
+ }
+ if (read(fd, &size, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (size)\n");
+ return -1;
+ }
+ size = ltohl(size);
+ if (read(fd, &formtype, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (formtype)\n");
+ return -1;
+ }
+ if (memcmp(&type, "RIFF", 4)) {
+ ast_log(LOG_WARNING, "Does not begin with RIFF\n");
+ return -1;
+ }
+ if (memcmp(&formtype, "WAVE", 4)) {
+ ast_log(LOG_WARNING, "Does not contain WAVE\n");
+ return -1;
+ }
+ if (read(fd, &fmt, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (fmt)\n");
+ return -1;
+ }
+ if (memcmp(&fmt, "fmt ", 4)) {
+ ast_log(LOG_WARNING, "Does not say fmt\n");
+ return -1;
+ }
+ if (read(fd, &hsize, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (formtype)\n");
+ return -1;
+ }
+ if (ltohl(hsize) != 20) {
+ ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize));
+ return -1;
+ }
+ if (read(fd, &format, 2) != 2) {
+ ast_log(LOG_WARNING, "Read failed (format)\n");
+ return -1;
+ }
+ if (ltohs(format) != 49) {
+ ast_log(LOG_WARNING, "Not a GSM file %d\n", ltohs(format));
+ return -1;
+ }
+ if (read(fd, &chans, 2) != 2) {
+ ast_log(LOG_WARNING, "Read failed (format)\n");
+ return -1;
+ }
+ if (ltohs(chans) != 1) {
+ ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
+ return -1;
+ }
+ if (read(fd, &freq, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (freq)\n");
+ return -1;
+ }
+ if (ltohl(freq) != 8000) {
+ ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq));
+ return -1;
+ }
+ /* Ignore the byte frequency */
+ if (read(fd, &freq, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (X_1)\n");
+ return -1;
+ }
+ /* Ignore the two weird fields */
+ if (read(fd, &freq, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (X_2/X_3)\n");
+ return -1;
+ }
+ /* Ignore the byte frequency */
+ if (read(fd, &freq, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (Y_1)\n");
+ return -1;
+ }
+ /* Check for the word fact */
+ if (read(fd, &fact, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (fact)\n");
+ return -1;
+ }
+ if (memcmp(&fact, "fact", 4)) {
+ ast_log(LOG_WARNING, "Does not say fact\n");
+ return -1;
+ }
+ /* Ignore the "fact value" */
+ if (read(fd, &fact, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (fact header)\n");
+ return -1;
+ }
+ if (read(fd, &fact, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (fact value)\n");
+ return -1;
+ }
+ /* Check for the word data */
+ if (read(fd, &data, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (data)\n");
+ return -1;
+ }
+ if (memcmp(&data, "data", 4)) {
+ ast_log(LOG_WARNING, "Does not say data\n");
+ return -1;
+ }
+ /* Ignore the data length */
+ if (read(fd, &data, 4) != 4) {
+ ast_log(LOG_WARNING, "Read failed (data)\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int update_header(int fd, int bytes)
+{
+ int cur;
+ int datalen = htoll(bytes);
+ int filelen = htoll(52 + ((bytes + 1) & ~0x1));
+ cur = lseek(fd, 0, SEEK_CUR);
+ if (cur < 0) {
+ ast_log(LOG_WARNING, "Unable to find our position\n");
+ return -1;
+ }
+ if (lseek(fd, 4, SEEK_SET) != 4) {
+ ast_log(LOG_WARNING, "Unable to set our position\n");
+ return -1;
+ }
+ if (write(fd, &filelen, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to set write file size\n");
+ return -1;
+ }
+ if (lseek(fd, 56, SEEK_SET) != 56) {
+ ast_log(LOG_WARNING, "Unable to set our position\n");
+ return -1;
+ }
+ if (write(fd, &datalen, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to set write datalen\n");
+ return -1;
+ }
+ if (lseek(fd, cur, SEEK_SET) != cur) {
+ ast_log(LOG_WARNING, "Unable to return to position\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int write_header(int fd)
+{
+ unsigned int hz=htoll(8000);
+ unsigned int bhz = htoll(1625);
+ unsigned int hs = htoll(20);
+ unsigned short fmt = htols(49);
+ 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);
+ unsigned int size = htoll(0);
+ /* Write a GSM header, ignoring sizes which will be filled in later */
+ if (write(fd, "RIFF", 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &size, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, "WAVEfmt ", 8) != 8) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &hs, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &fmt, 2) != 2) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &chans, 2) != 2) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &hz, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &bhz, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &x_1, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &x_2, 2) != 2) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &x_3, 2) != 2) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, "fact", 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &fhs, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &y_1, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, "data", 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ if (write(fd, &size, 4) != 4) {
+ ast_log(LOG_WARNING, "Unable to write header\n");
+ return -1;
+ }
+ return 0;
+}
+
+static struct ast_filestream *wav_open(int fd)
+{
+ /* 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 ast_filestream *tmp;
+ if ((tmp = malloc(sizeof(struct ast_filestream)))) {
+ memset(tmp, 0, sizeof(struct ast_filestream));
+ if (check_header(fd)) {
+ free(tmp);
+ return NULL;
+ }
+ if (pthread_mutex_lock(&wav_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock wav list\n");
+ free(tmp);
+ return NULL;
+ }
+ tmp->next = glist;
+ glist = tmp;
+ tmp->fd = fd;
+ tmp->owner = NULL;
+ tmp->fr.data = tmp->gsm;
+ tmp->fr.frametype = AST_FRAME_VOICE;
+ tmp->fr.subclass = AST_FORMAT_GSM;
+ /* datalen will vary for each frame */
+ tmp->fr.src = name;
+ tmp->fr.mallocd = 0;
+ tmp->secondhalf = 0;
+ tmp->lasttimeout = -1;
+ glistcnt++;
+ pthread_mutex_unlock(&wav_lock);
+ ast_update_use_count();
+ }
+ return tmp;
+}
+
+static struct ast_filestream *wav_rewrite(int fd, char *comment)
+{
+ /* 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 ast_filestream *tmp;
+ if ((tmp = malloc(sizeof(struct ast_filestream)))) {
+ memset(tmp, 0, sizeof(struct ast_filestream));
+ if (write_header(fd)) {
+ free(tmp);
+ return NULL;
+ }
+ if (pthread_mutex_lock(&wav_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock wav list\n");
+ free(tmp);
+ return NULL;
+ }
+ tmp->next = glist;
+ glist = tmp;
+ tmp->fd = fd;
+ tmp->owner = NULL;
+ tmp->lasttimeout = -1;
+ glistcnt++;
+ pthread_mutex_unlock(&wav_lock);
+ ast_update_use_count();
+ } else
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return tmp;
+}
+
+static struct ast_frame *wav_read(struct ast_filestream *s)
+{
+ return NULL;
+}
+
+static void wav_close(struct ast_filestream *s)
+{
+ struct ast_filestream *tmp, *tmpl = NULL;
+ char zero = 0;
+ if (pthread_mutex_lock(&wav_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock wav list\n");
+ return;
+ }
+ tmp = glist;
+ while(tmp) {
+ if (tmp == s) {
+ if (tmpl)
+ tmpl->next = tmp->next;
+ else
+ glist = tmp->next;
+ break;
+ }
+ tmpl = tmp;
+ tmp = tmp->next;
+ }
+ glistcnt--;
+ if (s->owner) {
+ s->owner->stream = NULL;
+ if (s->owner->streamid > -1)
+ ast_sched_del(s->owner->sched, s->owner->streamid);
+ s->owner->streamid = -1;
+ }
+ pthread_mutex_unlock(&wav_lock);
+ ast_update_use_count();
+ if (!tmp)
+ ast_log(LOG_WARNING, "Freeing a filestream we don't seem to own\n");
+ /* Pad to even length */
+ if (s->bytes & 0x1)
+ write(s->fd, &zero, 1);
+ close(s->fd);
+ free(s);
+}
+
+static int ast_read_callback(void *data)
+{
+ int retval = 0;
+ int res;
+ int delay = 20;
+ struct ast_filestream *s = data;
+ char msdata[66];
+ struct timeval tv;
+ /* Send a frame from the file to the appropriate channel */
+
+ s->fr.frametype = AST_FRAME_VOICE;
+ s->fr.subclass = AST_FORMAT_GSM;
+ s->fr.offset = AST_FRIENDLY_OFFSET;
+ s->fr.timelen = 20;
+ s->fr.datalen = 33;
+ s->fr.mallocd = 0;
+ if (s->secondhalf) {
+ /* Just return a frame based on the second GSM frame */
+ s->fr.data = s->gsm + 33;
+ } else {
+ if ((res = read(s->fd, msdata, 65)) != 65) {
+ if (res && (res != 1))
+ ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
+ s->owner->streamid = -1;
+ return 0;
+ }
+ /* Convert from MS format to two real GSM frames */
+ conv65(msdata, s->gsm);
+ s->fr.data = s->gsm;
+ }
+ s->secondhalf = !s->secondhalf;
+ /* Lastly, process the frame */
+ if (ast_write(s->owner, &s->fr)) {
+ ast_log(LOG_WARNING, "Failed to write frame\n");
+ s->owner->streamid = -1;
+ return 0;
+ }
+ if (s->last.tv_usec || s->last.tv_usec) {
+ int ms;
+ gettimeofday(&tv, NULL);
+ ms = 1000 * (tv.tv_sec - s->last.tv_sec) +
+ (tv.tv_usec - s->last.tv_usec) / 1000;
+ s->last.tv_sec = tv.tv_sec;
+ s->last.tv_usec = tv.tv_usec;
+ if ((ms - delay) * (ms - delay) > 4) {
+ /* Compensate if we're more than 2 ms off */
+ s->adj -= (ms - delay);
+ }
+#if 0
+ fprintf(stdout, "Delay is %d, adjustment is %d, last was %d\n", delay, s->adj, ms);
+#endif
+ delay += s->adj;
+ if (delay < 1)
+ delay = 1;
+ } else
+ gettimeofday(&s->last, NULL);
+ if (s->lasttimeout != delay) {
+ /* We'll install the next timeout now. */
+ s->owner->streamid = ast_sched_add(s->owner->sched,
+ delay, ast_read_callback, s);
+ s->lasttimeout = delay;
+ } else {
+ /* Just come back again at the same time */
+ retval = -1;
+ }
+ return retval;
+}
+
+static int wav_apply(struct ast_channel *c, struct ast_filestream *s)
+{
+ /* Select our owner for this stream, and get the ball rolling. */
+ s->owner = c;
+ ast_read_callback(s);
+ return 0;
+}
+
+static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
+{
+ int res;
+ char msdata[66];
+ 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);
+ return -1;
+ }
+ if (fs->secondhalf) {
+ memcpy(fs->gsm + 33, f->data, 33);
+ conv66(fs->gsm, msdata);
+ if ((res = write(fs->fd, msdata, 65)) != 65) {
+ ast_log(LOG_WARNING, "Bad write (%d/65): %s\n", res, strerror(errno));
+ return -1;
+ }
+ fs->bytes += 65;
+ update_header(fs->fd, fs->bytes);
+ } else {
+ /* Copy the data and do nothing */
+ memcpy(fs->gsm, f->data, 33);
+ }
+ fs->secondhalf = !fs->secondhalf;
+ return 0;
+}
+
+static char *wav_getcomment(struct ast_filestream *s)
+{
+ return NULL;
+}
+
+int load_module()
+{
+ return ast_format_register(name, exts, AST_FORMAT_GSM,
+ wav_open,
+ wav_rewrite,
+ wav_apply,
+ wav_write,
+ wav_read,
+ wav_close,
+ wav_getcomment);
+
+
+}
+
+int unload_module()
+{
+ struct ast_filestream *tmp, *tmpl;
+ if (pthread_mutex_lock(&wav_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock wav list\n");
+ return -1;
+ }
+ tmp = glist;
+ while(tmp) {
+ if (tmp->owner)
+ ast_softhangup(tmp->owner);
+ tmpl = tmp;
+ tmp = tmp->next;
+ free(tmpl);
+ }
+ pthread_mutex_unlock(&wav_lock);
+ return ast_format_unregister(name);
+}
+
+int usecount()
+{
+ int res;
+ if (pthread_mutex_lock(&wav_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock wav list\n");
+ return -1;
+ }
+ res = glistcnt;
+ pthread_mutex_unlock(&wav_lock);
+ return res;
+}
+
+char *description()
+{
+ return desc;
+}
+
diff --git a/formats/msgsm.h b/formats/msgsm.h
new file mode 100755
index 000000000..2513e72b1
--- /dev/null
+++ b/formats/msgsm.h
@@ -0,0 +1,685 @@
+/* Conversion routines derived from code by guido@sienanet.it */
+
+#define GSM_MAGIC 0xD
+
+typedef unsigned char gsm_byte;
+typedef unsigned char wav_byte;
+typedef unsigned int uword;
+
+#define readGSM_33(c1) { \
+ gsm_byte *c = (c1); \
+ LARc[0] = (*c++ & 0xF) << 2; /* 1 */ \
+ LARc[0] |= (*c >> 6) & 0x3; \
+ LARc[1] = *c++ & 0x3F; \
+ LARc[2] = (*c >> 3) & 0x1F; \
+ LARc[3] = (*c++ & 0x7) << 2; \
+ LARc[3] |= (*c >> 6) & 0x3; \
+ LARc[4] = (*c >> 2) & 0xF; \
+ LARc[5] = (*c++ & 0x3) << 2; \
+ LARc[5] |= (*c >> 6) & 0x3; \
+ LARc[6] = (*c >> 3) & 0x7; \
+ LARc[7] = *c++ & 0x7; \
+ Nc[0] = (*c >> 1) & 0x7F; \
+ bc[0] = (*c++ & 0x1) << 1; \
+ bc[0] |= (*c >> 7) & 0x1; \
+ Mc[0] = (*c >> 5) & 0x3; \
+ xmaxc[0] = (*c++ & 0x1F) << 1; \
+ xmaxc[0] |= (*c >> 7) & 0x1; \
+ xmc[0] = (*c >> 4) & 0x7; \
+ xmc[1] = (*c >> 1) & 0x7; \
+ xmc[2] = (*c++ & 0x1) << 2; \
+ xmc[2] |= (*c >> 6) & 0x3; \
+ xmc[3] = (*c >> 3) & 0x7; \
+ xmc[4] = *c++ & 0x7; \
+ xmc[5] = (*c >> 5) & 0x7; \
+ xmc[6] = (*c >> 2) & 0x7; \
+ xmc[7] = (*c++ & 0x3) << 1; /* 10 */ \
+ xmc[7] |= (*c >> 7) & 0x1; \
+ xmc[8] = (*c >> 4) & 0x7; \
+ xmc[9] = (*c >> 1) & 0x7; \
+ xmc[10] = (*c++ & 0x1) << 2; \
+ xmc[10] |= (*c >> 6) & 0x3; \
+ xmc[11] = (*c >> 3) & 0x7; \
+ xmc[12] = *c++ & 0x7; \
+ Nc[1] = (*c >> 1) & 0x7F; \
+ bc[1] = (*c++ & 0x1) << 1; \
+ bc[1] |= (*c >> 7) & 0x1; \
+ Mc[1] = (*c >> 5) & 0x3; \
+ xmaxc[1] = (*c++ & 0x1F) << 1; \
+ xmaxc[1] |= (*c >> 7) & 0x1; \
+ xmc[13] = (*c >> 4) & 0x7; \
+ xmc[14] = (*c >> 1) & 0x7; \
+ xmc[15] = (*c++ & 0x1) << 2; \
+ xmc[15] |= (*c >> 6) & 0x3; \
+ xmc[16] = (*c >> 3) & 0x7; \
+ xmc[17] = *c++ & 0x7; \
+ xmc[18] = (*c >> 5) & 0x7; \
+ xmc[19] = (*c >> 2) & 0x7; \
+ xmc[20] = (*c++ & 0x3) << 1; \
+ xmc[20] |= (*c >> 7) & 0x1; \
+ xmc[21] = (*c >> 4) & 0x7; \
+ xmc[22] = (*c >> 1) & 0x7; \
+ xmc[23] = (*c++ & 0x1) << 2; \
+ xmc[23] |= (*c >> 6) & 0x3; \
+ xmc[24] = (*c >> 3) & 0x7; \
+ xmc[25] = *c++ & 0x7; \
+ Nc[2] = (*c >> 1) & 0x7F; \
+ bc[2] = (*c++ & 0x1) << 1; /* 20 */ \
+ bc[2] |= (*c >> 7) & 0x1; \
+ Mc[2] = (*c >> 5) & 0x3; \
+ xmaxc[2] = (*c++ & 0x1F) << 1; \
+ xmaxc[2] |= (*c >> 7) & 0x1; \
+ xmc[26] = (*c >> 4) & 0x7; \
+ xmc[27] = (*c >> 1) & 0x7; \
+ xmc[28] = (*c++ & 0x1) << 2; \
+ xmc[28] |= (*c >> 6) & 0x3; \
+ xmc[29] = (*c >> 3) & 0x7; \
+ xmc[30] = *c++ & 0x7; \
+ xmc[31] = (*c >> 5) & 0x7; \
+ xmc[32] = (*c >> 2) & 0x7; \
+ xmc[33] = (*c++ & 0x3) << 1; \
+ xmc[33] |= (*c >> 7) & 0x1; \
+ xmc[34] = (*c >> 4) & 0x7; \
+ xmc[35] = (*c >> 1) & 0x7; \
+ xmc[36] = (*c++ & 0x1) << 2; \
+ xmc[36] |= (*c >> 6) & 0x3; \
+ xmc[37] = (*c >> 3) & 0x7; \
+ xmc[38] = *c++ & 0x7; \
+ Nc[3] = (*c >> 1) & 0x7F; \
+ bc[3] = (*c++ & 0x1) << 1; \
+ bc[3] |= (*c >> 7) & 0x1; \
+ Mc[3] = (*c >> 5) & 0x3; \
+ xmaxc[3] = (*c++ & 0x1F) << 1; \
+ xmaxc[3] |= (*c >> 7) & 0x1; \
+ xmc[39] = (*c >> 4) & 0x7; \
+ xmc[40] = (*c >> 1) & 0x7; \
+ xmc[41] = (*c++ & 0x1) << 2; \
+ xmc[41] |= (*c >> 6) & 0x3; \
+ xmc[42] = (*c >> 3) & 0x7; \
+ xmc[43] = *c++ & 0x7; /* 30 */ \
+ xmc[44] = (*c >> 5) & 0x7; \
+ xmc[45] = (*c >> 2) & 0x7; \
+ xmc[46] = (*c++ & 0x3) << 1; \
+ xmc[46] |= (*c >> 7) & 0x1; \
+ xmc[47] = (*c >> 4) & 0x7; \
+ xmc[48] = (*c >> 1) & 0x7; \
+ xmc[49] = (*c++ & 0x1) << 2; \
+ xmc[49] |= (*c >> 6) & 0x3; \
+ xmc[50] = (*c >> 3) & 0x7; \
+ xmc[51] = *c & 0x7; /* 33 */ \
+}
+
+static void conv66(gsm_byte * d, wav_byte * c) {
+ gsm_byte frame_chain;
+ unsigned int sr;
+ unsigned int LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4];
+
+ readGSM_33(d);
+ sr = 0;
+ sr = (sr >> 6) | (LARc[0] << 10);
+ sr = (sr >> 6) | (LARc[1] << 10);
+ *c++ = sr >> 4;
+ sr = (sr >> 5) | (LARc[2] << 11);
+ *c++ = sr >> 7;
+ sr = (sr >> 5) | (LARc[3] << 11);
+ sr = (sr >> 4) | (LARc[4] << 12);
+ *c++ = sr >> 6;
+ sr = (sr >> 4) | (LARc[5] << 12);
+ sr = (sr >> 3) | (LARc[6] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3) | (LARc[7] << 13);
+ sr = (sr >> 7) | (Nc[0] << 9);
+ *c++ = sr >> 5;
+ sr = (sr >> 2) | (bc[0] << 14);
+ sr = (sr >> 2) | (Mc[0] << 14);
+ sr = (sr >> 6) | (xmaxc[0] << 10);
+ *c++ = sr >> 3;
+ sr = (sr >> 3 )|( xmc[0] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[1] << 13);
+ sr = (sr >> 3 )|( xmc[2] << 13);
+ sr = (sr >> 3 )|( xmc[3] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[4] << 13);
+ sr = (sr >> 3 )|( xmc[5] << 13);
+ sr = (sr >> 3 )|( xmc[6] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[7] << 13);
+ sr = (sr >> 3 )|( xmc[8] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[9] << 13);
+ sr = (sr >> 3 )|( xmc[10] << 13);
+ sr = (sr >> 3 )|( xmc[11] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[12] << 13);
+ sr = (sr >> 7 )|( Nc[1] << 9);
+ *c++ = sr >> 5;
+ sr = (sr >> 2 )|( bc[1] << 14);
+ sr = (sr >> 2 )|( Mc[1] << 14);
+ sr = (sr >> 6 )|( xmaxc[1] << 10);
+ *c++ = sr >> 3;
+ sr = (sr >> 3 )|( xmc[13] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[14] << 13);
+ sr = (sr >> 3 )|( xmc[15] << 13);
+ sr = (sr >> 3 )|( xmc[16] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[17] << 13);
+ sr = (sr >> 3 )|( xmc[18] << 13);
+ sr = (sr >> 3 )|( xmc[19] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[20] << 13);
+ sr = (sr >> 3 )|( xmc[21] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[22] << 13);
+ sr = (sr >> 3 )|( xmc[23] << 13);
+ sr = (sr >> 3 )|( xmc[24] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[25] << 13);
+ sr = (sr >> 7 )|( Nc[2] << 9);
+ *c++ = sr >> 5;
+ sr = (sr >> 2 )|( bc[2] << 14);
+ sr = (sr >> 2 )|( Mc[2] << 14);
+ sr = (sr >> 6 )|( xmaxc[2] << 10);
+ *c++ = sr >> 3;
+ sr = (sr >> 3 )|( xmc[26] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[27] << 13);
+ sr = (sr >> 3 )|( xmc[28] << 13);
+ sr = (sr >> 3 )|( xmc[29] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[30] << 13);
+ sr = (sr >> 3 )|( xmc[31] << 13);
+ sr = (sr >> 3 )|( xmc[32] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[33] << 13);
+ sr = (sr >> 3 )|( xmc[34] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[35] << 13);
+ sr = (sr >> 3 )|( xmc[36] << 13);
+ sr = (sr >> 3 )|( xmc[37] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[38] << 13);
+ sr = (sr >> 7 )|( Nc[3] << 9);
+ *c++ = sr >> 5;
+ sr = (sr >> 2 )|( bc[3] << 14);
+ sr = (sr >> 2 )|( Mc[3] << 14);
+ sr = (sr >> 6 )|( xmaxc[3] << 10);
+ *c++ = sr >> 3;
+ sr = (sr >> 3 )|( xmc[39] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[40] << 13);
+ sr = (sr >> 3 )|( xmc[41] << 13);
+ sr = (sr >> 3 )|( xmc[42] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[43] << 13);
+ sr = (sr >> 3 )|( xmc[44] << 13);
+ sr = (sr >> 3 )|( xmc[45] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[46] << 13);
+ sr = (sr >> 3 )|( xmc[47] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[48] << 13);
+ sr = (sr >> 3 )|( xmc[49] << 13);
+ sr = (sr >> 3 )|( xmc[50] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[51] << 13);
+ sr = sr >> 4;
+ *c = sr >> 8;
+ frame_chain = *c;
+ readGSM_33(d+33);// puts all the parameters into LARc etc.
+
+
+ sr = 0;
+// sr = (sr >> 4 )|( s->frame_chain << 12);
+ sr = (sr >> 4 )|( frame_chain << 12);
+
+ sr = (sr >> 6 )|( LARc[0] << 10);
+ *c++ = sr >> 6;
+ sr = (sr >> 6 )|( LARc[1] << 10);
+ *c++ = sr >> 8;
+ sr = (sr >> 5 )|( LARc[2] << 11);
+ sr = (sr >> 5 )|( LARc[3] << 11);
+ *c++ = sr >> 6;
+ sr = (sr >> 4 )|( LARc[4] << 12);
+ sr = (sr >> 4 )|( LARc[5] << 12);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( LARc[6] << 13);
+ sr = (sr >> 3 )|( LARc[7] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 7 )|( Nc[0] << 9);
+ sr = (sr >> 2 )|( bc[0] << 14);
+ *c++ = sr >> 7;
+ sr = (sr >> 2 )|( Mc[0] << 14);
+ sr = (sr >> 6 )|( xmaxc[0] << 10);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[0] << 13);
+ sr = (sr >> 3 )|( xmc[1] << 13);
+ sr = (sr >> 3 )|( xmc[2] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[3] << 13);
+ sr = (sr >> 3 )|( xmc[4] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[5] << 13);
+ sr = (sr >> 3 )|( xmc[6] << 13);
+ sr = (sr >> 3 )|( xmc[7] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[8] << 13);
+ sr = (sr >> 3 )|( xmc[9] << 13);
+ sr = (sr >> 3 )|( xmc[10] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[11] << 13);
+ sr = (sr >> 3 )|( xmc[12] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 7 )|( Nc[1] << 9);
+ sr = (sr >> 2 )|( bc[1] << 14);
+ *c++ = sr >> 7;
+ sr = (sr >> 2 )|( Mc[1] << 14);
+ sr = (sr >> 6 )|( xmaxc[1] << 10);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[13] << 13);
+ sr = (sr >> 3 )|( xmc[14] << 13);
+ sr = (sr >> 3 )|( xmc[15] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[16] << 13);
+ sr = (sr >> 3 )|( xmc[17] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[18] << 13);
+ sr = (sr >> 3 )|( xmc[19] << 13);
+ sr = (sr >> 3 )|( xmc[20] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[21] << 13);
+ sr = (sr >> 3 )|( xmc[22] << 13);
+ sr = (sr >> 3 )|( xmc[23] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[24] << 13);
+ sr = (sr >> 3 )|( xmc[25] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 7 )|( Nc[2] << 9);
+ sr = (sr >> 2 )|( bc[2] << 14);
+ *c++ = sr >> 7;
+ sr = (sr >> 2 )|( Mc[2] << 14);
+ sr = (sr >> 6 )|( xmaxc[2] << 10);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[26] << 13);
+ sr = (sr >> 3 )|( xmc[27] << 13);
+ sr = (sr >> 3 )|( xmc[28] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[29] << 13);
+ sr = (sr >> 3 )|( xmc[30] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[31] << 13);
+ sr = (sr >> 3 )|( xmc[32] << 13);
+ sr = (sr >> 3 )|( xmc[33] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[34] << 13);
+ sr = (sr >> 3 )|( xmc[35] << 13);
+ sr = (sr >> 3 )|( xmc[36] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[37] << 13);
+ sr = (sr >> 3 )|( xmc[38] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 7 )|( Nc[3] << 9);
+ sr = (sr >> 2 )|( bc[3] << 14);
+ *c++ = sr >> 7;
+ sr = (sr >> 2 )|( Mc[3] << 14);
+ sr = (sr >> 6 )|( xmaxc[3] << 10);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[39] << 13);
+ sr = (sr >> 3 )|( xmc[40] << 13);
+ sr = (sr >> 3 )|( xmc[41] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[42] << 13);
+ sr = (sr >> 3 )|( xmc[43] << 13);
+ *c++ = sr >> 8;
+ sr = (sr >> 3 )|( xmc[44] << 13);
+ sr = (sr >> 3 )|( xmc[45] << 13);
+ sr = (sr >> 3 )|( xmc[46] << 13);
+ *c++ = sr >> 7;
+ sr = (sr >> 3 )|( xmc[47] << 13);
+ sr = (sr >> 3 )|( xmc[48] << 13);
+ sr = (sr >> 3 )|( xmc[49] << 13);
+ *c++ = sr >> 6;
+ sr = (sr >> 3 )|( xmc[50] << 13);
+ sr = (sr >> 3 )|( xmc[51] << 13);
+ *c++ = sr >> 8;
+
+}
+
+#define writeGSM_33(c1) { \
+ gsm_byte *c = (c1); \
+ *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ \
+ | ((LARc[0] >> 2) & 0xF); \
+ *c++ = ((LARc[0] & 0x3) << 6) \
+ | (LARc[1] & 0x3F); \
+ *c++ = ((LARc[2] & 0x1F) << 3) \
+ | ((LARc[3] >> 2) & 0x7); \
+ *c++ = ((LARc[3] & 0x3) << 6) \
+ | ((LARc[4] & 0xF) << 2) \
+ | ((LARc[5] >> 2) & 0x3); \
+ *c++ = ((LARc[5] & 0x3) << 6) \
+ | ((LARc[6] & 0x7) << 3) \
+ | (LARc[7] & 0x7); \
+ *c++ = ((Nc[0] & 0x7F) << 1) \
+ | ((bc[0] >> 1) & 0x1); \
+ *c++ = ((bc[0] & 0x1) << 7) \
+ | ((Mc[0] & 0x3) << 5) \
+ | ((xmaxc[0] >> 1) & 0x1F); \
+ *c++ = ((xmaxc[0] & 0x1) << 7) \
+ | ((xmc[0] & 0x7) << 4) \
+ | ((xmc[1] & 0x7) << 1) \
+ | ((xmc[2] >> 2) & 0x1); \
+ *c++ = ((xmc[2] & 0x3) << 6) \
+ | ((xmc[3] & 0x7) << 3) \
+ | (xmc[4] & 0x7); \
+ *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ \
+ | ((xmc[6] & 0x7) << 2) \
+ | ((xmc[7] >> 1) & 0x3); \
+ *c++ = ((xmc[7] & 0x1) << 7) \
+ | ((xmc[8] & 0x7) << 4) \
+ | ((xmc[9] & 0x7) << 1) \
+ | ((xmc[10] >> 2) & 0x1); \
+ *c++ = ((xmc[10] & 0x3) << 6) \
+ | ((xmc[11] & 0x7) << 3) \
+ | (xmc[12] & 0x7); \
+ *c++ = ((Nc[1] & 0x7F) << 1) \
+ | ((bc[1] >> 1) & 0x1); \
+ *c++ = ((bc[1] & 0x1) << 7) \
+ | ((Mc[1] & 0x3) << 5) \
+ | ((xmaxc[1] >> 1) & 0x1F); \
+ *c++ = ((xmaxc[1] & 0x1) << 7) \
+ | ((xmc[13] & 0x7) << 4) \
+ | ((xmc[14] & 0x7) << 1) \
+ | ((xmc[15] >> 2) & 0x1); \
+ *c++ = ((xmc[15] & 0x3) << 6) \
+ | ((xmc[16] & 0x7) << 3) \
+ | (xmc[17] & 0x7); \
+ *c++ = ((xmc[18] & 0x7) << 5) \
+ | ((xmc[19] & 0x7) << 2) \
+ | ((xmc[20] >> 1) & 0x3); \
+ *c++ = ((xmc[20] & 0x1) << 7) \
+ | ((xmc[21] & 0x7) << 4) \
+ | ((xmc[22] & 0x7) << 1) \
+ | ((xmc[23] >> 2) & 0x1); \
+ *c++ = ((xmc[23] & 0x3) << 6) \
+ | ((xmc[24] & 0x7) << 3) \
+ | (xmc[25] & 0x7); \
+ *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ \
+ | ((bc[2] >> 1) & 0x1); \
+ *c++ = ((bc[2] & 0x1) << 7) \
+ | ((Mc[2] & 0x3) << 5) \
+ | ((xmaxc[2] >> 1) & 0x1F); \
+ *c++ = ((xmaxc[2] & 0x1) << 7) \
+ | ((xmc[26] & 0x7) << 4) \
+ | ((xmc[27] & 0x7) << 1) \
+ | ((xmc[28] >> 2) & 0x1); \
+ *c++ = ((xmc[28] & 0x3) << 6) \
+ | ((xmc[29] & 0x7) << 3) \
+ | (xmc[30] & 0x7); \
+ *c++ = ((xmc[31] & 0x7) << 5) \
+ | ((xmc[32] & 0x7) << 2) \
+ | ((xmc[33] >> 1) & 0x3); \
+ *c++ = ((xmc[33] & 0x1) << 7) \
+ | ((xmc[34] & 0x7) << 4) \
+ | ((xmc[35] & 0x7) << 1) \
+ | ((xmc[36] >> 2) & 0x1); \
+ *c++ = ((xmc[36] & 0x3) << 6) \
+ | ((xmc[37] & 0x7) << 3) \
+ | (xmc[38] & 0x7); \
+ *c++ = ((Nc[3] & 0x7F) << 1) \
+ | ((bc[3] >> 1) & 0x1); \
+ *c++ = ((bc[3] & 0x1) << 7) \
+ | ((Mc[3] & 0x3) << 5) \
+ | ((xmaxc[3] >> 1) & 0x1F); \
+ *c++ = ((xmaxc[3] & 0x1) << 7) \
+ | ((xmc[39] & 0x7) << 4) \
+ | ((xmc[40] & 0x7) << 1) \
+ | ((xmc[41] >> 2) & 0x1); \
+ *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ \
+ | ((xmc[42] & 0x7) << 3) \
+ | (xmc[43] & 0x7); \
+ *c++ = ((xmc[44] & 0x7) << 5) \
+ | ((xmc[45] & 0x7) << 2) \
+ | ((xmc[46] >> 1) & 0x3); \
+ *c++ = ((xmc[46] & 0x1) << 7) \
+ | ((xmc[47] & 0x7) << 4) \
+ | ((xmc[48] & 0x7) << 1) \
+ | ((xmc[49] >> 2) & 0x1); \
+ *c++ = ((xmc[49] & 0x3) << 6) \
+ | ((xmc[50] & 0x7) << 3) \
+ | (xmc[51] & 0x7); \
+}
+
+static void conv65( wav_byte * c, gsm_byte * d){
+
+ unsigned int sr = 0;
+ unsigned int frame_chain;
+ unsigned int LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4];
+
+ sr = *c++;
+ LARc[0] = sr & 0x3f; sr >>= 6;
+ sr |= (uword)*c++ << 2;
+ LARc[1] = sr & 0x3f; sr >>= 6;
+ sr |= (uword)*c++ << 4;
+ LARc[2] = sr & 0x1f; sr >>= 5;
+ LARc[3] = sr & 0x1f; sr >>= 5;
+ sr |= (uword)*c++ << 2;
+ LARc[4] = sr & 0xf; sr >>= 4;
+ LARc[5] = sr & 0xf; sr >>= 4;
+ sr |= (uword)*c++ << 2; /* 5 */
+ LARc[6] = sr & 0x7; sr >>= 3;
+ LARc[7] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 4;
+ Nc[0] = sr & 0x7f; sr >>= 7;
+ bc[0] = sr & 0x3; sr >>= 2;
+ Mc[0] = sr & 0x3; sr >>= 2;
+ sr |= (uword)*c++ << 1;
+ xmaxc[0] = sr & 0x3f; sr >>= 6;
+ xmc[0] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[1] = sr & 0x7; sr >>= 3;
+ xmc[2] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[3] = sr & 0x7; sr >>= 3;
+ xmc[4] = sr & 0x7; sr >>= 3;
+ xmc[5] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1; /* 10 */
+ xmc[6] = sr & 0x7; sr >>= 3;
+ xmc[7] = sr & 0x7; sr >>= 3;
+ xmc[8] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[9] = sr & 0x7; sr >>= 3;
+ xmc[10] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[11] = sr & 0x7; sr >>= 3;
+ xmc[12] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 4;
+ Nc[1] = sr & 0x7f; sr >>= 7;
+ bc[1] = sr & 0x3; sr >>= 2;
+ Mc[1] = sr & 0x3; sr >>= 2;
+ sr |= (uword)*c++ << 1;
+ xmaxc[1] = sr & 0x3f; sr >>= 6;
+ xmc[13] = sr & 0x7; sr >>= 3;
+ sr = *c++; /* 15 */
+ xmc[14] = sr & 0x7; sr >>= 3;
+ xmc[15] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[16] = sr & 0x7; sr >>= 3;
+ xmc[17] = sr & 0x7; sr >>= 3;
+ xmc[18] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[19] = sr & 0x7; sr >>= 3;
+ xmc[20] = sr & 0x7; sr >>= 3;
+ xmc[21] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[22] = sr & 0x7; sr >>= 3;
+ xmc[23] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[24] = sr & 0x7; sr >>= 3;
+ xmc[25] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 4; /* 20 */
+ Nc[2] = sr & 0x7f; sr >>= 7;
+ bc[2] = sr & 0x3; sr >>= 2;
+ Mc[2] = sr & 0x3; sr >>= 2;
+ sr |= (uword)*c++ << 1;
+ xmaxc[2] = sr & 0x3f; sr >>= 6;
+ xmc[26] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[27] = sr & 0x7; sr >>= 3;
+ xmc[28] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[29] = sr & 0x7; sr >>= 3;
+ xmc[30] = sr & 0x7; sr >>= 3;
+ xmc[31] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[32] = sr & 0x7; sr >>= 3;
+ xmc[33] = sr & 0x7; sr >>= 3;
+ xmc[34] = sr & 0x7; sr >>= 3;
+ sr = *c++; /* 25 */
+ xmc[35] = sr & 0x7; sr >>= 3;
+ xmc[36] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[37] = sr & 0x7; sr >>= 3;
+ xmc[38] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 4;
+ Nc[3] = sr & 0x7f; sr >>= 7;
+ bc[3] = sr & 0x3; sr >>= 2;
+ Mc[3] = sr & 0x3; sr >>= 2;
+ sr |= (uword)*c++ << 1;
+ xmaxc[3] = sr & 0x3f; sr >>= 6;
+ xmc[39] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[40] = sr & 0x7; sr >>= 3;
+ xmc[41] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2; /* 30 */
+ xmc[42] = sr & 0x7; sr >>= 3;
+ xmc[43] = sr & 0x7; sr >>= 3;
+ xmc[44] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[45] = sr & 0x7; sr >>= 3;
+ xmc[46] = sr & 0x7; sr >>= 3;
+ xmc[47] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[49] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[50] = sr & 0x7; sr >>= 3;
+ xmc[51] = sr & 0x7; sr >>= 3;
+
+ frame_chain = sr & 0xf;
+
+
+ writeGSM_33(d);// LARc etc. -> array of 33 GSM bytes
+
+
+ sr = frame_chain;
+ sr |= (uword)*c++ << 4; /* 1 */
+ LARc[0] = sr & 0x3f; sr >>= 6;
+ LARc[1] = sr & 0x3f; sr >>= 6;
+ sr = *c++;
+ LARc[2] = sr & 0x1f; sr >>= 5;
+ sr |= (uword)*c++ << 3;
+ LARc[3] = sr & 0x1f; sr >>= 5;
+ LARc[4] = sr & 0xf; sr >>= 4;
+ sr |= (uword)*c++ << 2;
+ LARc[5] = sr & 0xf; sr >>= 4;
+ LARc[6] = sr & 0x7; sr >>= 3;
+ LARc[7] = sr & 0x7; sr >>= 3;
+ sr = *c++; /* 5 */
+ Nc[0] = sr & 0x7f; sr >>= 7;
+ sr |= (uword)*c++ << 1;
+ bc[0] = sr & 0x3; sr >>= 2;
+ Mc[0] = sr & 0x3; sr >>= 2;
+ sr |= (uword)*c++ << 5;
+ xmaxc[0] = sr & 0x3f; sr >>= 6;
+ xmc[0] = sr & 0x7; sr >>= 3;
+ xmc[1] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[2] = sr & 0x7; sr >>= 3;
+ xmc[3] = sr & 0x7; sr >>= 3;
+ xmc[4] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[5] = sr & 0x7; sr >>= 3;
+ xmc[6] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2; /* 10 */
+ xmc[7] = sr & 0x7; sr >>= 3;
+ xmc[8] = sr & 0x7; sr >>= 3;
+ xmc[9] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[10] = sr & 0x7; sr >>= 3;
+ xmc[11] = sr & 0x7; sr >>= 3;
+ xmc[12] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ Nc[1] = sr & 0x7f; sr >>= 7;
+ sr |= (uword)*c++ << 1;
+ bc[1] = sr & 0x3; sr >>= 2;
+ Mc[1] = sr & 0x3; sr >>= 2;
+ sr |= (uword)*c++ << 5;
+ xmaxc[1] = sr & 0x3f; sr >>= 6;
+ xmc[13] = sr & 0x7; sr >>= 3;
+ xmc[14] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1; /* 15 */
+ xmc[15] = sr & 0x7; sr >>= 3;
+ xmc[16] = sr & 0x7; sr >>= 3;
+ xmc[17] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[18] = sr & 0x7; sr >>= 3;
+ xmc[19] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[20] = sr & 0x7; sr >>= 3;
+ xmc[21] = sr & 0x7; sr >>= 3;
+ xmc[22] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[23] = sr & 0x7; sr >>= 3;
+ xmc[24] = sr & 0x7; sr >>= 3;
+ xmc[25] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ Nc[2] = sr & 0x7f; sr >>= 7;
+ sr |= (uword)*c++ << 1; /* 20 */
+ bc[2] = sr & 0x3; sr >>= 2;
+ Mc[2] = sr & 0x3; sr >>= 2;
+ sr |= (uword)*c++ << 5;
+ xmaxc[2] = sr & 0x3f; sr >>= 6;
+ xmc[26] = sr & 0x7; sr >>= 3;
+ xmc[27] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[28] = sr & 0x7; sr >>= 3;
+ xmc[29] = sr & 0x7; sr >>= 3;
+ xmc[30] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ xmc[31] = sr & 0x7; sr >>= 3;
+ xmc[32] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[33] = sr & 0x7; sr >>= 3;
+ xmc[34] = sr & 0x7; sr >>= 3;
+ xmc[35] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1; /* 25 */
+ xmc[36] = sr & 0x7; sr >>= 3;
+ xmc[37] = sr & 0x7; sr >>= 3;
+ xmc[38] = sr & 0x7; sr >>= 3;
+ sr = *c++;
+ Nc[3] = sr & 0x7f; sr >>= 7;
+ sr |= (uword)*c++ << 1;
+ bc[3] = sr & 0x3; sr >>= 2;
+ Mc[3] = sr & 0x3; sr >>= 2;
+ sr |= (uword)*c++ << 5;
+ xmaxc[3] = sr & 0x3f; sr >>= 6;
+ xmc[39] = sr & 0x7; sr >>= 3;
+ xmc[40] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[41] = sr & 0x7; sr >>= 3;
+ xmc[42] = sr & 0x7; sr >>= 3;
+ xmc[43] = sr & 0x7; sr >>= 3;
+ sr = *c++; /* 30 */
+ xmc[44] = sr & 0x7; sr >>= 3;
+ xmc[45] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 2;
+ xmc[46] = sr & 0x7; sr >>= 3;
+ xmc[47] = sr & 0x7; sr >>= 3;
+ xmc[48] = sr & 0x7; sr >>= 3;
+ sr |= (uword)*c++ << 1;
+ xmc[49] = sr & 0x7; sr >>= 3;
+ xmc[50] = sr & 0x7; sr >>= 3;
+ xmc[51] = sr & 0x7; sr >>= 3;
+ writeGSM_33(d+33);
+
+}
diff --git a/include/asterisk/channel_pvt.h b/include/asterisk/channel_pvt.h
index 6628e9d5f..bd75102e5 100755
--- a/include/asterisk/channel_pvt.h
+++ b/include/asterisk/channel_pvt.h
@@ -3,7 +3,7 @@
*
* Private channel definitions for channel implementations only.
*
- * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
+ * Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
@@ -40,8 +40,8 @@ struct ast_channel_pvt {
};
/* Create a channel structure */
-struct ast_channel *ast_channel_alloc();
-#define ast_channel_free(a) free(a)
+struct ast_channel *ast_channel_alloc(void);
+void ast_channel_free(struct ast_channel *);
#if defined(__cplusplus) || defined(c_plusplus)
}
diff --git a/include/asterisk/io.h b/include/asterisk/io.h
index 64d039a51..82060c20d 100755
--- a/include/asterisk/io.h
+++ b/include/asterisk/io.h
@@ -3,7 +3,7 @@
*
* Mark Spencer <markster@marko.net>
*
- * Copyright(C) 1999, Adtran, Inc.
+ * Copyright(C) Mark Spencer
*
* Distributed under the terms of the GNU General Public License (GPL) Version 2
*
@@ -38,10 +38,10 @@ extern "C" {
struct io_context;
/* Create a context for I/O operations */
-struct io_context *io_context_create();
+extern struct io_context *io_context_create(void);
/* Destroy a context for I/O operations */
-void io_context_destroy(struct io_context *ioc);
+extern void io_context_destroy(struct io_context *ioc);
typedef int (*ast_io_cb)(int *id, int fd, short events, void *cbdata);
#define AST_IO_CB(a) ((ast_io_cb)(a))
diff --git a/io.c b/io.c
index 2ec5b0218..aef361c64 100755
--- a/io.c
+++ b/io.c
@@ -3,7 +3,7 @@
*
* Mark Spencer <markster@marko.net>
*
- * Copyright(C) 1999, Adtran, Inc.
+ * Copyright(C) Mark Spencer
*
* Distributed under the terms of the GNU General Public License (GPL) Version 2
*
@@ -58,7 +58,7 @@ struct io_context {
};
-struct io_context *io_context_create()
+struct io_context *io_context_create(void)
{
/* Create an I/O context */
struct io_context *tmp;