diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2011-04-16 10:52:23 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2011-04-16 10:52:23 +0000 |
commit | 5d6db880853f46a8f3d2ae1d1da067766e9f05da (patch) | |
tree | 7f1c988fb37b220df3a3b08e1fb43d1e1e7917ab /lib/libsndio | |
parent | bf35bb6dae41c97716f0b69c4725fb50e7b9b982 (diff) |
Make aucat audio and midi backends share the same code to communicate
with the server. As we're at it use the same protocol for midi and
audio. Now, both audio and midi code use the same SNDIO_DEBUG environment
variable to turn on/off DPRINTF's.
Diffstat (limited to 'lib/libsndio')
-rw-r--r-- | lib/libsndio/Makefile | 5 | ||||
-rw-r--r-- | lib/libsndio/aucat.c | 330 | ||||
-rw-r--r-- | lib/libsndio/aucat.h | 29 | ||||
-rw-r--r-- | lib/libsndio/debug.c | 41 | ||||
-rw-r--r-- | lib/libsndio/debug.h | 42 | ||||
-rw-r--r-- | lib/libsndio/mio.c | 19 | ||||
-rw-r--r-- | lib/libsndio/mio_aucat.c | 173 | ||||
-rw-r--r-- | lib/libsndio/mio_open.3 | 6 | ||||
-rw-r--r-- | lib/libsndio/mio_priv.h | 22 | ||||
-rw-r--r-- | lib/libsndio/mio_rmidi.c | 3 | ||||
-rw-r--r-- | lib/libsndio/sio.c | 29 | ||||
-rw-r--r-- | lib/libsndio/sio_aucat.c | 503 | ||||
-rw-r--r-- | lib/libsndio/sio_open.3 | 6 | ||||
-rw-r--r-- | lib/libsndio/sio_priv.h | 22 | ||||
-rw-r--r-- | lib/libsndio/sio_sun.c | 3 |
15 files changed, 627 insertions, 606 deletions
diff --git a/lib/libsndio/Makefile b/lib/libsndio/Makefile index 83426f85226..73913d645b6 100644 --- a/lib/libsndio/Makefile +++ b/lib/libsndio/Makefile @@ -1,8 +1,9 @@ -# $OpenBSD: Makefile,v 1.6 2011/04/12 21:40:22 ratchov Exp $ +# $OpenBSD: Makefile,v 1.7 2011/04/16 10:52:22 ratchov Exp $ LIB= sndio MAN= sio_open.3 mio_open.3 sndio.7 -SRCS= sio_aucat.c sio_sun.c sio.c mio_rmidi.c mio_aucat.c mio.c +SRCS= debug.c aucat.c sio_aucat.c sio_sun.c sio.c \ + mio_rmidi.c mio_aucat.c mio.c CFLAGS+=-Wall -Wstrict-prototypes -Werror -Wundef -DDEBUG \ -I${.CURDIR} -I${.CURDIR}/../../usr.bin/aucat diff --git a/lib/libsndio/aucat.c b/lib/libsndio/aucat.c new file mode 100644 index 00000000000..b2baa8d753e --- /dev/null +++ b/lib/libsndio/aucat.c @@ -0,0 +1,330 @@ +/* $OpenBSD: aucat.c,v 1.44 2011/04/16 10:52:22 ratchov Exp $ */ +/* + * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "aucat.h" +#include "debug.h" + +/* + * read a message, return 0 if not completed + */ +int +aucat_rmsg(struct aucat *hdl, int *eof) +{ + ssize_t n; + unsigned char *data; + + if (hdl->rstate != RSTATE_MSG) { + DPRINTF("aucat_rmsg: bad state\n"); + abort(); + } + while (hdl->rtodo > 0) { + data = (unsigned char *)&hdl->rmsg; + data += sizeof(struct amsg) - hdl->rtodo; + while ((n = read(hdl->fd, data, hdl->rtodo)) < 0) { + if (errno == EINTR) + continue; + if (errno != EAGAIN) { + *eof = 1; + DPERROR("aucat_rmsg: read"); + } + return 0; + } + if (n == 0) { + DPRINTF("aucat_rmsg: eof\n"); + *eof = 1; + return 0; + } + hdl->rtodo -= n; + } + if (hdl->rmsg.cmd == AMSG_DATA) { + hdl->rtodo = hdl->rmsg.u.data.size; + hdl->rstate = RSTATE_DATA; + } else { + hdl->rtodo = sizeof(struct amsg); + hdl->rstate = RSTATE_MSG; + } + return 1; +} + +/* + * write a message, return 0 if not completed + */ +int +aucat_wmsg(struct aucat *hdl, int *eof) +{ + ssize_t n; + unsigned char *data; + + if (hdl->wstate == WSTATE_IDLE) + hdl->wstate = WSTATE_MSG; + hdl->wtodo = sizeof(struct amsg); + if (hdl->wstate != WSTATE_MSG) { + DPRINTF("aucat_wmsg: bad state\n"); + abort(); + } + while (hdl->wtodo > 0) { + data = (unsigned char *)&hdl->wmsg; + data += sizeof(struct amsg) - hdl->wtodo; + while ((n = write(hdl->fd, data, hdl->wtodo)) < 0) { + if (errno == EINTR) + continue; + if (errno != EAGAIN) { + *eof = 1; + DPERROR("aucat_wmsg: write"); + } + return 0; + } + hdl->wtodo -= n; + } + if (hdl->wmsg.cmd == AMSG_DATA) { + hdl->wtodo = hdl->wmsg.u.data.size; + hdl->wstate = WSTATE_DATA; + } else { + hdl->wtodo = 0xdeadbeef; + hdl->wstate = WSTATE_IDLE; + } + return 1; +} + +size_t +aucat_rdata(struct aucat *hdl, void *buf, size_t len, int *eof) +{ + ssize_t n; + + if (hdl->rstate != RSTATE_DATA) { + DPRINTF("aucat_rdata: bad state\n"); + abort(); + } + if (len > hdl->rtodo) + len = hdl->rtodo; + while ((n = read(hdl->fd, buf, len)) < 0) { + if (errno == EINTR) + continue; + if (errno != EAGAIN) { + *eof = 1; + DPERROR("aucat_rdata: read"); + } + return 0; + } + if (n == 0) { + DPRINTF("aucat_rdata: eof\n"); + *eof = 1; + return 0; + } + hdl->rtodo -= n; + if (hdl->rtodo == 0) { + hdl->rstate = RSTATE_MSG; + hdl->rtodo = sizeof(struct amsg); + } + DPRINTF("aucat_rdata: read: n = %zd\n", n); + return n; +} + +size_t +aucat_wdata(struct aucat *hdl, const void *buf, size_t len, unsigned wbpf, int *eof) +{ + ssize_t n; + + switch (hdl->wstate) { + case WSTATE_IDLE: + if (len > AMSG_DATAMAX) + len = AMSG_DATAMAX; + len -= len % wbpf; + if (len == 0) + len = wbpf; + hdl->wmsg.cmd = AMSG_DATA; + hdl->wmsg.u.data.size = len; + hdl->wtodo = sizeof(struct amsg); + hdl->wstate = WSTATE_MSG; + /* FALLTHROUGH */ + case WSTATE_MSG: + if (!aucat_wmsg(hdl, eof)) + return 0; + } + if (len > hdl->wtodo) + len = hdl->wtodo; + if (len == 0) { + DPRINTF("aucat_wdata: len == 0\n"); + abort(); + } + while ((n = write(hdl->fd, buf, len)) < 0) { + if (errno == EINTR) + continue; + if (errno != EAGAIN) { + *eof = 1; + DPERROR("aucat_wdata: write"); + } + return 0; + } + DPRINTF("aucat_wdata: write: n = %zd\n", n); + hdl->wtodo -= n; + if (hdl->wtodo == 0) { + hdl->wstate = WSTATE_IDLE; + hdl->wtodo = 0xdeadbeef; + } + return n; +} + +int +aucat_open(struct aucat *hdl, const char *str, char *sock, unsigned mode, int nbio) +{ + extern char *__progname; + int s, eof; + char unit[4], *sep, *opt; + struct sockaddr_un ca; + socklen_t len = sizeof(struct sockaddr_un); + uid_t uid; + + sep = strchr(str, '.'); + if (sep == NULL) { + opt = "default"; + strlcpy(unit, str, sizeof(unit)); + } else { + opt = sep + 1; + if (sep - str >= sizeof(unit)) { + DPRINTF("aucat_init: %s: too long\n", str); + return 0; + } + strlcpy(unit, str, opt - str); + } + DPRINTF("aucat_init: trying %s -> %s.%s\n", str, unit, opt); + uid = geteuid(); + if (strchr(str, '/') != NULL) + return 0; + snprintf(ca.sun_path, sizeof(ca.sun_path), + "/tmp/aucat-%u/%s%s", uid, sock, unit); + ca.sun_family = AF_UNIX; + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) + goto bad_free; + while (connect(s, (struct sockaddr *)&ca, len) < 0) { + if (errno == EINTR) + continue; + DPERROR("aucat_init: connect"); + /* try shared server */ + snprintf(ca.sun_path, sizeof(ca.sun_path), + "/tmp/aucat/%s%s", sock, unit); + while (connect(s, (struct sockaddr *)&ca, len) < 0) { + if (errno == EINTR) + continue; + DPERROR("aucat_init: connect"); + goto bad_connect; + } + break; + } + if (fcntl(s, F_SETFD, FD_CLOEXEC) < 0) { + DPERROR("FD_CLOEXEC"); + goto bad_connect; + } + hdl->fd = s; + hdl->rstate = RSTATE_MSG; + hdl->rtodo = sizeof(struct amsg); + hdl->wstate = WSTATE_IDLE; + hdl->wtodo = 0xdeadbeef; + + /* + * say hello to server + */ + AMSG_INIT(&hdl->wmsg); + hdl->wmsg.cmd = AMSG_HELLO; + hdl->wmsg.u.hello.version = AMSG_VERSION; + hdl->wmsg.u.hello.mode = mode; + strlcpy(hdl->wmsg.u.hello.who, __progname, + sizeof(hdl->wmsg.u.hello.who)); + strlcpy(hdl->wmsg.u.hello.opt, opt, + sizeof(hdl->wmsg.u.hello.opt)); + hdl->wtodo = sizeof(struct amsg); + if (!aucat_wmsg(hdl, &eof)) + goto bad_connect; + hdl->rtodo = sizeof(struct amsg); + if (!aucat_rmsg(hdl, &eof)) { + DPRINTF("aucat_init: mode refused\n"); + goto bad_connect; + } + if (hdl->rmsg.cmd != AMSG_ACK) { + DPRINTF("aucat_init: protocol err\n"); + goto bad_connect; + } + return 1; + bad_connect: + while (close(s) < 0 && errno == EINTR) + ; /* retry */ + bad_free: + return 0; +} + +void +aucat_close(struct aucat *hdl, int eof) +{ + char dummy[1]; + + if (!eof) { + AMSG_INIT(&hdl->wmsg); + hdl->wmsg.cmd = AMSG_BYE; + hdl->wtodo = sizeof(struct amsg); + if (!aucat_wmsg(hdl, &eof)) + goto bad_close; + while (read(hdl->fd, dummy, 1) < 0 && errno == EINTR) + ; /* nothing */ + } + bad_close: + while (close(hdl->fd) < 0 && errno == EINTR) + ; /* nothing */ +} + +int +aucat_setfl(struct aucat *hdl, int nbio, int *eof) +{ + if (fcntl(hdl->fd, F_SETFL, nbio ? O_NONBLOCK : 0) < 0) { + DPERROR("aucat_setfl: fcntl"); + *eof = 1; + return 0; + } + return 1; +} + +int +aucat_pollfd(struct aucat *hdl, struct pollfd *pfd, int events) +{ + if (hdl->rstate == RSTATE_MSG) + events |= POLLIN; + pfd->fd = hdl->fd; + pfd->events = events; + return 1; +} + +int +aucat_revents(struct aucat *hdl, struct pollfd *pfd) +{ + int revents = pfd->revents; + + DPRINTF("aucat_revents: revents: %x\n", revents); + return revents; +} diff --git a/lib/libsndio/aucat.h b/lib/libsndio/aucat.h new file mode 100644 index 00000000000..aef23e00101 --- /dev/null +++ b/lib/libsndio/aucat.h @@ -0,0 +1,29 @@ +#ifndef AUCAT_H +#define AUCAT_H + +#include "amsg.h" + +struct aucat { + int fd; /* socket */ + struct amsg rmsg, wmsg; /* temporary messages */ + size_t wtodo, rtodo; /* bytes to complete the packet */ +#define RSTATE_MSG 0 /* message being received */ +#define RSTATE_DATA 1 /* data being received */ + unsigned rstate; /* one of above */ +#define WSTATE_IDLE 2 /* nothing to do */ +#define WSTATE_MSG 3 /* message being transferred */ +#define WSTATE_DATA 4 /* data being transferred */ + unsigned wstate; /* one of above */ +}; + +int aucat_rmsg(struct aucat *, int *); +int aucat_wmsg(struct aucat *, int *); +size_t aucat_rdata(struct aucat *, void *, size_t, int *); +size_t aucat_wdata(struct aucat *, const void *, size_t, unsigned, int *); +int aucat_open(struct aucat *, const char *, char *, unsigned, int); +void aucat_close(struct aucat *, int); +int aucat_pollfd(struct aucat *, struct pollfd *, int); +int aucat_revents(struct aucat *, struct pollfd *); +int aucat_setfl(struct aucat *, int, int *); + +#endif /* !defined(AUCAT_H) */ diff --git a/lib/libsndio/debug.c b/lib/libsndio/debug.c new file mode 100644 index 00000000000..05431cc6b3e --- /dev/null +++ b/lib/libsndio/debug.c @@ -0,0 +1,41 @@ +/* $OpenBSD: debug.c,v 1.1 2011/04/16 10:52:22 ratchov Exp $ */ +/* + * Copyright (c) 2011 Alexandre Ratchov <alex@caoua.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "debug.h" + +#ifdef DEBUG +/* + * debug level, -1 means uninitialized + */ +int sndio_debug = -1; + +void +sndio_debug_init(void) +{ + char *dbg; + + if (sndio_debug < 0) { + dbg = issetugid() ? NULL : getenv("SNDIO_DEBUG"); + if (!dbg || sscanf(dbg, "%u", &sndio_debug) != 1) + sndio_debug = 0; + } +} +#endif diff --git a/lib/libsndio/debug.h b/lib/libsndio/debug.h new file mode 100644 index 00000000000..53265f68550 --- /dev/null +++ b/lib/libsndio/debug.h @@ -0,0 +1,42 @@ +/* $OpenBSD: debug.h,v 1.1 2011/04/16 10:52:22 ratchov Exp $ */ +/* + * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef DEBUG_H +#define DEBUG_H + +#ifdef DEBUG +#include <stdio.h> + +#define DPRINTF(...) \ + do { \ + if (sndio_debug > 0) \ + fprintf(stderr, __VA_ARGS__); \ + } while(0) + +#define DPERROR(s) \ + do { \ + if (sndio_debug > 0) \ + perror(s); \ + } while(0) + +void sndio_debug_init(void); +extern int sndio_debug; +#else +#define DPRINTF(...) do {} while(0) +#define DPERROR(s) do {} while(0) +#endif + +#endif diff --git a/lib/libsndio/mio.c b/lib/libsndio/mio.c index 8c8d2c69edc..42785278a63 100644 --- a/lib/libsndio/mio.c +++ b/lib/libsndio/mio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mio.c,v 1.9 2011/04/12 21:40:22 ratchov Exp $ */ +/* $OpenBSD: mio.c,v 1.10 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -28,15 +28,9 @@ #include <string.h> #include <unistd.h> +#include "debug.h" #include "mio_priv.h" -#ifdef DEBUG -/* - * debug level, -1 means uninitialized - */ -int mio_debug = -1; -#endif - struct mio_hdl * mio_open(const char *str, unsigned mode, int nbio) { @@ -47,14 +41,9 @@ mio_open(const char *str, unsigned mode, int nbio) struct stat sb; char *sep, buf[4]; int len; -#ifdef DEBUG - char *dbg; - if (mio_debug < 0) { - dbg = issetugid() ? NULL : getenv("MIO_DEBUG"); - if (!dbg || sscanf(dbg, "%u", &mio_debug) != 1) - mio_debug = 0; - } +#ifdef DEBUG + sndio_debug_init(); #endif if ((mode & (MIO_OUT | MIO_IN)) == 0) return NULL; diff --git a/lib/libsndio/mio_aucat.c b/lib/libsndio/mio_aucat.c index c2748b78ec3..25d825453e2 100644 --- a/lib/libsndio/mio_aucat.c +++ b/lib/libsndio/mio_aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mio_aucat.c,v 1.1 2011/04/12 21:40:22 ratchov Exp $ */ +/* $OpenBSD: mio_aucat.c,v 1.2 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -27,12 +27,14 @@ #include <string.h> #include <unistd.h> -#include "amsg.h" +#include "aucat.h" +#include "debug.h" #include "mio_priv.h" struct mio_aucat_hdl { struct mio_hdl mio; - int fd; + struct aucat aucat; + int events; }; static void mio_aucat_close(struct mio_hdl *); @@ -52,111 +54,18 @@ static struct mio_ops mio_aucat_ops = { static struct mio_hdl * mio_xxx_open(const char *str, char *sock, unsigned mode, int nbio) { - extern char *__progname; - char unit[4], *sep, *opt; - struct amsg msg; - int s, n, todo; - unsigned char *data; struct mio_aucat_hdl *hdl; - struct sockaddr_un ca; - socklen_t len = sizeof(struct sockaddr_un); - uid_t uid; - - sep = strchr(str, '.'); - if (sep == NULL) { - opt = "default"; - strlcpy(unit, str, sizeof(unit)); - } else { - opt = sep + 1; - if (sep - str >= sizeof(unit)) { - DPRINTF("mio_aucat_open: %s: too long\n", str); - return NULL; - } - strlcpy(unit, str, opt - str); - } - DPRINTF("mio_aucat_open: trying %s -> %s.%s\n", str, unit, opt); - uid = geteuid(); - if (strchr(str, '/') != NULL) - return NULL; - snprintf(ca.sun_path, sizeof(ca.sun_path), - "/tmp/aucat-%u/%s%s", uid, sock, unit); - ca.sun_family = AF_UNIX; hdl = malloc(sizeof(struct mio_aucat_hdl)); if (hdl == NULL) return NULL; + if (!aucat_open(&hdl->aucat, str, sock, mode, nbio)) + goto bad; mio_create(&hdl->mio, &mio_aucat_ops, mode, nbio); - - s = socket(AF_UNIX, SOCK_STREAM, 0); - if (s < 0) - goto bad_free; - while (connect(s, (struct sockaddr *)&ca, len) < 0) { - if (errno == EINTR) - continue; - DPERROR("mio_aucat_open: connect"); - /* try shared server */ - snprintf(ca.sun_path, sizeof(ca.sun_path), - "/tmp/aucat/%s%s", sock, unit); - while (connect(s, (struct sockaddr *)&ca, len) < 0) { - if (errno == EINTR) - continue; - DPERROR("mio_aucat_open: connect"); - goto bad_connect; - } - break; - } - if (fcntl(s, F_SETFD, FD_CLOEXEC) < 0) { - DPERROR("FD_CLOEXEC"); - goto bad_connect; - } - hdl->fd = s; - - /* - * say hello to server - */ - AMSG_INIT(&msg); - msg.cmd = AMSG_HELLO; - msg.u.hello.version = AMSG_VERSION; - msg.u.hello.mode = mode; - strlcpy(msg.u.hello.opt, opt, sizeof(msg.u.hello.opt)); - strlcpy(msg.u.hello.who, __progname, sizeof(msg.u.hello.who)); - n = write(s, &msg, sizeof(struct amsg)); - if (n < 0) { - DPERROR("mio_aucat_open"); - goto bad_connect; - } - if (n != sizeof(struct amsg)) { - DPRINTF("mio_aucat_open: short write\n"); - goto bad_connect; - } - todo = sizeof(struct amsg); - data = (unsigned char *)&msg; - while (todo > 0) { - n = read(s, data, todo); - if (n < 0) { - DPERROR("mio_aucat_open"); - goto bad_connect; - } - if (n == 0) { - DPRINTF("mio_aucat_open: eof\n"); - goto bad_connect; - } - todo -= n; - data += n; - } - if (msg.cmd != AMSG_ACK) { - DPRINTF("mio_aucat_open: proto error\n"); - goto bad_connect; - } - if (nbio && fcntl(hdl->fd, F_SETFL, O_NONBLOCK) < 0) { - DPERROR("mio_aucat_open: fcntl(NONBLOCK)"); - goto bad_connect; - } + if (!aucat_setfl(&hdl->aucat, nbio, &hdl->mio.eof)) + goto bad; return (struct mio_hdl *)hdl; - bad_connect: - while (close(s) < 0 && errno == EINTR) - ; /* retry */ - bad_free: +bad: free(hdl); return NULL; } @@ -177,11 +86,10 @@ static void mio_aucat_close(struct mio_hdl *sh) { struct mio_aucat_hdl *hdl = (struct mio_aucat_hdl *)sh; - int rc; - do { - rc = close(hdl->fd); - } while (rc < 0 && errno == EINTR); + if (!hdl->mio.eof) + aucat_setfl(&hdl->aucat, 0, &hdl->mio.eof); + aucat_close(&hdl->aucat, hdl->mio.eof); free(hdl); } @@ -189,41 +97,20 @@ static size_t mio_aucat_read(struct mio_hdl *sh, void *buf, size_t len) { struct mio_aucat_hdl *hdl = (struct mio_aucat_hdl *)sh; - ssize_t n; - - while ((n = read(hdl->fd, buf, len)) < 0) { - if (errno == EINTR) - continue; - if (errno != EAGAIN) { - DPERROR("mio_aucat_read: read"); - hdl->mio.eof = 1; - } - return 0; - } - if (n == 0) { - DPRINTF("mio_aucat_read: eof\n"); - hdl->mio.eof = 1; - return 0; + + while (hdl->aucat.rstate == RSTATE_MSG) { + if (!aucat_rmsg(&hdl->aucat, &hdl->mio.eof)) + return 0; } - return n; + return aucat_rdata(&hdl->aucat, buf, len, &hdl->mio.eof); } static size_t mio_aucat_write(struct mio_hdl *sh, const void *buf, size_t len) { struct mio_aucat_hdl *hdl = (struct mio_aucat_hdl *)sh; - ssize_t n; - - while ((n = write(hdl->fd, buf, len)) < 0) { - if (errno == EINTR) - continue; - if (errno != EAGAIN) { - DPERROR("mio_aucat_write: write"); - hdl->mio.eof = 1; - } - return 0; - } - return n; + + return aucat_wdata(&hdl->aucat, buf, len, 1, &hdl->mio.eof); } static int @@ -231,13 +118,25 @@ mio_aucat_pollfd(struct mio_hdl *sh, struct pollfd *pfd, int events) { struct mio_aucat_hdl *hdl = (struct mio_aucat_hdl *)sh; - pfd->fd = hdl->fd; - pfd->events = events; - return 1; + hdl->events = events; + return aucat_pollfd(&hdl->aucat, pfd, events); } static int mio_aucat_revents(struct mio_hdl *sh, struct pollfd *pfd) { - return pfd->revents; + struct mio_aucat_hdl *hdl = (struct mio_aucat_hdl *)sh; + int revents = pfd->revents; + + if (revents & POLLIN) { + while (hdl->aucat.rstate == RSTATE_MSG) { + if (!aucat_rmsg(&hdl->aucat, &hdl->mio.eof)) + break; + } + if (hdl->aucat.rstate != RSTATE_DATA) + revents &= ~POLLIN; + } + if (hdl->mio.eof) + return POLLHUP; + return revents & (hdl->events | POLLHUP); } diff --git a/lib/libsndio/mio_open.3 b/lib/libsndio/mio_open.3 index 05a32f84439..76f5b03f2e6 100644 --- a/lib/libsndio/mio_open.3 +++ b/lib/libsndio/mio_open.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: mio_open.3,v 1.3 2009/07/26 12:42:48 ratchov Exp $ +.\" $OpenBSD: mio_open.3,v 1.4 2011/04/16 10:52:22 ratchov Exp $ .\" .\" Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: July 26 2009 $ +.Dd $Mdocdate: April 16 2011 $ .Dt MIO_OPEN 3 .Os .Sh NAME @@ -233,7 +233,7 @@ and functions return the number of bytes transferred. .Sh ENVIRONMENT .Bl -tag -width "MIO_DEBUGXXX" -compact -.It Ev MIO_DEBUG +.It Ev SNDIO_DEBUG The debug level: may be a value between 0 and 2. .El diff --git a/lib/libsndio/mio_priv.h b/lib/libsndio/mio_priv.h index 07d86684ab4..51ef244bc1d 100644 --- a/lib/libsndio/mio_priv.h +++ b/lib/libsndio/mio_priv.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mio_priv.h,v 1.5 2011/04/12 21:40:22 ratchov Exp $ */ +/* $OpenBSD: mio_priv.h,v 1.6 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -20,22 +20,6 @@ #include <sys/param.h> #include "sndio.h" -#ifdef DEBUG -#define DPRINTF(...) \ - do { \ - if (mio_debug > 0) \ - fprintf(stderr, __VA_ARGS__); \ - } while(0) -#define DPERROR(s) \ - do { \ - if (mio_debug > 0) \ - perror(s); \ - } while(0) -#else -#define DPRINTF(...) do {} while(0) -#define DPERROR(s) do {} while(0) -#endif - /* * private ``handle'' structure */ @@ -63,8 +47,4 @@ struct mio_hdl *mio_aucat_open(const char *, unsigned, int); void mio_create(struct mio_hdl *, struct mio_ops *, unsigned, int); void mio_destroy(struct mio_hdl *); -#ifdef DEBUG -extern int mio_debug; -#endif - #endif /* !defined(MIO_PRIV_H) */ diff --git a/lib/libsndio/mio_rmidi.c b/lib/libsndio/mio_rmidi.c index d311fe4452c..b40584a0bfc 100644 --- a/lib/libsndio/mio_rmidi.c +++ b/lib/libsndio/mio_rmidi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mio_rmidi.c,v 1.8 2011/04/12 21:40:22 ratchov Exp $ */ +/* $OpenBSD: mio_rmidi.c,v 1.9 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -27,6 +27,7 @@ #include <string.h> #include <unistd.h> +#include "debug.h" #include "mio_priv.h" struct mio_rmidi_hdl { diff --git a/lib/libsndio/sio.c b/lib/libsndio/sio.c index c67ed11b807..b59e1ee05f8 100644 --- a/lib/libsndio/sio.c +++ b/lib/libsndio/sio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sio.c,v 1.1 2011/04/08 11:18:07 ratchov Exp $ */ +/* $OpenBSD: sio.c,v 1.2 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -28,17 +28,11 @@ #include <string.h> #include <unistd.h> +#include "debug.h" #include "sio_priv.h" #define SIO_PAR_MAGIC 0x83b905a4 -#ifdef DEBUG -/* - * debug level, -1 means uninitialized - */ -int sio_debug = -1; -#endif - void sio_initpar(struct sio_par *par) { @@ -55,14 +49,9 @@ sio_open(const char *str, unsigned mode, int nbio) struct stat sb; char *sep, buf[NAME_MAX]; int len; -#ifdef DEBUG - char *dbg; - if (sio_debug < 0) { - dbg = issetugid() ? NULL : getenv("SIO_DEBUG"); - if (!dbg || sscanf(dbg, "%u", &sio_debug) != 1) - sio_debug = 0; - } +#ifdef DEBUG + sndio_debug_init(); #endif if ((mode & (SIO_PLAY | SIO_REC)) == 0) return NULL; @@ -304,7 +293,7 @@ sio_write(struct sio_hdl *hdl, const void *buf, size_t len) struct timeval tv0, tv1, dtv; unsigned us; - if (sio_debug >= 2) + if (sndio_debug >= 2) gettimeofday(&tv0, NULL); #endif @@ -337,7 +326,7 @@ sio_write(struct sio_hdl *hdl, const void *buf, size_t len) #endif } #ifdef DEBUG - if (sio_debug >= 2) { + if (sndio_debug >= 2) { gettimeofday(&tv1, NULL); timersub(&tv0, &hdl->tv, &dtv); DPRINTF("%ld.%06ld: ", dtv.tv_sec, dtv.tv_usec); @@ -376,7 +365,7 @@ sio_revents(struct sio_hdl *hdl, struct pollfd *pfd) struct timeval tv0, tv1, dtv; unsigned us; - if (sio_debug >= 2) + if (sndio_debug >= 2) gettimeofday(&tv0, NULL); #endif if (hdl->eof) @@ -388,7 +377,7 @@ sio_revents(struct sio_hdl *hdl, struct pollfd *pfd) if (!hdl->started) return revents & POLLHUP; #ifdef DEBUG - if (sio_debug >= 2) { + if (sndio_debug >= 2) { gettimeofday(&tv1, NULL); timersub(&tv0, &hdl->tv, &dtv); DPRINTF("%ld.%06ld: ", dtv.tv_sec, dtv.tv_usec); @@ -427,7 +416,7 @@ sio_onmove_cb(struct sio_hdl *hdl, int delta) struct timeval tv0, dtv; long long playpos; - if (sio_debug >= 3 && (hdl->mode & SIO_PLAY)) { + if (sndio_debug >= 3 && (hdl->mode & SIO_PLAY)) { gettimeofday(&tv0, NULL); timersub(&tv0, &hdl->tv, &dtv); DPRINTF("%ld.%06ld: ", dtv.tv_sec, dtv.tv_usec); diff --git a/lib/libsndio/sio_aucat.c b/lib/libsndio/sio_aucat.c index b0c42cb7bbb..3d1f1b177ca 100644 --- a/lib/libsndio/sio_aucat.c +++ b/lib/libsndio/sio_aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sio_aucat.c,v 1.1 2011/04/08 11:18:07 ratchov Exp $ */ +/* $OpenBSD: sio_aucat.c,v 1.2 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -27,23 +27,21 @@ #include <string.h> #include <unistd.h> -#include "amsg.h" +#include "aucat.h" +#include "debug.h" #include "sio_priv.h" struct sio_aucat_hdl { struct sio_hdl sio; - int fd; /* socket */ - struct amsg rmsg, wmsg; /* temporary messages */ - size_t wtodo, rtodo; /* bytes to complete the packet */ -#define STATE_IDLE 0 /* nothing to do */ -#define STATE_MSG 1 /* message being transferred */ -#define STATE_DATA 2 /* data being transferred */ - unsigned rstate, wstate; /* one of above */ + struct aucat aucat; unsigned rbpf, wbpf; /* read and write bytes-per-frame */ int maxwrite; /* latency constraint */ int events; /* events the user requested */ unsigned curvol, reqvol; /* current and requested volume */ int delta; /* some of received deltas */ +#define PSTATE_INIT 0 +#define PSTATE_RUN 1 + int pstate; }; static void sio_aucat_close(struct sio_hdl *); @@ -77,238 +75,96 @@ static struct sio_ops sio_aucat_ops = { }; /* - * read a message, return 0 if blocked - */ -static int -sio_aucat_rmsg(struct sio_aucat_hdl *hdl) -{ - ssize_t n; - unsigned char *data; - - while (hdl->rtodo > 0) { - data = (unsigned char *)&hdl->rmsg; - data += sizeof(struct amsg) - hdl->rtodo; - while ((n = read(hdl->fd, data, hdl->rtodo)) < 0) { - if (errno == EINTR) - continue; - if (errno != EAGAIN) { - hdl->sio.eof = 1; - DPERROR("sio_aucat_rmsg: read"); - } - return 0; - } - if (n == 0) { - DPRINTF("sio_aucat_rmsg: eof\n"); - hdl->sio.eof = 1; - return 0; - } - hdl->rtodo -= n; - } - return 1; -} - -/* - * write a message, return 0 if blocked - */ -static int -sio_aucat_wmsg(struct sio_aucat_hdl *hdl) -{ - ssize_t n; - unsigned char *data; - - while (hdl->wtodo > 0) { - data = (unsigned char *)&hdl->wmsg; - data += sizeof(struct amsg) - hdl->wtodo; - while ((n = write(hdl->fd, data, hdl->wtodo)) < 0) { - if (errno == EINTR) - continue; - if (errno != EAGAIN) { - hdl->sio.eof = 1; - DPERROR("sio_aucat_wmsg: write"); - } - return 0; - } - hdl->wtodo -= n; - } - return 1; -} - -/* * execute the next message, return 0 if blocked */ static int sio_aucat_runmsg(struct sio_aucat_hdl *hdl) { - if (!sio_aucat_rmsg(hdl)) + if (!aucat_rmsg(&hdl->aucat, &hdl->sio.eof)) return 0; - switch (hdl->rmsg.cmd) { + switch (hdl->aucat.rmsg.cmd) { case AMSG_DATA: - if (hdl->rmsg.u.data.size == 0 || - hdl->rmsg.u.data.size % hdl->rbpf) { + if (hdl->aucat.rmsg.u.data.size == 0 || + hdl->aucat.rmsg.u.data.size % hdl->rbpf) { DPRINTF("sio_aucat_runmsg: bad data message\n"); hdl->sio.eof = 1; return 0; } - hdl->rstate = STATE_DATA; - hdl->rtodo = hdl->rmsg.u.data.size; - break; + return 1; case AMSG_POS: - hdl->maxwrite += hdl->rmsg.u.ts.delta * (int)hdl->wbpf; + hdl->maxwrite += hdl->aucat.rmsg.u.ts.delta * (int)hdl->wbpf; DPRINTF("aucat: pos = %d, maxwrite = %d\n", - hdl->rmsg.u.ts.delta, hdl->maxwrite); - hdl->delta = hdl->rmsg.u.ts.delta; - hdl->rstate = STATE_MSG; - hdl->rtodo = sizeof(struct amsg); + hdl->aucat.rmsg.u.ts.delta, hdl->maxwrite); + hdl->delta = hdl->aucat.rmsg.u.ts.delta; break; case AMSG_MOVE: - hdl->maxwrite += hdl->rmsg.u.ts.delta * hdl->wbpf; - hdl->delta += hdl->rmsg.u.ts.delta; + hdl->maxwrite += hdl->aucat.rmsg.u.ts.delta * hdl->wbpf; + hdl->delta += hdl->aucat.rmsg.u.ts.delta; DPRINTF("aucat: move = %d, delta = %d, maxwrite = %d\n", - hdl->rmsg.u.ts.delta, hdl->delta, hdl->maxwrite); + hdl->aucat.rmsg.u.ts.delta, hdl->delta, hdl->maxwrite); if (hdl->delta >= 0) { sio_onmove_cb(&hdl->sio, hdl->delta); hdl->delta = 0; } - hdl->rstate = STATE_MSG; - hdl->rtodo = sizeof(struct amsg); break; case AMSG_SETVOL: - hdl->curvol = hdl->reqvol = hdl->rmsg.u.vol.ctl; + hdl->curvol = hdl->reqvol = hdl->aucat.rmsg.u.vol.ctl; sio_onvol_cb(&hdl->sio, hdl->curvol); - hdl->rstate = STATE_MSG; - hdl->rtodo = sizeof(struct amsg); break; - case AMSG_GETPAR: - case AMSG_ACK: - hdl->rstate = STATE_IDLE; - hdl->rtodo = 0xdeadbeef; + case AMSG_STOP: + hdl->pstate = PSTATE_INIT; break; default: - DPRINTF("sio_aucat_runmsg: unknown message\n"); + DPRINTF("sio_aucat_runmsg: unhandled message %u\n", hdl->aucat.rmsg.cmd); hdl->sio.eof = 1; return 0; } + hdl->aucat.rstate = RSTATE_MSG; + hdl->aucat.rtodo = sizeof(struct amsg); return 1; } +static int +sio_aucat_buildmsg(struct sio_aucat_hdl *hdl) +{ + if (hdl->curvol != hdl->reqvol) { + hdl->aucat.wstate = WSTATE_MSG; + hdl->aucat.wtodo = sizeof(struct amsg); + hdl->aucat.wmsg.cmd = AMSG_SETVOL; + hdl->aucat.wmsg.u.vol.ctl = hdl->reqvol; + hdl->curvol = hdl->reqvol; + return aucat_wmsg(&hdl->aucat, &hdl->sio.eof); + } + return 0; +} + struct sio_hdl * sio_aucat_open(const char *str, unsigned mode, int nbio) { - extern char *__progname; - int s; - char unit[4], *sep, *opt; struct sio_aucat_hdl *hdl; - struct sockaddr_un ca; - socklen_t len = sizeof(struct sockaddr_un); - uid_t uid; - - sep = strchr(str, '.'); - if (sep == NULL) { - opt = "default"; - strlcpy(unit, str, sizeof(unit)); - } else { - opt = sep + 1; - if (sep - str >= sizeof(unit)) { - DPRINTF("sio_open_aucat: %s: too long\n", str); - return NULL; - } - strlcpy(unit, str, opt - str); - } - DPRINTF("sio_open_aucat: trying %s -> %s.%s\n", str, unit, opt); - uid = geteuid(); - if (strchr(str, '/') != NULL) - return NULL; - snprintf(ca.sun_path, sizeof(ca.sun_path), - "/tmp/aucat-%u/softaudio%s", uid, unit); - ca.sun_family = AF_UNIX; hdl = malloc(sizeof(struct sio_aucat_hdl)); if (hdl == NULL) return NULL; - sio_create(&hdl->sio, &sio_aucat_ops, mode, nbio); - - s = socket(AF_UNIX, SOCK_STREAM, 0); - if (s < 0) - goto bad_free; - while (connect(s, (struct sockaddr *)&ca, len) < 0) { - if (errno == EINTR) - continue; - DPERROR("sio_open_aucat: connect"); - /* try shared server */ - snprintf(ca.sun_path, sizeof(ca.sun_path), - "/tmp/aucat/softaudio%s", unit); - while (connect(s, (struct sockaddr *)&ca, len) < 0) { - if (errno == EINTR) - continue; - DPERROR("sio_open_aucat: connect"); - goto bad_connect; - } - break; - } - if (fcntl(s, F_SETFD, FD_CLOEXEC) < 0) { - DPERROR("FD_CLOEXEC"); - goto bad_connect; + if (!aucat_open(&hdl->aucat, str, "softaudio", mode, nbio)) { + free(hdl); + return NULL; } - hdl->fd = s; - hdl->rstate = STATE_IDLE; - hdl->rtodo = 0xdeadbeef; - hdl->wstate = STATE_IDLE; - hdl->wtodo = 0xdeadbeef; + sio_create(&hdl->sio, &sio_aucat_ops, mode, nbio); hdl->curvol = SIO_MAXVOL; hdl->reqvol = SIO_MAXVOL; - - /* - * say hello to server - */ - AMSG_INIT(&hdl->wmsg); - hdl->wmsg.cmd = AMSG_HELLO; - hdl->wmsg.u.hello.version = AMSG_VERSION; - hdl->wmsg.u.hello.mode = mode; - strlcpy(hdl->wmsg.u.hello.who, __progname, - sizeof(hdl->wmsg.u.hello.who)); - strlcpy(hdl->wmsg.u.hello.opt, opt, - sizeof(hdl->wmsg.u.hello.opt)); - hdl->wtodo = sizeof(struct amsg); - if (!sio_aucat_wmsg(hdl)) - goto bad_connect; - hdl->rtodo = sizeof(struct amsg); - if (!sio_aucat_rmsg(hdl)) { - DPRINTF("sio_open_aucat: mode refused\n"); - goto bad_connect; - } - if (hdl->rmsg.cmd != AMSG_ACK) { - DPRINTF("sio_open_aucat: protocol err\n"); - goto bad_connect; - } + hdl->pstate = PSTATE_INIT; return (struct sio_hdl *)hdl; - bad_connect: - while (close(s) < 0 && errno == EINTR) - ; /* retry */ - bad_free: - free(hdl); - return NULL; } static void sio_aucat_close(struct sio_hdl *sh) { struct sio_aucat_hdl *hdl = (struct sio_aucat_hdl *)sh; - char dummy[1]; if (!hdl->sio.eof && hdl->sio.started) (void)sio_aucat_stop(&hdl->sio); - if (!hdl->sio.eof) { - AMSG_INIT(&hdl->wmsg); - hdl->wmsg.cmd = AMSG_BYE; - hdl->wtodo = sizeof(struct amsg); - if (!sio_aucat_wmsg(hdl)) - goto bad_close; - while (read(hdl->fd, dummy, 1) < 0 && errno == EINTR) - ; /* nothing */ - } - bad_close: - while (close(hdl->fd) < 0 && errno == EINTR) - ; /* nothing */ + aucat_close(&hdl->aucat, hdl->sio.eof); free(hdl); } @@ -329,18 +185,16 @@ sio_aucat_start(struct sio_hdl *sh) hdl->delta = 0; DPRINTF("aucat: start, maxwrite = %d\n", hdl->maxwrite); - AMSG_INIT(&hdl->wmsg); - hdl->wmsg.cmd = AMSG_START; - hdl->wtodo = sizeof(struct amsg); - if (!sio_aucat_wmsg(hdl)) + AMSG_INIT(&hdl->aucat.wmsg); + hdl->aucat.wmsg.cmd = AMSG_START; + hdl->aucat.wtodo = sizeof(struct amsg); + if (!aucat_wmsg(&hdl->aucat, &hdl->sio.eof)) return 0; - hdl->rstate = STATE_MSG; - hdl->rtodo = sizeof(struct amsg); - if (fcntl(hdl->fd, F_SETFL, O_NONBLOCK) < 0) { - DPERROR("sio_aucat_start: fcntl(0)"); - hdl->sio.eof = 1; + hdl->aucat.rstate = RSTATE_MSG; + hdl->aucat.rtodo = sizeof(struct amsg); + if (!aucat_setfl(&hdl->aucat, 1, &hdl->sio.eof)) return 0; - } + hdl->pstate = PSTATE_RUN; return 1; } @@ -352,28 +206,19 @@ sio_aucat_stop(struct sio_hdl *sh) struct sio_aucat_hdl *hdl = (struct sio_aucat_hdl *)sh; unsigned n, count; - if (fcntl(hdl->fd, F_SETFL, 0) < 0) { - DPERROR("sio_aucat_stop: fcntl(0)"); - hdl->sio.eof = 1; + if (!aucat_setfl(&hdl->aucat, 0, &hdl->sio.eof)) return 0; - } - /* * complete message or data block in progress */ - if (hdl->wstate == STATE_MSG) { - if (!sio_aucat_wmsg(hdl)) + if (hdl->aucat.wstate == WSTATE_MSG) { + if (!aucat_wmsg(&hdl->aucat, &hdl->sio.eof)) return 0; - if (hdl->wmsg.cmd == AMSG_DATA) { - hdl->wstate = STATE_DATA; - hdl->wtodo = hdl->wmsg.u.data.size; - } else - hdl->wstate = STATE_IDLE; } - if (hdl->wstate == STATE_DATA) { - hdl->maxwrite = hdl->wtodo; - while (hdl->wstate != STATE_IDLE) { - count = hdl->wtodo; + if (hdl->aucat.wstate == WSTATE_DATA) { + hdl->maxwrite = hdl->aucat.wtodo; + while (hdl->aucat.wstate != WSTATE_IDLE) { + count = hdl->aucat.wtodo; if (count > ZERO_MAX) count = ZERO_MAX; n = sio_aucat_write(&hdl->sio, zero, count); @@ -385,26 +230,22 @@ sio_aucat_stop(struct sio_hdl *sh) /* * send stop message */ - AMSG_INIT(&hdl->wmsg); - hdl->wmsg.cmd = AMSG_STOP; - hdl->wtodo = sizeof(struct amsg); - if (!sio_aucat_wmsg(hdl)) + AMSG_INIT(&hdl->aucat.wmsg); + hdl->aucat.wmsg.cmd = AMSG_STOP; + hdl->aucat.wtodo = sizeof(struct amsg); + if (!aucat_wmsg(&hdl->aucat, &hdl->sio.eof)) return 0; - if (hdl->rstate == STATE_IDLE) { - hdl->rstate = STATE_MSG; - hdl->rtodo = sizeof(struct amsg); - } /* * wait for the STOP ACK */ - while (hdl->rstate != STATE_IDLE) { - switch (hdl->rstate) { - case STATE_MSG: + while (hdl->pstate != PSTATE_INIT) { + switch (hdl->aucat.rstate) { + case RSTATE_MSG: if (!sio_aucat_runmsg(hdl)) return 0; break; - case STATE_DATA: + case RSTATE_DATA: if (!sio_aucat_read(&hdl->sio, zero, ZERO_MAX)) return 0; break; @@ -418,22 +259,22 @@ sio_aucat_setpar(struct sio_hdl *sh, struct sio_par *par) { struct sio_aucat_hdl *hdl = (struct sio_aucat_hdl *)sh; - AMSG_INIT(&hdl->wmsg); - hdl->wmsg.cmd = AMSG_SETPAR; - hdl->wmsg.u.par.bits = par->bits; - hdl->wmsg.u.par.bps = par->bps; - hdl->wmsg.u.par.sig = par->sig; - hdl->wmsg.u.par.le = par->le; - hdl->wmsg.u.par.msb = par->msb; - hdl->wmsg.u.par.rate = par->rate; - hdl->wmsg.u.par.appbufsz = par->appbufsz; - hdl->wmsg.u.par.xrun = par->xrun; + AMSG_INIT(&hdl->aucat.wmsg); + hdl->aucat.wmsg.cmd = AMSG_SETPAR; + hdl->aucat.wmsg.u.par.bits = par->bits; + hdl->aucat.wmsg.u.par.bps = par->bps; + hdl->aucat.wmsg.u.par.sig = par->sig; + hdl->aucat.wmsg.u.par.le = par->le; + hdl->aucat.wmsg.u.par.msb = par->msb; + hdl->aucat.wmsg.u.par.rate = par->rate; + hdl->aucat.wmsg.u.par.appbufsz = par->appbufsz; + hdl->aucat.wmsg.u.par.xrun = par->xrun; if (hdl->sio.mode & SIO_REC) - hdl->wmsg.u.par.rchan = par->rchan; + hdl->aucat.wmsg.u.par.rchan = par->rchan; if (hdl->sio.mode & SIO_PLAY) - hdl->wmsg.u.par.pchan = par->pchan; - hdl->wtodo = sizeof(struct amsg); - if (!sio_aucat_wmsg(hdl)) + hdl->aucat.wmsg.u.par.pchan = par->pchan; + hdl->aucat.wtodo = sizeof(struct amsg); + if (!aucat_wmsg(&hdl->aucat, &hdl->sio.eof)) return 0; return 1; } @@ -443,33 +284,33 @@ sio_aucat_getpar(struct sio_hdl *sh, struct sio_par *par) { struct sio_aucat_hdl *hdl = (struct sio_aucat_hdl *)sh; - AMSG_INIT(&hdl->wmsg); - hdl->wmsg.cmd = AMSG_GETPAR; - hdl->wtodo = sizeof(struct amsg); - if (!sio_aucat_wmsg(hdl)) + AMSG_INIT(&hdl->aucat.wmsg); + hdl->aucat.wmsg.cmd = AMSG_GETPAR; + hdl->aucat.wtodo = sizeof(struct amsg); + if (!aucat_wmsg(&hdl->aucat, &hdl->sio.eof)) return 0; - hdl->rtodo = sizeof(struct amsg); - if (!sio_aucat_rmsg(hdl)) + hdl->aucat.rtodo = sizeof(struct amsg); + if (!aucat_rmsg(&hdl->aucat, &hdl->sio.eof)) return 0; - if (hdl->rmsg.cmd != AMSG_GETPAR) { + if (hdl->aucat.rmsg.cmd != AMSG_GETPAR) { DPRINTF("sio_aucat_getpar: protocol err\n"); hdl->sio.eof = 1; return 0; } - par->bits = hdl->rmsg.u.par.bits; - par->bps = hdl->rmsg.u.par.bps; - par->sig = hdl->rmsg.u.par.sig; - par->le = hdl->rmsg.u.par.le; - par->msb = hdl->rmsg.u.par.msb; - par->rate = hdl->rmsg.u.par.rate; - par->bufsz = hdl->rmsg.u.par.bufsz; - par->appbufsz = hdl->rmsg.u.par.appbufsz; - par->xrun = hdl->rmsg.u.par.xrun; - par->round = hdl->rmsg.u.par.round; + par->bits = hdl->aucat.rmsg.u.par.bits; + par->bps = hdl->aucat.rmsg.u.par.bps; + par->sig = hdl->aucat.rmsg.u.par.sig; + par->le = hdl->aucat.rmsg.u.par.le; + par->msb = hdl->aucat.rmsg.u.par.msb; + par->rate = hdl->aucat.rmsg.u.par.rate; + par->bufsz = hdl->aucat.rmsg.u.par.bufsz; + par->appbufsz = hdl->aucat.rmsg.u.par.appbufsz; + par->xrun = hdl->aucat.rmsg.u.par.xrun; + par->round = hdl->aucat.rmsg.u.par.round; if (hdl->sio.mode & SIO_PLAY) - par->pchan = hdl->rmsg.u.par.pchan; + par->pchan = hdl->aucat.rmsg.u.par.pchan; if (hdl->sio.mode & SIO_REC) - par->rchan = hdl->rmsg.u.par.rchan; + par->rchan = hdl->aucat.rmsg.u.par.rchan; return 1; } @@ -480,15 +321,15 @@ sio_aucat_getcap(struct sio_hdl *sh, struct sio_cap *cap) unsigned i, bps, le, sig, chan, rindex, rmult; static unsigned rates[] = { 8000, 11025, 12000 }; - AMSG_INIT(&hdl->wmsg); - hdl->wmsg.cmd = AMSG_GETCAP; - hdl->wtodo = sizeof(struct amsg); - if (!sio_aucat_wmsg(hdl)) + AMSG_INIT(&hdl->aucat.wmsg); + hdl->aucat.wmsg.cmd = AMSG_GETCAP; + hdl->aucat.wtodo = sizeof(struct amsg); + if (!aucat_wmsg(&hdl->aucat, &hdl->sio.eof)) return 0; - hdl->rtodo = sizeof(struct amsg); - if (!sio_aucat_rmsg(hdl)) + hdl->aucat.rtodo = sizeof(struct amsg); + if (!aucat_rmsg(&hdl->aucat, &hdl->sio.eof)) return 0; - if (hdl->rmsg.cmd != AMSG_GETCAP) { + if (hdl->aucat.rmsg.cmd != AMSG_GETCAP) { DPRINTF("sio_aucat_getcap: protocol err\n"); hdl->sio.eof = 1; return 0; @@ -565,127 +406,30 @@ static size_t sio_aucat_read(struct sio_hdl *sh, void *buf, size_t len) { struct sio_aucat_hdl *hdl = (struct sio_aucat_hdl *)sh; - ssize_t n; - while (hdl->rstate != STATE_DATA) { - switch (hdl->rstate) { - case STATE_MSG: - if (!sio_aucat_runmsg(hdl)) - return 0; - break; - case STATE_IDLE: - DPRINTF("sio_aucat_read: unexpected idle state\n"); - hdl->sio.eof = 1; + while (hdl->aucat.rstate == RSTATE_MSG) { + if (!sio_aucat_runmsg(hdl)) return 0; - } - } - if (len > hdl->rtodo) - len = hdl->rtodo; - while ((n = read(hdl->fd, buf, len)) < 0) { - if (errno == EINTR) - continue; - if (errno != EAGAIN) { - hdl->sio.eof = 1; - DPERROR("sio_aucat_read: read"); - } - return 0; - } - if (n == 0) { - DPRINTF("sio_aucat_read: eof\n"); - hdl->sio.eof = 1; - return 0; - } - hdl->rtodo -= n; - if (hdl->rtodo == 0) { - hdl->rstate = STATE_MSG; - hdl->rtodo = sizeof(struct amsg); } - DPRINTF("aucat: read: n = %zd\n", n); - return n; -} - -static int -sio_aucat_buildmsg(struct sio_aucat_hdl *hdl, size_t len) -{ - unsigned sz; - - if (hdl->curvol != hdl->reqvol) { - hdl->wstate = STATE_MSG; - hdl->wtodo = sizeof(struct amsg); - hdl->wmsg.cmd = AMSG_SETVOL; - hdl->wmsg.u.vol.ctl = hdl->reqvol; - hdl->curvol = hdl->reqvol; - return 1; - } else if (len > 0 && hdl->maxwrite > 0) { - sz = len; - if (sz > AMSG_DATAMAX) - sz = AMSG_DATAMAX; - if (sz > hdl->maxwrite) - sz = hdl->maxwrite; - sz -= sz % hdl->wbpf; - if (sz == 0) - sz = hdl->wbpf; - hdl->wstate = STATE_MSG; - hdl->wtodo = sizeof(struct amsg); - hdl->wmsg.cmd = AMSG_DATA; - hdl->wmsg.u.data.size = sz; - return 1; - } - return 0; + return aucat_rdata(&hdl->aucat, buf, len, &hdl->sio.eof); } static size_t sio_aucat_write(struct sio_hdl *sh, const void *buf, size_t len) { struct sio_aucat_hdl *hdl = (struct sio_aucat_hdl *)sh; - ssize_t n; + size_t n; - while (hdl->wstate != STATE_DATA) { - switch (hdl->wstate) { - case STATE_IDLE: - if (!sio_aucat_buildmsg(hdl, len)) - return 0; - /* PASSTHROUGH */ - case STATE_MSG: - if (!sio_aucat_wmsg(hdl)) - return 0; - if (hdl->wmsg.cmd == AMSG_DATA) { - hdl->wstate = STATE_DATA; - hdl->wtodo = hdl->wmsg.u.data.size; - } else - hdl->wstate = STATE_IDLE; + while (hdl->aucat.wstate == WSTATE_IDLE) { + if (!sio_aucat_buildmsg(hdl)) break; - default: - DPRINTF("sio_aucat_write: bad state\n"); - abort(); - } } - if (hdl->maxwrite <= 0) + if (len <= 0 || hdl->maxwrite <= 0) return 0; if (len > hdl->maxwrite) len = hdl->maxwrite; - if (len > hdl->wtodo) - len = hdl->wtodo; - if (len == 0) { - DPRINTF("sio_aucat_write: len == 0\n"); - abort(); - } - while ((n = write(hdl->fd, buf, len)) < 0) { - if (errno == EINTR) - continue; - if (errno != EAGAIN) { - hdl->sio.eof = 1; - DPERROR("sio_aucat_write: write"); - } - return 0; - } + n = aucat_wdata(&hdl->aucat, buf, len, hdl->wbpf, &hdl->sio.eof); hdl->maxwrite -= n; - DPRINTF("aucat: write: n = %zd, maxwrite = %d\n", n, hdl->maxwrite); - hdl->wtodo -= n; - if (hdl->wtodo == 0) { - hdl->wstate = STATE_IDLE; - hdl->wtodo = 0xdeadbeef; - } return n; } @@ -703,12 +447,7 @@ sio_aucat_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events) hdl->events = events; if (hdl->maxwrite <= 0) events &= ~POLLOUT; - if (hdl->rstate == STATE_MSG) - events |= POLLIN; - pfd->fd = hdl->fd; - pfd->events = events; - DPRINTF("aucat: pollfd: %x -> %x\n", hdl->events, pfd->events); - return 1; + return aucat_pollfd(&hdl->aucat, pfd, events); } static int @@ -718,12 +457,12 @@ sio_aucat_revents(struct sio_hdl *sh, struct pollfd *pfd) int revents = pfd->revents; if (revents & POLLIN) { - while (hdl->rstate == STATE_MSG) { - if (!sio_aucat_runmsg(hdl)) { - revents &= ~POLLIN; + while (hdl->aucat.rstate == RSTATE_MSG) { + if (!sio_aucat_runmsg(hdl)) break; - } } + if (hdl->aucat.rstate != RSTATE_DATA) + revents &= ~POLLIN; } if (revents & POLLOUT) { if (hdl->maxwrite <= 0) @@ -731,7 +470,7 @@ sio_aucat_revents(struct sio_hdl *sh, struct pollfd *pfd) } if (hdl->sio.eof) return POLLHUP; - DPRINTF("aucat: revents: %x\n", revents & hdl->events); + DPRINTF("sio_aucat_revents: %x\n", revents & hdl->events); return revents & (hdl->events | POLLHUP); } diff --git a/lib/libsndio/sio_open.3 b/lib/libsndio/sio_open.3 index 981a37f8b42..4725b772da7 100644 --- a/lib/libsndio/sio_open.3 +++ b/lib/libsndio/sio_open.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sio_open.3,v 1.26 2010/11/06 22:17:26 jmc Exp $ +.\" $OpenBSD: sio_open.3,v 1.27 2011/04/16 10:52:22 ratchov Exp $ .\" .\" Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: November 6 2010 $ +.Dd $Mdocdate: April 16 2011 $ .Dt SIO_OPEN 3 .Os .Sh NAME @@ -729,7 +729,7 @@ Device to use if is called with a NULL .Va name argument. -.It Ev SIO_DEBUG +.It Ev SNDIO_DEBUG The debug level: may be a value between 0 and 2. .El diff --git a/lib/libsndio/sio_priv.h b/lib/libsndio/sio_priv.h index 4a292409538..1d7ed73e7b1 100644 --- a/lib/libsndio/sio_priv.h +++ b/lib/libsndio/sio_priv.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sio_priv.h,v 1.1 2011/04/08 11:18:07 ratchov Exp $ */ +/* $OpenBSD: sio_priv.h,v 1.2 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -20,22 +20,6 @@ #include <sys/param.h> #include "sndio.h" -#ifdef DEBUG -#define DPRINTF(...) \ - do { \ - if (sio_debug > 0) \ - fprintf(stderr, __VA_ARGS__); \ - } while(0) -#define DPERROR(s) \ - do { \ - if (sio_debug > 0) \ - perror(s); \ - } while(0) -#else -#define DPRINTF(...) do {} while(0) -#define DPERROR(s) do {} while(0) -#endif - /* * private ``handle'' structure */ @@ -85,8 +69,4 @@ void sio_destroy(struct sio_hdl *); void sio_onmove_cb(struct sio_hdl *, int); void sio_onvol_cb(struct sio_hdl *, unsigned); -#ifdef DEBUG -extern int sio_debug; -#endif - #endif /* !defined(SNDIO_PRIV_H) */ diff --git a/lib/libsndio/sio_sun.c b/lib/libsndio/sio_sun.c index 5399e698ed5..903db875c8c 100644 --- a/lib/libsndio/sio_sun.c +++ b/lib/libsndio/sio_sun.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sio_sun.c,v 1.1 2011/04/08 11:18:07 ratchov Exp $ */ +/* $OpenBSD: sio_sun.c,v 1.2 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -40,6 +40,7 @@ #include <string.h> #include <unistd.h> +#include "debug.h" #include "sio_priv.h" struct sio_sun_hdl { |