diff options
-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 | ||||
-rw-r--r-- | usr.bin/aucat/amsg.h | 4 | ||||
-rw-r--r-- | usr.bin/aucat/sock.c | 116 |
17 files changed, 679 insertions, 674 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 { diff --git a/usr.bin/aucat/amsg.h b/usr.bin/aucat/amsg.h index dca82864639..5a358887e8a 100644 --- a/usr.bin/aucat/amsg.h +++ b/usr.bin/aucat/amsg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amsg.h,v 1.18 2010/10/21 18:57:42 ratchov Exp $ */ +/* $OpenBSD: amsg.h,v 1.19 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -83,7 +83,7 @@ struct amsg { } vol; struct amsg_hello { uint16_t mode; /* bitmap of MODE_XXX */ -#define AMSG_VERSION 3 +#define AMSG_VERSION 4 uint8_t version; /* protocol version */ uint8_t reserved1[5]; /* for future use */ char opt[12]; /* profile name */ diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c index f349f026c2a..0f9624306d9 100644 --- a/usr.bin/aucat/sock.c +++ b/usr.bin/aucat/sock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sock.c,v 1.54 2011/04/08 13:00:57 ratchov Exp $ */ +/* $OpenBSD: sock.c,v 1.55 2011/04/16 10:52:22 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -707,7 +707,7 @@ sock_rdata(struct sock *f) unsigned n; #ifdef DEBUG - if (f->pstate != SOCK_MIDI && f->rtodo == 0) { + if (f->rtodo == 0) { sock_dbg(f); dbg_puts(": data block already read\n"); dbg_panic(); @@ -719,17 +719,12 @@ sock_rdata(struct sock *f) return 0; if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK)) return 0; - if (f->pstate == SOCK_MIDI) { - if (!rfile_do(p, obuf->len, NULL)) - return 0; - } else { - if (!rfile_do(p, f->rtodo, &n)) - return 0; - f->rtodo -= n; - if (f->pstate == SOCK_START) { - if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF)) - f->pstate = SOCK_READY; - } + if (!rfile_do(p, f->rtodo, &n)) + return 0; + f->rtodo -= n; + if (f->pstate == SOCK_START) { + if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF)) + f->pstate = SOCK_READY; } return 1; } @@ -746,7 +741,7 @@ sock_wdata(struct sock *f) unsigned n; #ifdef DEBUG - if (f->pstate != SOCK_MIDI && f->wtodo == 0) { + if (f->wtodo == 0) { sock_dbg(f); dbg_puts(": attempted to write zero-sized data block\n"); dbg_panic(); @@ -757,7 +752,7 @@ sock_wdata(struct sock *f) p = f->pipe.file.wproc; ibuf = LIST_FIRST(&p->ins); #ifdef DEBUG - if (f->pstate != SOCK_MIDI && ibuf == NULL) { + if (ibuf == NULL) { sock_dbg(f); dbg_puts(": attempted to write on detached buffer\n"); dbg_panic(); @@ -767,14 +762,9 @@ sock_wdata(struct sock *f) return 0; if (!ABUF_ROK(ibuf)) return 0; - if (f->pstate == SOCK_MIDI) { - if (!wfile_do(p, ibuf->len, NULL)) - return 0; - } else { - if (!wfile_do(p, f->wtodo, &n)) - return 0; - f->wtodo -= n; - } + if (!wfile_do(p, f->wtodo, &n)) + return 0; + f->wtodo -= n; return 1; } @@ -1102,8 +1092,8 @@ sock_execmsg(struct sock *f) dbg_puts(": DATA message\n"); } #endif - if (f->pstate != SOCK_RUN && f->pstate != SOCK_START && - f->pstate != SOCK_READY) { + if (f->pstate != SOCK_MIDI && f->pstate != SOCK_RUN && + f->pstate != SOCK_START && f->pstate != SOCK_READY) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1113,7 +1103,7 @@ sock_execmsg(struct sock *f) aproc_del(f->pipe.file.rproc); return 0; } - if (!(f->mode & MODE_PLAY)) { + if (!(f->mode & (MODE_PLAY | MODE_MIDIOUT))) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1147,7 +1137,8 @@ sock_execmsg(struct sock *f) f->rstate = SOCK_RDATA; f->rtodo = m->u.data.size / obuf->bpf; #ifdef DEBUG - if (f->rtodo > f->rmax && debug_level >= 2) { + if (debug_level >= 2 && + f->pstate != SOCK_MIDI && f->rtodo > f->rmax) { sock_dbg(f); dbg_puts(": received past current position, rtodo = "); dbg_putu(f->rtodo); @@ -1158,7 +1149,8 @@ sock_execmsg(struct sock *f) return 0; } #endif - f->rmax -= f->rtodo; + if (f->pstate != SOCK_MIDI) + f->rmax -= f->rtodo; if (f->rtodo == 0) { #ifdef DEBUG if (debug_level >= 1) { @@ -1221,7 +1213,7 @@ sock_execmsg(struct sock *f) else f->pstate = SOCK_STOP; AMSG_INIT(m); - m->cmd = AMSG_ACK; + m->cmd = AMSG_STOP; f->rstate = SOCK_RRET; f->rtodo = sizeof(struct amsg); break; @@ -1390,7 +1382,7 @@ sock_execmsg(struct sock *f) dbg_puts(": BYE message\n"); } #endif - if (f->pstate != SOCK_INIT) { + if (f->pstate != SOCK_INIT && f->pstate != SOCK_MIDI) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1423,18 +1415,6 @@ sock_buildmsg(struct sock *f) struct abuf *ibuf; unsigned size, max; - if (f->pstate == SOCK_MIDI) { -#ifdef DEBUG - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": switching to MIDI mode\n"); - } -#endif - f->wstate = SOCK_WDATA; - f->wtodo = 0; - return 1; - } - /* * Send initial position */ @@ -1509,7 +1489,8 @@ sock_buildmsg(struct sock *f) ibuf = LIST_FIRST(&p->ins); if (ibuf && ABUF_ROK(ibuf)) { #ifdef DEBUG - if (ibuf->used > f->wmax && debug_level >= 3) { + if (debug_level >= 3 && + f->pstate != SOCK_MIDI && ibuf->used > f->wmax) { sock_dbg(f); dbg_puts(": attempt to send past current position: used = "); dbg_putu(ibuf->used); @@ -1518,23 +1499,31 @@ sock_buildmsg(struct sock *f) dbg_puts("\n"); } #endif - max = AMSG_DATAMAX / ibuf->bpf; size = ibuf->used; - if (size > f->walign) - size = f->walign; - if (size > f->wmax) - size = f->wmax; - if (size > max) - size = max; - if (size == 0) - return 0; - f->walign -= size; - f->wmax -= size; - if (f->walign == 0) - f->walign = f->round; + if (f->pstate == SOCK_MIDI) { + if (size > AMSG_DATAMAX) + size = AMSG_DATAMAX; + if (size == 0) + return 0; + } else { + max = AMSG_DATAMAX / ibuf->bpf; + if (size > max) + size = max; + if (size > f->walign) + size = f->walign; + if (size > f->wmax) + size = f->wmax; + if (size == 0) + return 0; + f->walign -= size; + f->wmax -= size; + if (f->walign == 0) + f->walign = f->round; + size *= ibuf->bpf; + } AMSG_INIT(&f->wmsg); f->wmsg.cmd = AMSG_DATA; - f->wmsg.u.data.size = size * ibuf->bpf; + f->wmsg.u.data.size = size; f->wtodo = sizeof(struct amsg); f->wstate = SOCK_WMSG; return 1; @@ -1575,7 +1564,7 @@ sock_read(struct sock *f) case SOCK_RDATA: if (!sock_rdata(f)) return 0; - if (f->pstate != SOCK_MIDI && f->rtodo == 0) { + if (f->rtodo == 0) { f->rstate = SOCK_RMSG; f->rtodo = sizeof(struct amsg); } @@ -1623,13 +1612,8 @@ sock_return(struct sock *f) dbg_puts(": sent RRET message\n"); } #endif - if (f->pstate == SOCK_MIDI && (f->mode & MODE_MIDIOUT)) { - f->rstate = SOCK_RDATA; - f->rtodo = 0; - } else { - f->rstate = SOCK_RMSG; - f->rtodo = sizeof(struct amsg); - } + f->rstate = SOCK_RMSG; + f->rtodo = sizeof(struct amsg); if (f->pipe.file.state & FILE_RINUSE) break; f->pipe.file.state |= FILE_RINUSE; @@ -1687,7 +1671,7 @@ sock_write(struct sock *f) case SOCK_WDATA: if (!sock_wdata(f)) return 0; - if (f->pstate == SOCK_MIDI || f->wtodo > 0) + if (f->wtodo > 0) break; f->wstate = SOCK_WIDLE; f->wtodo = 0xdeadbeef; |