Blob


1 /*
2 * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include "config.h"
19 #include <errno.h>
20 #include <limits.h>
21 #include <poll.h>
22 #include <sndio.h>
23 #include <stdio.h>
25 #include "amused.h"
26 #include "log.h"
28 static struct sio_hdl *hdl;
29 static struct sio_par par;
30 static int stopped = 1;
32 int
33 audio_open(void (*onmove_cb)(void *, int))
34 {
35 if ((hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1)) == NULL)
36 return -1;
38 sio_onmove(hdl, onmove_cb, NULL);
39 return 0;
40 }
42 int
43 audio_setup(unsigned int bits, unsigned int rate, unsigned int channels,
44 struct pollfd *pfds, int nfds)
45 {
46 int fpct;
48 fpct = (rate * 5) / 100;
50 /* don't stop if the parameters are the same */
51 if (bits == par.bits && channels == par.pchan &&
52 par.rate - fpct <= rate && rate <= par.rate + fpct) {
53 if (stopped)
54 goto start;
55 return 0;
56 }
58 again:
59 if (!stopped) {
60 sio_stop(hdl);
61 stopped = 1;
62 }
64 sio_initpar(&par);
65 par.bits = bits;
66 par.rate = rate;
67 par.pchan = channels;
68 if (!sio_setpar(hdl, &par)) {
69 if (errno == EAGAIN) {
70 sio_pollfd(hdl, pfds, POLLOUT);
71 if (poll(pfds, nfds, INFTIM) == -1)
72 fatal("poll");
73 goto again;
74 }
75 log_warnx("invalid params (bits=%u, rate=%u, channels=%u)",
76 bits, rate, channels);
77 return -1;
78 }
79 if (!sio_getpar(hdl, &par)) {
80 log_warnx("can't get params");
81 return -1;
82 }
84 if (par.bits != bits || par.pchan != channels) {
85 log_warnx("failed to set params");
86 return -1;
87 }
89 /* TODO: check sample rate? */
91 start:
92 if (!sio_start(hdl)) {
93 log_warn("sio_start");
94 return -1;
95 }
96 stopped = 0;
97 return 0;
98 }
100 int
101 audio_nfds(void)
103 return sio_nfds(hdl);
106 int
107 audio_pollfd(struct pollfd *pfds, int nfds, int events)
109 return sio_pollfd(hdl, pfds, events);
112 int
113 audio_revents(struct pollfd *pfds, int nfds)
115 return sio_revents(hdl, pfds);
118 size_t
119 audio_write(const void *buf, size_t len)
121 return sio_write(hdl, buf, len);
124 int
125 audio_flush(void)
127 stopped = 1;
128 return sio_flush(hdl);
131 int
132 audio_stop(void)
134 stopped = 1;
135 return sio_stop(hdl);