2 c2297fa3 2023-12-10 op * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
4 c2297fa3 2023-12-10 op * Permission to use, copy, modify, and distribute this software for any
5 c2297fa3 2023-12-10 op * purpose with or without fee is hereby granted, provided that the above
6 c2297fa3 2023-12-10 op * copyright notice and this permission notice appear in all copies.
8 c2297fa3 2023-12-10 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 c2297fa3 2023-12-10 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 c2297fa3 2023-12-10 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 c2297fa3 2023-12-10 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 c2297fa3 2023-12-10 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 c2297fa3 2023-12-10 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 c2297fa3 2023-12-10 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 c2297fa3 2023-12-10 op #include "config.h"
21 c2297fa3 2023-12-10 op #include <sys/socket.h>
23 c2297fa3 2023-12-10 op #include <errno.h>
24 c2297fa3 2023-12-10 op #include <limits.h>
25 c2297fa3 2023-12-10 op #include <poll.h>
26 c2297fa3 2023-12-10 op #include <stdio.h>
28 c2297fa3 2023-12-10 op #include <oboe/Oboe.h>
31 c2297fa3 2023-12-10 op #include "amused.h"
32 c2297fa3 2023-12-10 op #include "log.h"
35 c2297fa3 2023-12-10 op #define ext extern "C"
37 c2297fa3 2023-12-10 op static void (*onmove_cb)(void *, int);
38 c2297fa3 2023-12-10 op static int sp[2]; /* main, audio thread */
39 c2297fa3 2023-12-10 op static pthread_t at;
41 c2297fa3 2023-12-10 op static int bpf;
42 c2297fa3 2023-12-10 op static unsigned int bits, rate, chan;
43 c2297fa3 2023-12-10 op static oboe::AudioFormat fmt;
44 c2297fa3 2023-12-10 op static char buf[BUFSIZ];
45 c2297fa3 2023-12-10 op static size_t buflen;
47 c2297fa3 2023-12-10 op static std::shared_ptr<oboe::AudioStream> stream;
50 c2297fa3 2023-12-10 op aworker(void *d)
52 c2297fa3 2023-12-10 op unsigned int last_bits, last_rate, last_chan;
54 c2297fa3 2023-12-10 op int sock = sp[1];
57 c2297fa3 2023-12-10 op stream = nullptr;
58 c2297fa3 2023-12-10 op last_bits = last_rate = last_chan = 0;
60 c2297fa3 2023-12-10 op log_info("%s: starting", __func__);
63 c2297fa3 2023-12-10 op if ((r = write(sock, &ch, 1)) == -1)
64 c2297fa3 2023-12-10 op fatal("write");
68 c2297fa3 2023-12-10 op if ((r = read(sock, &ch, 1)) == -1)
69 c2297fa3 2023-12-10 op fatal("read");
73 c2297fa3 2023-12-10 op if (bits != last_bits ||
74 c2297fa3 2023-12-10 op rate != last_rate ||
75 c2297fa3 2023-12-10 op chan != last_chan) {
77 c2297fa3 2023-12-10 op stream->close();
78 c2297fa3 2023-12-10 op stream = nullptr;
81 c2297fa3 2023-12-10 op last_bits = bits;
82 c2297fa3 2023-12-10 op last_rate = rate;
83 c2297fa3 2023-12-10 op last_chan = chan;
85 c2297fa3 2023-12-10 op log_debug("setting bits=%d rate=%d chan=%d bpf=%d",
86 c2297fa3 2023-12-10 op bits, rate, chan, bpf);
88 c2297fa3 2023-12-10 op oboe::AudioStreamBuilder streamBuilder;
89 c2297fa3 2023-12-10 op streamBuilder.setFormat(fmt);
90 c2297fa3 2023-12-10 op streamBuilder.setSampleRate(rate);
91 c2297fa3 2023-12-10 op streamBuilder.setChannelCount(chan);
92 c2297fa3 2023-12-10 op oboe::Result result = streamBuilder.openStream(stream);
93 c2297fa3 2023-12-10 op if (result != oboe::Result::OK)
94 c2297fa3 2023-12-10 op fatalx("Error opening stream %s",
95 c2297fa3 2023-12-10 op oboe::convertToText(result));
97 c2297fa3 2023-12-10 op stream->requestStart();
100 c2297fa3 2023-12-10 op // oboe works in terms of FRAMES not BYTES!
101 c2297fa3 2023-12-10 op unsigned int len = buflen / bpf;
103 c2297fa3 2023-12-10 op // XXX should be the timeout in nanoseconds...
104 c2297fa3 2023-12-10 op auto ret = stream->write(buf, len, 1000000000);
106 c2297fa3 2023-12-10 op fatalx("write failed: %s",
107 c2297fa3 2023-12-10 op oboe::convertToText(ret.error()));
111 c2297fa3 2023-12-10 op return nullptr;
115 c2297fa3 2023-12-10 op audio_open(void (*cb)(void *, int))
117 c2297fa3 2023-12-10 op onmove_cb = cb;
119 c2297fa3 2023-12-10 op if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == -1) {
120 c2297fa3 2023-12-10 op log_warn("socketpair");
124 c2297fa3 2023-12-10 op if (pthread_create(&at, NULL, aworker, NULL) == -1) {
125 c2297fa3 2023-12-10 op log_warn("pthread_create");
133 c2297fa3 2023-12-10 op audio_setup(unsigned int p_bits, unsigned int p_rate, unsigned int p_chan,
134 c2297fa3 2023-12-10 op struct pollfd *pfds, int nfds)
136 c2297fa3 2023-12-10 op bits = p_bits;
137 c2297fa3 2023-12-10 op rate = p_rate;
138 c2297fa3 2023-12-10 op chan = p_chan;
140 c2297fa3 2023-12-10 op if (bits == 8) {
141 c2297fa3 2023-12-10 op log_warnx("would require a conversion layer...");
143 c2297fa3 2023-12-10 op } else if (bits == 16) {
145 c2297fa3 2023-12-10 op fmt = oboe::AudioFormat::I16;
146 c2297fa3 2023-12-10 op } else if (bits == 24) {
148 c2297fa3 2023-12-10 op fmt = oboe::AudioFormat::I24;
149 c2297fa3 2023-12-10 op } else if (bits == 32) {
150 c2297fa3 2023-12-10 op // XXX not so sure...
152 c2297fa3 2023-12-10 op fmt = oboe::AudioFormat::I24;
154 c2297fa3 2023-12-10 op log_warnx("can't handle %d bits", bits);
164 c2297fa3 2023-12-10 op audio_nfds(void)
170 c2297fa3 2023-12-10 op audio_pollfd(struct pollfd *pfds, int nfds, int events)
172 c2297fa3 2023-12-10 op if (nfds != 1) {
173 c2297fa3 2023-12-10 op errno = EINVAL;
177 c2297fa3 2023-12-10 op pfds[0].fd = sp[0];
178 c2297fa3 2023-12-10 op pfds[0].events = POLLIN;
183 c2297fa3 2023-12-10 op audio_revents(struct pollfd *pfds, int nfds)
185 c2297fa3 2023-12-10 op if (nfds != 1) {
186 c2297fa3 2023-12-10 op log_warnx("%s: called with %d nfds", __func__, nfds);
190 c2297fa3 2023-12-10 op /* don't need to check; if we're here the audio thread is ready */
191 c2297fa3 2023-12-10 op return POLLOUT;
195 c2297fa3 2023-12-10 op audio_write(const void *data, size_t len)
200 c2297fa3 2023-12-10 op if ((r = read(sp[0], &ch, 1)) == -1) {
201 c2297fa3 2023-12-10 op log_warn("oboe/%s: read failed", __func__);
207 c2297fa3 2023-12-10 op if (len > sizeof(buf))
208 c2297fa3 2023-12-10 op len = sizeof(buf);
210 c2297fa3 2023-12-10 op memcpy(buf, data, len);
211 c2297fa3 2023-12-10 op buflen = len;
214 c2297fa3 2023-12-10 op if ((r = write(sp[0], &ch, 1)) == -1) {
215 c2297fa3 2023-12-10 op log_warn("oboe/%s: write failed", __func__);
218 c2297fa3 2023-12-10 op if (r == 0) {
219 c2297fa3 2023-12-10 op log_warnx("oboe/%s: write got EOF", __func__);
223 c2297fa3 2023-12-10 op if (onmove_cb)
224 c2297fa3 2023-12-10 op onmove_cb(NULL, len / bpf);
230 c2297fa3 2023-12-10 op audio_flush(void)
232 c2297fa3 2023-12-10 op return 0; // XXX request flush
236 c2297fa3 2023-12-10 op audio_stop(void)
238 c2297fa3 2023-12-10 op return 0; // XXX request stop