diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2008-11-11 19:39:36 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2008-11-11 19:39:36 +0000 |
commit | 66ce1beacebfce86cedb28308199ef5dbebb775c (patch) | |
tree | c5cd534c23219bbfd3653e19d8fea8a0499c1fc6 /lib/libsndio/aucat.c | |
parent | 3bc33a8c8c92b0092ffe1bb775de2cc4fc8ec6d0 (diff) |
expose a volume knob in the sndio API: add sio_setvol(3) and
sio_onvol(3) functions. The audio(4) backend tries to use the
inputs.dac, outputs.dac, outputs.output and outputs.master
controls (in this order). Add a sample file in
regress/lib/libsndio/vol/vol.c
Diffstat (limited to 'lib/libsndio/aucat.c')
-rw-r--r-- | lib/libsndio/aucat.c | 132 |
1 files changed, 90 insertions, 42 deletions
diff --git a/lib/libsndio/aucat.c b/lib/libsndio/aucat.c index 83689a16e37..14d6fc393ed 100644 --- a/lib/libsndio/aucat.c +++ b/lib/libsndio/aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aucat.c,v 1.1 2008/10/27 00:26:33 ratchov Exp $ */ +/* $OpenBSD: aucat.c,v 1.2 2008/11/11 19:39:35 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -40,6 +40,7 @@ struct aucat_hdl { 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 */ }; void aucat_close(struct sio_hdl *); @@ -52,6 +53,8 @@ size_t aucat_read(struct sio_hdl *, void *, size_t); size_t aucat_write(struct sio_hdl *, void *, size_t); int aucat_pollfd(struct sio_hdl *, struct pollfd *, int); int aucat_revents(struct sio_hdl *, struct pollfd *); +int aucat_setvol(struct sio_hdl *, unsigned); +void aucat_getvol(struct sio_hdl *); struct sio_ops aucat_ops = { aucat_close, @@ -63,7 +66,9 @@ struct sio_ops aucat_ops = { aucat_start, aucat_stop, aucat_pollfd, - aucat_revents + aucat_revents, + aucat_setvol, + aucat_getvol }; struct sio_hdl * @@ -101,6 +106,8 @@ sio_open_aucat(char *path, unsigned mode, int nbio) hdl->rtodo = 0xdeadbeef; hdl->wstate = STATE_IDLE; hdl->wtodo = 0xdeadbeef; + hdl->curvol = SIO_MAXVOL; + hdl->reqvol = SIO_MAXVOL; return (struct sio_hdl *)hdl; } @@ -434,15 +441,19 @@ aucat_read(struct sio_hdl *sh, void *buf, size_t len) return n; } -size_t -aucat_write(struct sio_hdl *sh, void *buf, size_t len) +int +aucat_buildmsg(struct aucat_hdl *hdl, size_t len) { - struct aucat_hdl *hdl = (struct aucat_hdl *)sh; unsigned sz; - ssize_t n; - switch (hdl->wstate) { - case STATE_IDLE: + 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) { sz = (len < AMSG_DATAMAX) ? len : AMSG_DATAMAX; sz -= sz % hdl->wbpf; if (sz == 0) @@ -451,44 +462,63 @@ aucat_write(struct sio_hdl *sh, void *buf, size_t len) hdl->wtodo = sizeof(struct amsg); hdl->wmsg.cmd = AMSG_DATA; hdl->wmsg.u.data.size = sz; - /* PASSTHROUGH */ - case STATE_MSG: - if (!aucat_wmsg(hdl)) - return 0; - hdl->wstate = STATE_DATA; - hdl->wtodo = hdl->wmsg.u.data.size; - /* PASSTHROUGH */ - case STATE_DATA: - if (hdl->maxwrite <= 0) - return 0; - if (len > hdl->maxwrite) - len = hdl->maxwrite; - if (len > hdl->wtodo) - len = hdl->wtodo; - if (len == 0) { - fprintf(stderr, "aucat_write: len == 0\n"); + return 1; + } + return 0; +} + +size_t +aucat_write(struct sio_hdl *sh, void *buf, size_t len) +{ + struct aucat_hdl *hdl = (struct aucat_hdl *)sh; + ssize_t n; + + while (hdl->wstate != STATE_DATA) { + switch (hdl->wstate) { + case STATE_IDLE: + if (!aucat_buildmsg(hdl, len)) + return 0; + /* PASSTHROUGH */ + case STATE_MSG: + if (!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; + break; + default: + fprintf(stderr, "aucat_read: bad state\n"); abort(); } - while ((n = write(hdl->fd, buf, len)) < 0) { - if (errno == EINTR) - continue; - if (errno != EAGAIN) { - hdl->sa.eof = 1; - perror("aucat_read: read"); - } - return 0; - } - hdl->maxwrite -= n; - hdl->wtodo -= n; - if (hdl->wtodo == 0) { - hdl->wstate = STATE_IDLE; - hdl->wtodo = 0xdeadbeef; - } - return n; - default: - fprintf(stderr, "aucat_read: bad state\n"); + } + if (hdl->maxwrite <= 0) + return 0; + if (len > hdl->maxwrite) + len = hdl->maxwrite; + if (len > hdl->wtodo) + len = hdl->wtodo; + if (len == 0) { + fprintf(stderr, "aucat_write: len == 0\n"); abort(); } + while ((n = write(hdl->fd, buf, len)) < 0) { + if (errno == EINTR) + continue; + if (errno != EAGAIN) { + hdl->sa.eof = 1; + perror("aucat_read: read"); + } + return 0; + } + hdl->maxwrite -= n; + hdl->wtodo -= n; + if (hdl->wtodo == 0) { + hdl->wstate = STATE_IDLE; + hdl->wtodo = 0xdeadbeef; + } + return n; } int @@ -526,3 +556,21 @@ aucat_revents(struct sio_hdl *sh, struct pollfd *pfd) } return revents & hdl->events; } + +int +aucat_setvol(struct sio_hdl *sh, unsigned vol) +{ + struct aucat_hdl *hdl = (struct aucat_hdl *)sh; + + hdl->reqvol = vol; + return 1; +} + +void +aucat_getvol(struct sio_hdl *sh) +{ + struct aucat_hdl *hdl = (struct aucat_hdl *)sh; + + sio_onvol_cb(&hdl->sa, hdl->reqvol); + return; +} |