Blame


1 c2297fa3 2023-12-10 op /*
2 c2297fa3 2023-12-10 op * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
3 c2297fa3 2023-12-10 op *
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.
7 c2297fa3 2023-12-10 op *
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.
15 c2297fa3 2023-12-10 op */
16 c2297fa3 2023-12-10 op
17 c2297fa3 2023-12-10 op extern "C" {
18 c2297fa3 2023-12-10 op #include "config.h"
19 c2297fa3 2023-12-10 op }
20 c2297fa3 2023-12-10 op
21 c2297fa3 2023-12-10 op #include <sys/socket.h>
22 c2297fa3 2023-12-10 op
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>
27 c2297fa3 2023-12-10 op
28 c2297fa3 2023-12-10 op #include <oboe/Oboe.h>
29 c2297fa3 2023-12-10 op
30 c2297fa3 2023-12-10 op extern "C" {
31 c2297fa3 2023-12-10 op #include "amused.h"
32 c2297fa3 2023-12-10 op #include "log.h"
33 c2297fa3 2023-12-10 op }
34 c2297fa3 2023-12-10 op
35 c2297fa3 2023-12-10 op #define ext extern "C"
36 c2297fa3 2023-12-10 op
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;
40 c2297fa3 2023-12-10 op
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;
46 c2297fa3 2023-12-10 op
47 c2297fa3 2023-12-10 op static std::shared_ptr<oboe::AudioStream> stream;
48 c2297fa3 2023-12-10 op
49 c2297fa3 2023-12-10 op static void *
50 c2297fa3 2023-12-10 op aworker(void *d)
51 c2297fa3 2023-12-10 op {
52 c2297fa3 2023-12-10 op unsigned int last_bits, last_rate, last_chan;
53 c2297fa3 2023-12-10 op ssize_t r;
54 c2297fa3 2023-12-10 op int sock = sp[1];
55 c2297fa3 2023-12-10 op char ch;
56 c2297fa3 2023-12-10 op
57 c2297fa3 2023-12-10 op stream = nullptr;
58 c2297fa3 2023-12-10 op last_bits = last_rate = last_chan = 0;
59 c2297fa3 2023-12-10 op
60 c2297fa3 2023-12-10 op log_info("%s: starting", __func__);
61 c2297fa3 2023-12-10 op for (;;) {
62 c2297fa3 2023-12-10 op ch = 1;
63 c2297fa3 2023-12-10 op if ((r = write(sock, &ch, 1)) == -1)
64 c2297fa3 2023-12-10 op fatal("write");
65 c2297fa3 2023-12-10 op if (r == 0)
66 c2297fa3 2023-12-10 op break;
67 c2297fa3 2023-12-10 op
68 c2297fa3 2023-12-10 op if ((r = read(sock, &ch, 1)) == -1)
69 c2297fa3 2023-12-10 op fatal("read");
70 c2297fa3 2023-12-10 op if (r == 0)
71 c2297fa3 2023-12-10 op break;
72 c2297fa3 2023-12-10 op
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) {
76 c2297fa3 2023-12-10 op if (stream) {
77 c2297fa3 2023-12-10 op stream->close();
78 c2297fa3 2023-12-10 op stream = nullptr;
79 c2297fa3 2023-12-10 op }
80 c2297fa3 2023-12-10 op
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;
84 c2297fa3 2023-12-10 op
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);
87 c2297fa3 2023-12-10 op
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));
96 c2297fa3 2023-12-10 op
97 c2297fa3 2023-12-10 op stream->requestStart();
98 c2297fa3 2023-12-10 op }
99 c2297fa3 2023-12-10 op
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;
102 c2297fa3 2023-12-10 op
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);
105 c2297fa3 2023-12-10 op if (!ret) {
106 c2297fa3 2023-12-10 op fatalx("write failed: %s",
107 c2297fa3 2023-12-10 op oboe::convertToText(ret.error()));
108 c2297fa3 2023-12-10 op }
109 c2297fa3 2023-12-10 op }
110 c2297fa3 2023-12-10 op
111 c2297fa3 2023-12-10 op return nullptr;
112 c2297fa3 2023-12-10 op }
113 c2297fa3 2023-12-10 op
114 c2297fa3 2023-12-10 op ext int
115 c2297fa3 2023-12-10 op audio_open(void (*cb)(void *, int))
116 c2297fa3 2023-12-10 op {
117 c2297fa3 2023-12-10 op onmove_cb = cb;
118 c2297fa3 2023-12-10 op
119 c2297fa3 2023-12-10 op if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == -1) {
120 c2297fa3 2023-12-10 op log_warn("socketpair");
121 c2297fa3 2023-12-10 op return (-1);
122 c2297fa3 2023-12-10 op }
123 c2297fa3 2023-12-10 op
124 c2297fa3 2023-12-10 op if (pthread_create(&at, NULL, aworker, NULL) == -1) {
125 c2297fa3 2023-12-10 op log_warn("pthread_create");
126 c2297fa3 2023-12-10 op return (-1);
127 c2297fa3 2023-12-10 op }
128 c2297fa3 2023-12-10 op
129 c2297fa3 2023-12-10 op return (0);
130 c2297fa3 2023-12-10 op }
131 c2297fa3 2023-12-10 op
132 c2297fa3 2023-12-10 op ext int
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)
135 c2297fa3 2023-12-10 op {
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;
139 c2297fa3 2023-12-10 op
140 c2297fa3 2023-12-10 op if (bits == 8) {
141 c2297fa3 2023-12-10 op log_warnx("would require a conversion layer...");
142 c2297fa3 2023-12-10 op return (-1);
143 c2297fa3 2023-12-10 op } else if (bits == 16) {
144 c2297fa3 2023-12-10 op bpf = 2;
145 c2297fa3 2023-12-10 op fmt = oboe::AudioFormat::I16;
146 c2297fa3 2023-12-10 op } else if (bits == 24) {
147 c2297fa3 2023-12-10 op bpf = 4;
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...
151 c2297fa3 2023-12-10 op bpf = 4;
152 c2297fa3 2023-12-10 op fmt = oboe::AudioFormat::I24;
153 c2297fa3 2023-12-10 op } else {
154 c2297fa3 2023-12-10 op log_warnx("can't handle %d bits", bits);
155 c2297fa3 2023-12-10 op return (-1);
156 c2297fa3 2023-12-10 op }
157 c2297fa3 2023-12-10 op
158 c2297fa3 2023-12-10 op bpf *= chan;
159 c2297fa3 2023-12-10 op
160 c2297fa3 2023-12-10 op return (0);
161 c2297fa3 2023-12-10 op }
162 c2297fa3 2023-12-10 op
163 c2297fa3 2023-12-10 op ext int
164 c2297fa3 2023-12-10 op audio_nfds(void)
165 c2297fa3 2023-12-10 op {
166 c2297fa3 2023-12-10 op return 1;
167 c2297fa3 2023-12-10 op }
168 c2297fa3 2023-12-10 op
169 c2297fa3 2023-12-10 op ext int
170 c2297fa3 2023-12-10 op audio_pollfd(struct pollfd *pfds, int nfds, int events)
171 c2297fa3 2023-12-10 op {
172 c2297fa3 2023-12-10 op if (nfds != 1) {
173 c2297fa3 2023-12-10 op errno = EINVAL;
174 c2297fa3 2023-12-10 op return -1;
175 c2297fa3 2023-12-10 op }
176 c2297fa3 2023-12-10 op
177 c2297fa3 2023-12-10 op pfds[0].fd = sp[0];
178 c2297fa3 2023-12-10 op pfds[0].events = POLLIN;
179 c2297fa3 2023-12-10 op return (0);
180 c2297fa3 2023-12-10 op }
181 c2297fa3 2023-12-10 op
182 c2297fa3 2023-12-10 op ext int
183 c2297fa3 2023-12-10 op audio_revents(struct pollfd *pfds, int nfds)
184 c2297fa3 2023-12-10 op {
185 c2297fa3 2023-12-10 op if (nfds != 1) {
186 c2297fa3 2023-12-10 op log_warnx("%s: called with %d nfds", __func__, nfds);
187 c2297fa3 2023-12-10 op return 0;
188 c2297fa3 2023-12-10 op }
189 c2297fa3 2023-12-10 op
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;
192 c2297fa3 2023-12-10 op }
193 c2297fa3 2023-12-10 op
194 c2297fa3 2023-12-10 op ext size_t
195 c2297fa3 2023-12-10 op audio_write(const void *data, size_t len)
196 c2297fa3 2023-12-10 op {
197 c2297fa3 2023-12-10 op char ch;
198 c2297fa3 2023-12-10 op ssize_t r;
199 c2297fa3 2023-12-10 op
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__);
202 c2297fa3 2023-12-10 op return 0;
203 c2297fa3 2023-12-10 op }
204 c2297fa3 2023-12-10 op if (r == 0)
205 c2297fa3 2023-12-10 op return 0;
206 c2297fa3 2023-12-10 op
207 c2297fa3 2023-12-10 op if (len > sizeof(buf))
208 c2297fa3 2023-12-10 op len = sizeof(buf);
209 c2297fa3 2023-12-10 op
210 c2297fa3 2023-12-10 op memcpy(buf, data, len);
211 c2297fa3 2023-12-10 op buflen = len;
212 c2297fa3 2023-12-10 op
213 c2297fa3 2023-12-10 op ch = 1;
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__);
216 c2297fa3 2023-12-10 op return 0;
217 c2297fa3 2023-12-10 op }
218 c2297fa3 2023-12-10 op if (r == 0) {
219 c2297fa3 2023-12-10 op log_warnx("oboe/%s: write got EOF", __func__);
220 c2297fa3 2023-12-10 op return 0;
221 c2297fa3 2023-12-10 op }
222 c2297fa3 2023-12-10 op
223 c2297fa3 2023-12-10 op if (onmove_cb)
224 c2297fa3 2023-12-10 op onmove_cb(NULL, len / bpf);
225 c2297fa3 2023-12-10 op
226 c2297fa3 2023-12-10 op return len;
227 c2297fa3 2023-12-10 op }
228 c2297fa3 2023-12-10 op
229 c2297fa3 2023-12-10 op ext int
230 c2297fa3 2023-12-10 op audio_flush(void)
231 c2297fa3 2023-12-10 op {
232 c2297fa3 2023-12-10 op return 0; // XXX request flush
233 c2297fa3 2023-12-10 op }
234 c2297fa3 2023-12-10 op
235 c2297fa3 2023-12-10 op ext int
236 c2297fa3 2023-12-10 op audio_stop(void)
237 c2297fa3 2023-12-10 op {
238 c2297fa3 2023-12-10 op return 0; // XXX request stop
239 c2297fa3 2023-12-10 op }