master
c 565 lines 12.9 KB
Raw
1 /*
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2019 Alexandre Ratchov <alex@caoua.org>
5 */
6
7 /*
8 * TODO :
9 *
10 * Use a single device and open it in full-duplex rather than
11 * opening it twice (once for playback once for recording).
12 *
13 * This is the only way to ensure that playback doesn't drift with respect
14 * to recording, which is what guest systems expect.
15 */
16
17 #include "qemu/osdep.h"
18 #include <poll.h>
19 #include <sndio.h>
20 #include "qemu/main-loop.h"
21 #include "qemu/error-report.h"
22 #include "qemu/audio.h"
23 #include "qom/object.h"
24
25 #include "audio_int.h"
26 #include "trace.h"
27
28 #define TYPE_AUDIO_SNDIO "audio-sndio"
29 OBJECT_DECLARE_SIMPLE_TYPE(AudioSndio, AUDIO_SNDIO)
30
31 struct AudioSndio {
32 AudioMixengBackend parent_obj;
33 };
34
35
36 /* default latency in microseconds if no option is set */
37 #define SNDIO_LATENCY_US 50000
38
39 typedef struct SndioVoice {
40 union {
41 HWVoiceOut out;
42 HWVoiceIn in;
43 } hw;
44 struct sio_par par;
45 struct sio_hdl *hdl;
46 struct pollfd *pfds;
47 struct pollindex {
48 struct SndioVoice *self;
49 int index;
50 } *pindexes;
51 unsigned char *buf;
52 size_t buf_size;
53 size_t sndio_pos;
54 size_t qemu_pos;
55 unsigned int mode;
56 unsigned int nfds;
57 bool enabled;
58 } SndioVoice;
59
60 typedef struct SndioConf {
61 const char *devname;
62 unsigned int latency;
63 } SndioConf;
64
65 /* needed for forward reference */
66 static void sndio_poll_in(void *arg);
67 static void sndio_poll_out(void *arg);
68
69 /*
70 * stop polling descriptors
71 */
72 static void sndio_poll_clear(SndioVoice *self)
73 {
74 struct pollfd *pfd;
75 int i;
76
77 for (i = 0; i < self->nfds; i++) {
78 pfd = &self->pfds[i];
79 qemu_set_fd_handler(pfd->fd, NULL, NULL, NULL);
80 }
81
82 self->nfds = 0;
83 }
84
85 /*
86 * write data to the device until it blocks or
87 * all of our buffered data is written
88 */
89 static void sndio_write(SndioVoice *self)
90 {
91 size_t todo, n;
92
93 todo = self->qemu_pos - self->sndio_pos;
94
95 /*
96 * transfer data to device, until it blocks
97 */
98 while (todo > 0) {
99 n = sio_write(self->hdl, self->buf + self->sndio_pos, todo);
100 if (n == 0) {
101 break;
102 }
103 self->sndio_pos += n;
104 todo -= n;
105 }
106
107 if (self->sndio_pos == self->buf_size) {
108 /*
109 * we complete the block
110 */
111 self->sndio_pos = 0;
112 self->qemu_pos = 0;
113 }
114 }
115
116 /*
117 * read data from the device until it blocks or
118 * there no room any longer
119 */
120 static void sndio_read(SndioVoice *self)
121 {
122 size_t todo, n;
123
124 todo = self->buf_size - self->sndio_pos;
125
126 /*
127 * transfer data from the device, until it blocks
128 */
129 while (todo > 0) {
130 n = sio_read(self->hdl, self->buf + self->sndio_pos, todo);
131 if (n == 0) {
132 break;
133 }
134 self->sndio_pos += n;
135 todo -= n;
136 }
137 }
138
139 /*
140 * Set handlers for all descriptors libsndio needs to
141 * poll
142 */
143 static void sndio_poll_wait(SndioVoice *self)
144 {
145 struct pollfd *pfd;
146 int events, i;
147
148 events = 0;
149 if (self->mode == SIO_PLAY) {
150 if (self->sndio_pos < self->qemu_pos) {
151 events |= POLLOUT;
152 }
153 } else {
154 if (self->sndio_pos < self->buf_size) {
155 events |= POLLIN;
156 }
157 }
158
159 /*
160 * fill the given array of descriptors with the events sndio
161 * wants, they are different from our 'event' variable because
162 * sndio may use descriptors internally.
163 */
164 self->nfds = sio_pollfd(self->hdl, self->pfds, events);
165
166 for (i = 0; i < self->nfds; i++) {
167 pfd = &self->pfds[i];
168 if (pfd->fd < 0) {
169 continue;
170 }
171 qemu_set_fd_handler(pfd->fd,
172 (pfd->events & POLLIN) ? sndio_poll_in : NULL,
173 (pfd->events & POLLOUT) ? sndio_poll_out : NULL,
174 &self->pindexes[i]);
175 pfd->revents = 0;
176 }
177 }
178
179 /*
180 * call-back called when one of the descriptors
181 * became readable or writable
182 */
183 static void sndio_poll_event(SndioVoice *self, int index, int event)
184 {
185 int revents;
186
187 /*
188 * ensure we're not called twice this cycle
189 */
190 sndio_poll_clear(self);
191
192 /*
193 * make self->pfds[] look as we're returning from poll syscal,
194 * this is how sio_revents expects events to be.
195 */
196 self->pfds[index].revents = event;
197
198 /*
199 * tell sndio to handle events and return whether we can read or
200 * write without blocking.
201 */
202 revents = sio_revents(self->hdl, self->pfds);
203 if (self->mode == SIO_PLAY) {
204 if (revents & POLLOUT) {
205 sndio_write(self);
206 }
207
208 if (self->qemu_pos < self->buf_size) {
209 audio_run(self->hw.out.s, "sndio_out");
210 }
211 } else {
212 if (revents & POLLIN) {
213 sndio_read(self);
214 }
215
216 if (self->qemu_pos < self->sndio_pos) {
217 audio_run(self->hw.in.s, "sndio_in");
218 }
219 }
220
221 /*
222 * audio_run() may have changed state
223 */
224 if (self->enabled) {
225 sndio_poll_wait(self);
226 }
227 }
228
229 /*
230 * return the upper limit of the amount of free play buffer space
231 */
232 static size_t sndio_buffer_get_free(HWVoiceOut *hw)
233 {
234 SndioVoice *self = (SndioVoice *) hw;
235
236 return self->buf_size - self->qemu_pos;
237 }
238
239 /*
240 * return a buffer where data to play can be stored,
241 * its size is stored in the location pointed by the size argument.
242 */
243 static void *sndio_get_buffer_out(HWVoiceOut *hw, size_t *size)
244 {
245 SndioVoice *self = (SndioVoice *) hw;
246
247 *size = self->buf_size - self->qemu_pos;
248 return self->buf + self->qemu_pos;
249 }
250
251 /*
252 * put back to sndio back-end a buffer returned by sndio_get_buffer_out()
253 */
254 static size_t sndio_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
255 {
256 SndioVoice *self = (SndioVoice *) hw;
257
258 self->qemu_pos += size;
259 sndio_poll_wait(self);
260 return size;
261 }
262
263 /*
264 * return a buffer from where recorded data is available,
265 * its size is stored in the location pointed by the size argument.
266 * it may not exceed the initial value of "*size".
267 */
268 static void *sndio_get_buffer_in(HWVoiceIn *hw, size_t *size)
269 {
270 SndioVoice *self = (SndioVoice *) hw;
271 size_t todo, max_todo;
272
273 /*
274 * unlike the get_buffer_out() method, get_buffer_in()
275 * must return a buffer of at most the given size, see audio.c
276 */
277 max_todo = *size;
278
279 todo = self->sndio_pos - self->qemu_pos;
280 if (todo > max_todo) {
281 todo = max_todo;
282 }
283
284 *size = todo;
285 return self->buf + self->qemu_pos;
286 }
287
288 /*
289 * discard the given amount of recorded data
290 */
291 static void sndio_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
292 {
293 SndioVoice *self = (SndioVoice *) hw;
294
295 self->qemu_pos += size;
296 if (self->qemu_pos == self->buf_size) {
297 self->qemu_pos = 0;
298 self->sndio_pos = 0;
299 }
300 sndio_poll_wait(self);
301 }
302
303 /*
304 * call-back called when one of our descriptors becomes writable
305 */
306 static void sndio_poll_out(void *arg)
307 {
308 struct pollindex *pindex = (struct pollindex *) arg;
309
310 sndio_poll_event(pindex->self, pindex->index, POLLOUT);
311 }
312
313 /*
314 * call-back called when one of our descriptors becomes readable
315 */
316 static void sndio_poll_in(void *arg)
317 {
318 struct pollindex *pindex = (struct pollindex *) arg;
319
320 sndio_poll_event(pindex->self, pindex->index, POLLIN);
321 }
322
323 static void sndio_fini(SndioVoice *self)
324 {
325 if (self->hdl) {
326 sio_close(self->hdl);
327 self->hdl = NULL;
328 }
329
330 g_free(self->pfds);
331 g_free(self->pindexes);
332 g_free(self->buf);
333 }
334
335 static int sndio_init(SndioVoice *self,
336 struct audsettings *as, int mode, Audiodev *dev)
337 {
338 AudiodevSndioOptions *opts = &dev->u.sndio;
339 unsigned long long latency;
340 const char *dev_name;
341 struct sio_par req;
342 unsigned int nch;
343 int i, nfds;
344
345 dev_name = opts->dev ?: SIO_DEVANY;
346 latency = opts->has_latency ? opts->latency : SNDIO_LATENCY_US;
347
348 /* open the device in non-blocking mode */
349 self->hdl = sio_open(dev_name, mode, 1);
350 if (self->hdl == NULL) {
351 error_report("sndio: failed to open device");
352 return -1;
353 }
354
355 self->mode = mode;
356
357 sio_initpar(&req);
358
359 switch (as->fmt) {
360 case AUDIO_FORMAT_S8:
361 req.bits = 8;
362 req.sig = 1;
363 break;
364 case AUDIO_FORMAT_U8:
365 req.bits = 8;
366 req.sig = 0;
367 break;
368 case AUDIO_FORMAT_S16:
369 req.bits = 16;
370 req.sig = 1;
371 break;
372 case AUDIO_FORMAT_U16:
373 req.bits = 16;
374 req.sig = 0;
375 break;
376 case AUDIO_FORMAT_S32:
377 req.bits = 32;
378 req.sig = 1;
379 break;
380 case AUDIO_FORMAT_U32:
381 req.bits = 32;
382 req.sig = 0;
383 break;
384 default:
385 error_report("sndio: unknown audio sample format");
386 return -1;
387 }
388
389 if (req.bits > 8) {
390 req.le = !as->big_endian;
391 }
392
393 req.rate = as->freq;
394 if (mode == SIO_PLAY) {
395 req.pchan = as->nchannels;
396 } else {
397 req.rchan = as->nchannels;
398 }
399
400 /* set on-device buffer size */
401 req.appbufsz = req.rate * latency / 1000000;
402
403 if (!sio_setpar(self->hdl, &req)) {
404 error_report("sndio: failed to set audio params");
405 goto fail;
406 }
407
408 if (!sio_getpar(self->hdl, &self->par)) {
409 error_report("sndio: failed to get audio params");
410 goto fail;
411 }
412
413 nch = (mode == SIO_PLAY) ? self->par.pchan : self->par.rchan;
414
415 /*
416 * With the default setup, sndio supports any combination of parameters
417 * so these checks are mostly to catch configuration errors.
418 */
419 if (self->par.bits != req.bits || self->par.bps != req.bits / 8 ||
420 self->par.sig != req.sig || (req.bits > 8 && self->par.le != req.le) ||
421 self->par.rate != as->freq || nch != as->nchannels) {
422 error_report("sndio: unsupported audio params");
423 goto fail;
424 }
425
426 /*
427 * we use one block as buffer size; this is how
428 * transfers get well aligned
429 */
430 self->buf_size = self->par.round * self->par.bps * nch;
431
432 self->buf = g_malloc(self->buf_size);
433 if (self->buf == NULL) {
434 error_report("sndio: failed to allocate audio buffer");
435 goto fail;
436 }
437
438 nfds = sio_nfds(self->hdl);
439
440 self->pfds = g_malloc_n(nfds, sizeof(struct pollfd));
441 if (self->pfds == NULL) {
442 error_report("sndio: failed to allocate pollfd structures");
443 goto fail;
444 }
445
446 self->pindexes = g_malloc_n(nfds, sizeof(struct pollindex));
447 if (self->pindexes == NULL) {
448 error_report("sndio: failed to allocate pollindex structures");
449 goto fail;
450 }
451
452 for (i = 0; i < nfds; i++) {
453 self->pindexes[i].self = self;
454 self->pindexes[i].index = i;
455 }
456
457 return 0;
458 fail:
459 sndio_fini(self);
460 return -1;
461 }
462
463 static void sndio_enable(SndioVoice *self, bool enable)
464 {
465 if (enable) {
466 sio_start(self->hdl);
467 self->enabled = true;
468 sndio_poll_wait(self);
469 } else {
470 self->enabled = false;
471 sndio_poll_clear(self);
472 sio_stop(self->hdl);
473 }
474 }
475
476 static void sndio_enable_out(HWVoiceOut *hw, bool enable)
477 {
478 SndioVoice *self = (SndioVoice *) hw;
479
480 sndio_enable(self, enable);
481 }
482
483 static void sndio_enable_in(HWVoiceIn *hw, bool enable)
484 {
485 SndioVoice *self = (SndioVoice *) hw;
486
487 sndio_enable(self, enable);
488 }
489
490 static int sndio_init_out(HWVoiceOut *hw, struct audsettings *as)
491 {
492 SndioVoice *self = (SndioVoice *) hw;
493
494 if (sndio_init(self, as, SIO_PLAY, hw->s->dev) == -1) {
495 return -1;
496 }
497
498 audio_pcm_init_info(&hw->info, as);
499 hw->samples = self->par.round;
500 return 0;
501 }
502
503 static int sndio_init_in(HWVoiceIn *hw, struct audsettings *as)
504 {
505 SndioVoice *self = (SndioVoice *) hw;
506
507 if (sndio_init(self, as, SIO_REC, hw->s->dev) == -1) {
508 return -1;
509 }
510
511 audio_pcm_init_info(&hw->info, as);
512 hw->samples = self->par.round;
513 return 0;
514 }
515
516 static void sndio_fini_out(HWVoiceOut *hw)
517 {
518 SndioVoice *self = (SndioVoice *) hw;
519
520 sndio_fini(self);
521 }
522
523 static void sndio_fini_in(HWVoiceIn *hw)
524 {
525 SndioVoice *self = (SndioVoice *) hw;
526
527 sndio_fini(self);
528 }
529
530 static void audio_sndio_class_init(ObjectClass *klass, const void *data)
531 {
532 AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
533
534 k->max_voices_out = INT_MAX;
535 k->max_voices_in = INT_MAX;
536 k->voice_size_out = sizeof(SndioVoice);
537 k->voice_size_in = sizeof(SndioVoice);
538
539 k->init_out = sndio_init_out;
540 k->fini_out = sndio_fini_out;
541 k->write = audio_generic_write;
542 k->buffer_get_free = sndio_buffer_get_free;
543 k->get_buffer_out = sndio_get_buffer_out;
544 k->put_buffer_out = sndio_put_buffer_out;
545 k->enable_out = sndio_enable_out;
546
547 k->init_in = sndio_init_in;
548 k->fini_in = sndio_fini_in;
549 k->read = audio_generic_read;
550 k->get_buffer_in = sndio_get_buffer_in;
551 k->put_buffer_in = sndio_put_buffer_in;
552 k->enable_in = sndio_enable_in;
553 }
554
555 static const TypeInfo audio_types[] = {
556 {
557 .name = TYPE_AUDIO_SNDIO,
558 .parent = TYPE_AUDIO_MIXENG_BACKEND,
559 .instance_size = sizeof(AudioSndio),
560 .class_init = audio_sndio_class_init,
561 },
562 };
563
564 DEFINE_TYPES(audio_types)
565 module_obj(TYPE_AUDIO_SNDIO);