2 * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
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.
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.
19 #include <sys/socket.h>
30 static void (*onmove_cb)(void *, int);
31 static int sp[2]; /* main, audio thread */
35 static ao_sample_format fmt;
36 static char buf[BUFSIZ];
43 ao_device *device = NULL;
48 memset(&f, 0, sizeof(f));
50 log_info("%s: starting", __func__);
54 if ((r = write(sock, &ch, 1)) == -1)
59 if ((r = read(sock, &ch, 1)) == -1)
64 if (memcmp(&fmt, &f, sizeof(f)) != 0) {
67 device = ao_open_live(ao_default_driver_id(),
72 log_warnx("ao: no driver found");
75 log_warnx("ao: not a live device");
78 log_warnx("ao: bad option(s)");
81 log_warnx("ao: failed to open device");
85 log_warnx("ao: failed opening driver");
91 log_info("%s: device (re)opened", __func__);
92 memcpy(&f, &fmt, sizeof(f));
95 if (ao_play(device, buf, buflen) == 0) {
96 log_warnx("ao_play failed");
101 log_info("quitting audio thread");
107 audio_open(void (*cb)(void *, int))
112 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == -1) {
113 log_warn("socketpair");
117 if (pthread_create(&at, NULL, aworker, NULL) == -1) {
118 log_warn("pthread_create");
126 audio_setup(unsigned int bits, unsigned int rate, unsigned int channels,
127 struct pollfd *pfds, int nfds)
131 fmt.channels = channels;
132 fmt.byte_format = AO_FMT_NATIVE;
139 else if (bits == 24 || bits == 32)
142 log_warnx("can't handle %d bits", bits);
156 audio_pollfd(struct pollfd *pfds, int nfds, int events)
164 pfds[0].events = POLLIN;
169 audio_revents(struct pollfd *pfds, int nfds)
172 log_warnx("%s: called with nfds=%d", __func__, nfds);
176 /* don't need to check; if we're here the audio thread is ready */
181 audio_write(const void *data, size_t len)
186 if ((r = read(sp[0], &ch, 1)) == -1) {
187 log_warn("ao/%s: read failed", __func__);
193 if (len > sizeof(buf))
196 memcpy(buf, data, len);
200 if ((r = write(sp[0], &ch, 1)) == -1) {
201 log_warn("ao/%s: write failed", __func__);
205 log_warnx("ao/%s: write got EOF", __func__);
210 onmove_cb(NULL, len / bpf);