summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2014-04-11 19:36:31 +0200
committerAlfred E. Heggestad <aeh@db.org>2014-04-11 19:36:31 +0200
commit2a9edfbd3d03c2925d5d7d23f435cc5730fe3622 (patch)
treee6dd3317f93bee44af70083e6aa62329853ec2bb
parent7766b0130f88d52e7dce1edb9439b81394b5213b (diff)
parent78271821396aad56bd7cbe83a6552a102b551aa6 (diff)
Merge branch 'master' into ausrc_api
-rw-r--r--docs/README1
-rw-r--r--modules/presence/subscriber.c2
-rw-r--r--modules/sndio/module.mk11
-rw-r--r--modules/sndio/sndio.c307
-rw-r--r--src/account.c18
-rw-r--r--src/call.c18
-rw-r--r--src/config.c4
-rw-r--r--src/core.h2
-rw-r--r--src/message.c11
-rw-r--r--src/sdp.c8
-rw-r--r--src/stream.c3
-rw-r--r--src/ua.c4
12 files changed, 356 insertions, 33 deletions
diff --git a/docs/README b/docs/README
index 2468bfd..f1efe03 100644
--- a/docs/README
+++ b/docs/README
@@ -187,6 +187,7 @@ selfview Video selfview module
silk SILK audio codec
snapshot Save video-stream as PNG images
sndfile Audio dumper using libsndfile
+sndio Audio driver for OpenBSD
speex Speex audio codec
speex_aec Acoustic Echo Cancellation (AEC) using libspeexdsp
speex_pp Audio pre-processor using libspeexdsp
diff --git a/modules/presence/subscriber.c b/modules/presence/subscriber.c
index 22361d5..b04fa7c 100644
--- a/modules/presence/subscriber.c
+++ b/modules/presence/subscriber.c
@@ -254,7 +254,7 @@ int subscriber_init(void)
struct sip_addr *addr = contact_addr(c);
struct pl val;
- if (0 == sip_param_decode(&addr->params, "presence", &val) &&
+ if (0 == msg_param_decode(&addr->params, "presence", &val) &&
0 == pl_strcasecmp(&val, "p2p")) {
err |= presence_alloc(le->data);
diff --git a/modules/sndio/module.mk b/modules/sndio/module.mk
new file mode 100644
index 0000000..79ace67
--- /dev/null
+++ b/modules/sndio/module.mk
@@ -0,0 +1,11 @@
+#
+# module.mk
+#
+# Copyright (C) 2014 Creytiv.com
+#
+
+MOD := sndio
+$(MOD)_SRCS += sndio.c
+$(MOD)_LFLAGS += -lsndio
+
+include mk/mod.mk
diff --git a/modules/sndio/sndio.c b/modules/sndio/sndio.c
new file mode 100644
index 0000000..ee0fd46
--- /dev/null
+++ b/modules/sndio/sndio.c
@@ -0,0 +1,307 @@
+/**
+ * @file sndio.c SndIO sound driver
+ *
+ * Copyright (C) 2014 Creytiv.com
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <sndio.h>
+#include <pthread.h>
+#include <re.h>
+#include <rem.h>
+#include <baresip.h>
+
+
+struct ausrc_st {
+ struct ausrc *as;
+ struct sio_hdl *hdl;
+ pthread_t thread;
+ size_t nbytes;
+ void *buf;
+ int run;
+ ausrc_read_h *rh;
+ void *arg;
+};
+
+struct auplay_st {
+ struct auplay *ap;
+ struct sio_hdl *hdl;
+ pthread_t thread;
+ size_t nbytes;
+ void *buf;
+ int run;
+ auplay_write_h *wh;
+ void *arg;
+};
+
+static struct ausrc *ausrc;
+static struct auplay *auplay;
+
+
+static struct sio_par *sndio_initpar(void *arg)
+{
+ struct sio_par *par;
+ struct auplay_prm *prm = arg;
+
+ if ((par = malloc(sizeof(struct sio_par))) == NULL)
+ return NULL;
+
+ sio_initpar(par);
+
+ /* sndio doesn't support a-low and u-low */
+ prm->fmt = AUFMT_S16LE;
+ par->bits = 16;
+ par->bps = SIO_BPS(par->bits);
+ par->sig = 1;
+ par->le = 1;
+
+ par->rchan = prm->ch;
+ par->pchan = prm->ch;
+ par->rate = prm->srate;
+
+ return par;
+}
+
+
+static void *read_thread(void *arg)
+{
+ struct ausrc_st *st = arg;
+
+ if (!sio_start(st->hdl)) {
+ warning("sndio: could not start record\n");
+ goto out;
+ }
+
+ while (st->run) {
+ sio_read(st->hdl, st->buf, st->nbytes);
+ st->rh(st->buf, st->nbytes, st->arg);
+ }
+
+ out:
+ return NULL;
+}
+
+
+static void *write_thread(void *arg)
+{
+ struct auplay_st *st = arg;
+
+ if (!sio_start(st->hdl)) {
+ warning("sndio: could not start playback\n");
+ goto out;
+ }
+
+ while (st->run) {
+ st->wh(st->buf, st->nbytes, st->arg);
+ sio_write(st->hdl, st->buf, st->nbytes);
+ }
+
+ out:
+ return NULL;
+}
+
+
+static void ausrc_destructor(void *arg)
+{
+ struct ausrc_st *st = arg;
+
+ if (st->run) {
+ st->run = false;
+ (void)pthread_join(st->thread, NULL);
+ }
+
+ sio_close(st->hdl);
+
+ mem_deref(st->buf);
+ mem_deref(st->as);
+}
+
+
+static void auplay_destructor(void *arg)
+{
+ struct auplay_st *st = arg;
+
+ if (st->run) {
+ st->run = false;
+ (void)pthread_join(st->thread, NULL);
+ }
+
+ sio_close(st->hdl);
+
+ mem_deref(st->buf);
+ mem_deref(st->ap);
+}
+
+
+static int src_alloc(struct ausrc_st **stp, struct ausrc *as,
+ struct media_ctx **ctx,
+ struct ausrc_prm *prm, const char *device,
+ ausrc_read_h *rh, ausrc_error_h *errh, void *arg)
+{
+ struct ausrc_st *st;
+ struct sio_par *par;
+ int err;
+ const char *name;
+
+ (void)ctx;
+ (void)errh;
+
+ if (!stp || !as || !prm)
+ return EINVAL;
+
+ name = (str_isset(device)) ? device : SIO_DEVANY;
+
+ if ((st = mem_zalloc(sizeof(*st), ausrc_destructor)) == NULL)
+ return ENOMEM;
+
+ st->as = mem_ref(as);
+ st->rh = rh;
+ st->arg = arg;
+ st->hdl = sio_open(name, SIO_REC, 0);
+
+ if (!st->hdl) {
+ warning("sndio: could not open ausrc device '%s'\n", name);
+ err = EINVAL;
+ goto out;
+ }
+
+ par = sndio_initpar(prm);
+ if (!par) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ if (!sio_setpar(st->hdl, par)) {
+ free(par);
+ err = EINVAL;
+ goto out;
+ }
+
+ if (!sio_getpar(st->hdl, par)) {
+ free(par);
+ err = EINVAL;
+ goto out;
+ }
+
+ st->nbytes = 2 * par->appbufsz;
+ st->buf = mem_alloc(st->nbytes, NULL);
+ if (!st->buf) {
+ free(par);
+ err = ENOMEM;
+ goto out;
+ }
+
+ free(par);
+
+ st->run = true;
+ err = pthread_create(&st->thread, NULL, read_thread, st);
+ if (err)
+ st->run = false;
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *stp = st;
+
+ return err;
+}
+
+
+static int play_alloc(struct auplay_st **stp, struct auplay *ap,
+ struct auplay_prm *prm, const char *device,
+ auplay_write_h *wh, void *arg)
+{
+ struct auplay_st *st;
+ struct sio_par *par;
+ int err;
+ const char *name;
+
+ if (!stp || !ap || !prm)
+ return EINVAL;
+
+ name = (str_isset(device)) ? device : SIO_DEVANY;
+
+ if ((st = mem_zalloc(sizeof(*st), auplay_destructor)) == NULL)
+ return ENOMEM;
+
+ st->ap = mem_ref(ap);
+ st->wh = wh;
+ st->arg = arg;
+ st->hdl = sio_open(name, SIO_PLAY, 0);
+
+ if (!st->hdl) {
+ warning("sndio: could not open auplay device '%s'\n", name);
+ err = EINVAL;
+ goto out;
+ }
+
+ par = sndio_initpar(prm);
+ if (!par) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ if (!sio_setpar(st->hdl, par)) {
+ free(par);
+ err = EINVAL;
+ goto out;
+ }
+
+ if (!sio_getpar(st->hdl, par)) {
+ free(par);
+ err = EINVAL;
+ goto out;
+ }
+
+ st->nbytes = 2 * par->appbufsz;
+ st->buf = mem_alloc(st->nbytes, NULL);
+ if (!st->buf) {
+ free(par);
+ err = ENOMEM;
+ goto out;
+ }
+
+ free(par);
+
+ st->run = true;
+ err = pthread_create(&st->thread, NULL, write_thread, st);
+ if (err)
+ st->run = false;
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *stp = st;
+
+ return err;
+}
+
+
+static int sndio_init(void)
+{
+ int err = 0;
+
+ err |= ausrc_register(&ausrc, "sndio", src_alloc);
+ err |= auplay_register(&auplay, "sndio", play_alloc);
+
+ return err;
+}
+
+
+static int sndio_close(void)
+{
+ ausrc = mem_deref(ausrc);
+ auplay = mem_deref(auplay);
+
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(sndio) = {
+ "sndio",
+ "sound",
+ sndio_init,
+ sndio_close
+};
diff --git a/src/account.c b/src/account.c
index 95ceeba..b8945b1 100644
--- a/src/account.c
+++ b/src/account.c
@@ -43,7 +43,7 @@ static int param_dstr(char **dstr, const struct pl *params, const char *name)
{
struct pl pl;
- if (sip_param_decode(params, name, &pl))
+ if (msg_param_decode(params, name, &pl))
return 0;
return pl_strdup(dstr, &pl);
@@ -54,7 +54,7 @@ static int param_u32(uint32_t *v, const struct pl *params, const char *name)
{
struct pl pl;
- if (sip_param_decode(params, name, &pl))
+ if (msg_param_decode(params, name, &pl))
return 0;
*v = pl_u32(&pl);
@@ -74,7 +74,7 @@ static int stunsrv_decode(struct account *acc, const struct sip_addr *aor)
memset(&uri, 0, sizeof(uri));
- if (0 == sip_param_decode(&aor->params, "stunserver", &srv)) {
+ if (0 == msg_param_decode(&aor->params, "stunserver", &srv)) {
info("using stunserver: '%r'\n", &srv);
@@ -134,7 +134,7 @@ static void answermode_decode(struct account *prm, const struct pl *pl)
{
struct pl amode;
- if (0 == sip_param_decode(pl, "answermode", &amode)) {
+ if (0 == msg_param_decode(pl, "answermode", &amode)) {
if (0 == pl_strcasecmp(&amode, "manual")) {
prm->answermode = ANSWERMODE_MANUAL;
@@ -180,12 +180,12 @@ static int audio_codecs_decode(struct account *acc, const struct pl *prm)
list_init(&acc->aucodecl);
- if (0 == sip_param_exists(prm, "audio_codecs", &tmp)) {
+ if (0 == msg_param_exists(prm, "audio_codecs", &tmp)) {
struct pl acs;
char cname[64];
unsigned i = 0;
- if (sip_param_decode(prm, "audio_codecs", &acs))
+ if (msg_param_decode(prm, "audio_codecs", &acs))
return 0;
while (0 == csl_parse(&acs, cname, sizeof(cname))) {
@@ -236,12 +236,12 @@ static int video_codecs_decode(struct account *acc, const struct pl *prm)
list_init(&acc->vidcodecl);
- if (0 == sip_param_exists(prm, "video_codecs", &tmp)) {
+ if (0 == msg_param_exists(prm, "video_codecs", &tmp)) {
struct pl vcs;
char cname[64];
unsigned i = 0;
- if (sip_param_decode(prm, "video_codecs", &vcs))
+ if (msg_param_decode(prm, "video_codecs", &vcs))
return 0;
while (0 == csl_parse(&vcs, cname, sizeof(cname))) {
@@ -298,7 +298,7 @@ static int sip_params_decode(struct account *acc, const struct sip_addr *aor)
err |= param_dstr(&acc->sipnat, &aor->params, "sipnat");
- if (0 == sip_param_decode(&aor->params, "auth_user", &auth_user))
+ if (0 == msg_param_decode(&aor->params, "auth_user", &auth_user))
err |= pl_strdup(&acc->auth_user, &auth_user);
else
err |= pl_strdup(&acc->auth_user, &aor->uri.user);
diff --git a/src/call.c b/src/call.c
index 41c6d16..a947c25 100644
--- a/src/call.c
+++ b/src/call.c
@@ -958,7 +958,8 @@ static int sipsess_answer_handler(const struct sip_msg *msg, void *arg)
MAGIC_CHECK(call);
- (void)sdp_decode_multipart(&msg->ctype, msg->mb);
+ if (msg_ctype_cmp(&msg->ctyp, "multipart", "mixed"))
+ (void)sdp_decode_multipart(&msg->ctyp.params, msg->mb);
err = sdp_decode(call->sdp, msg->mb, false);
if (err) {
@@ -1034,7 +1035,7 @@ static void sipsess_info_handler(struct sip *sip, const struct sip_msg *msg,
{
struct call *call = arg;
- if (!pl_strcasecmp(&msg->ctype, "application/dtmf-relay")) {
+ if (msg_ctype_cmp(&msg->ctyp, "application", "dtmf-relay")) {
struct pl body, sig, dur;
int err;
@@ -1067,8 +1068,8 @@ static void sipsess_info_handler(struct sip *sip, const struct sip_msg *msg,
}
}
#ifdef USE_VIDEO
- else if (!pl_strcasecmp(&msg->ctype,
- "application/media_control+xml")) {
+ else if (msg_ctype_cmp(&msg->ctyp,
+ "application", "media_control+xml")) {
call_handle_info_req(call, msg);
(void)sip_reply(sip, msg, 200, "OK");
}
@@ -1231,8 +1232,8 @@ static void sipsess_progr_handler(const struct sip_msg *msg, void *arg)
MAGIC_CHECK(call);
- info("call: SIP Progress: %u %r (%r)\n",
- msg->scode, &msg->reason, &msg->ctype);
+ info("call: SIP Progress: %u %r (%r/%r)\n",
+ msg->scode, &msg->reason, &msg->ctyp.type, &msg->ctyp.subtype);
if (msg->scode <= 100)
return;
@@ -1245,12 +1246,13 @@ static void sipsess_progr_handler(const struct sip_msg *msg, void *arg)
* we must also handle changes to/from 180 and 183,
* so we reset the media-stream/ringback each time.
*/
- if (!pl_strcasecmp(&msg->ctype, "application/sdp")
+ if (msg_ctype_cmp(&msg->ctyp, "application", "sdp")
&& mbuf_get_left(msg->mb)
&& !sdp_decode(call->sdp, msg->mb, false)) {
media = true;
}
- else if (!sdp_decode_multipart(&msg->ctype, msg->mb) &&
+ else if (msg_ctype_cmp(&msg->ctyp, "multipart", "mixed") &&
+ !sdp_decode_multipart(&msg->ctyp.params, msg->mb) &&
!sdp_decode(call->sdp, msg->mb, false)) {
media = true;
}
diff --git a/src/config.c b/src/config.c
index dd65c52..4a84b67 100644
--- a/src/config.c
+++ b/src/config.c
@@ -334,6 +334,8 @@ static const char *default_audio_device(void)
return "oss,/dev/dsp";
#elif defined (WIN32)
return "winwave,nil";
+#elif defined (ANDROID)
+ return "opensles";
#else
return "alsa,default";
#endif
@@ -583,6 +585,8 @@ int config_write_template(const char *file, const struct config *cfg)
(void)re_fprintf(f, "module\t\t\t" MOD_PRE "mda" MOD_EXT "\n");
#elif defined (DARWIN)
(void)re_fprintf(f, "module\t\t\t" MOD_PRE "coreaudio" MOD_EXT "\n");
+#elif defined (ANDROID)
+ (void)re_fprintf(f, "module\t\t\t" MOD_PRE "opensles" MOD_EXT "\n");
#else
(void)re_fprintf(f, "module\t\t\t" MOD_PRE "oss" MOD_EXT "\n");
(void)re_fprintf(f, "module\t\t\t" MOD_PRE "alsa" MOD_EXT "\n");
diff --git a/src/core.h b/src/core.h
index 9b92b4b..2f8784b 100644
--- a/src/core.h
+++ b/src/core.h
@@ -283,7 +283,7 @@ int sip_req_send(struct ua *ua, const char *method, const char *uri,
* SDP
*/
-int sdp_decode_multipart(const struct pl *ctype, struct mbuf *mb);
+int sdp_decode_multipart(const struct pl *ctype_prm, struct mbuf *mb);
const struct sdp_format *sdp_media_format_cycle(struct sdp_media *m);
diff --git a/src/message.c b/src/message.c
index b0e33e1..9d3662b 100644
--- a/src/message.c
+++ b/src/message.c
@@ -15,15 +15,12 @@ static void *recvarg;
static void handle_message(struct ua *ua, const struct sip_msg *msg)
{
- static const char *ctype_text = "text/plain";
- struct pl mtype;
+ static const char ctype_text[] = "text/plain";
+ struct pl ctype_pl = {ctype_text, sizeof(ctype_text)-1};
(void)ua;
- if (re_regex(msg->ctype.p, msg->ctype.l, "[^;]+", &mtype))
- mtype = msg->ctype;
-
- if (0==pl_strcasecmp(&mtype, ctype_text) && recvh) {
- recvh(&msg->from.auri, &msg->ctype, msg->mb, recvarg);
+ if (msg_ctype_cmp(&msg->ctyp, "text", "plain") && recvh) {
+ recvh(&msg->from.auri, &ctype_pl, msg->mb, recvarg);
(void)sip_reply(uag_sip(), msg, 200, "OK");
}
else {
diff --git a/src/sdp.c b/src/sdp.c
index 7a8ed29..8001253 100644
--- a/src/sdp.c
+++ b/src/sdp.c
@@ -145,18 +145,18 @@ static void decode_part(const struct pl *part, struct mbuf *mb)
/**
* Decode a multipart/mixed message and find the part with application/sdp
*/
-int sdp_decode_multipart(const struct pl *ctype, struct mbuf *mb)
+int sdp_decode_multipart(const struct pl *ctype_prm, struct mbuf *mb)
{
struct pl bnd, s, e, p;
char expr[64];
int err;
- if (!ctype || !mb)
+ if (!ctype_prm || !mb)
return EINVAL;
/* fetch the boundary tag, excluding quotes */
- err = re_regex(ctype->p, ctype->l,
- "multipart/mixed;[ \t]*boundary=[~]+", NULL, &bnd);
+ err = re_regex(ctype_prm->p, ctype_prm->l,
+ "boundary=[~]+", &bnd);
if (err)
return err;
diff --git a/src/stream.c b/src/stream.c
index 122cd96..f30bf0c 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -565,7 +565,8 @@ int stream_debug(struct re_printf *pf, const struct stream *s)
s->pt_enc);
sdp_media_raddr_rtcp(s->sdp, &rrtcp);
- err |= re_hprintf(pf, " remote: %J/%J\n",
+ err |= re_hprintf(pf, " local: %J, remote: %J/%J\n",
+ sdp_media_laddr(s->sdp),
sdp_media_raddr(s->sdp), &rrtcp);
err |= rtp_debug(pf, s->rtp);
diff --git a/src/ua.c b/src/ua.c
index 5e05e98..c30be6a 100644
--- a/src/ua.c
+++ b/src/ua.c
@@ -1424,14 +1424,14 @@ struct ua *uag_find_param(const char *name, const char *value)
if (value) {
- if (0 == sip_param_decode(&laddr->params, name, &val)
+ if (0 == msg_param_decode(&laddr->params, name, &val)
&&
0 == pl_strcasecmp(&val, value)) {
return ua;
}
}
else {
- if (0 == sip_param_exists(&laddr->params, name, &val))
+ if (0 == msg_param_exists(&laddr->params, name, &val))
return ua;
}
}