Revert "tests/avocado: Enable reverse_debugging.py tests in gitlab CI"
[qemu/ar7.git] / audio / pwaudio.c
blob3ce5f6507b47270c1283cabf5b47ad81932d6e5e
1 /*
2 * QEMU PipeWire audio driver
4 * Copyright (c) 2023 Red Hat Inc.
6 * Author: Dorinda Bassey <dbassey@redhat.com>
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "qemu/osdep.h"
12 #include "qemu/module.h"
13 #include "audio.h"
14 #include <errno.h>
15 #include "qemu/error-report.h"
16 #include "qapi/error.h"
17 #include <spa/param/audio/format-utils.h>
18 #include <spa/utils/ringbuffer.h>
19 #include <spa/utils/result.h>
20 #include <spa/param/props.h>
22 #include <pipewire/pipewire.h>
23 #include "trace.h"
25 #define AUDIO_CAP "pipewire"
26 #define RINGBUFFER_SIZE (1u << 22)
27 #define RINGBUFFER_MASK (RINGBUFFER_SIZE - 1)
29 #include "audio_int.h"
31 typedef struct pwvolume {
32 uint32_t channels;
33 float values[SPA_AUDIO_MAX_CHANNELS];
34 } pwvolume;
36 typedef struct pwaudio {
37 Audiodev *dev;
38 struct pw_thread_loop *thread_loop;
39 struct pw_context *context;
41 struct pw_core *core;
42 struct spa_hook core_listener;
43 int last_seq, pending_seq, error;
44 } pwaudio;
46 typedef struct PWVoice {
47 pwaudio *g;
48 struct pw_stream *stream;
49 struct spa_hook stream_listener;
50 struct spa_audio_info_raw info;
51 uint32_t highwater_mark;
52 uint32_t frame_size, req;
53 struct spa_ringbuffer ring;
54 uint8_t buffer[RINGBUFFER_SIZE];
56 pwvolume volume;
57 bool muted;
58 } PWVoice;
60 typedef struct PWVoiceOut {
61 HWVoiceOut hw;
62 PWVoice v;
63 } PWVoiceOut;
65 typedef struct PWVoiceIn {
66 HWVoiceIn hw;
67 PWVoice v;
68 } PWVoiceIn;
70 #define PW_VOICE_IN(v) ((PWVoiceIn *)v)
71 #define PW_VOICE_OUT(v) ((PWVoiceOut *)v)
73 static void
74 stream_destroy(void *data)
76 PWVoice *v = (PWVoice *) data;
77 spa_hook_remove(&v->stream_listener);
78 v->stream = NULL;
81 /* output data processing function to read stuffs from the buffer */
82 static void
83 playback_on_process(void *data)
85 PWVoice *v = data;
86 void *p;
87 struct pw_buffer *b;
88 struct spa_buffer *buf;
89 uint32_t req, index, n_bytes;
90 int32_t avail;
92 assert(v->stream);
94 /* obtain a buffer to read from */
95 b = pw_stream_dequeue_buffer(v->stream);
96 if (b == NULL) {
97 error_report("out of buffers: %s", strerror(errno));
98 return;
101 buf = b->buffer;
102 p = buf->datas[0].data;
103 if (p == NULL) {
104 return;
106 /* calculate the total no of bytes to read data from buffer */
107 req = b->requested * v->frame_size;
108 if (req == 0) {
109 req = v->req;
111 n_bytes = SPA_MIN(req, buf->datas[0].maxsize);
113 /* get no of available bytes to read data from buffer */
114 avail = spa_ringbuffer_get_read_index(&v->ring, &index);
116 if (avail <= 0) {
117 PWVoiceOut *vo = container_of(data, PWVoiceOut, v);
118 audio_pcm_info_clear_buf(&vo->hw.info, p, n_bytes / v->frame_size);
119 } else {
120 if ((uint32_t) avail < n_bytes) {
122 * PipeWire immediately calls this callback again if we provide
123 * less than n_bytes. Then audio_pcm_info_clear_buf() fills the
124 * rest of the buffer with silence.
126 n_bytes = avail;
129 spa_ringbuffer_read_data(&v->ring,
130 v->buffer, RINGBUFFER_SIZE,
131 index & RINGBUFFER_MASK, p, n_bytes);
133 index += n_bytes;
134 spa_ringbuffer_read_update(&v->ring, index);
137 buf->datas[0].chunk->offset = 0;
138 buf->datas[0].chunk->stride = v->frame_size;
139 buf->datas[0].chunk->size = n_bytes;
141 /* queue the buffer for playback */
142 pw_stream_queue_buffer(v->stream, b);
145 /* output data processing function to generate stuffs in the buffer */
146 static void
147 capture_on_process(void *data)
149 PWVoice *v = (PWVoice *) data;
150 void *p;
151 struct pw_buffer *b;
152 struct spa_buffer *buf;
153 int32_t filled;
154 uint32_t index, offs, n_bytes;
156 assert(v->stream);
158 /* obtain a buffer */
159 b = pw_stream_dequeue_buffer(v->stream);
160 if (b == NULL) {
161 error_report("out of buffers: %s", strerror(errno));
162 return;
165 /* Write data into buffer */
166 buf = b->buffer;
167 p = buf->datas[0].data;
168 if (p == NULL) {
169 return;
171 offs = SPA_MIN(buf->datas[0].chunk->offset, buf->datas[0].maxsize);
172 n_bytes = SPA_MIN(buf->datas[0].chunk->size, buf->datas[0].maxsize - offs);
174 filled = spa_ringbuffer_get_write_index(&v->ring, &index);
177 if (filled < 0) {
178 error_report("%p: underrun write:%u filled:%d", p, index, filled);
179 } else {
180 if ((uint32_t) filled + n_bytes > RINGBUFFER_SIZE) {
181 error_report("%p: overrun write:%u filled:%d + size:%u > max:%u",
182 p, index, filled, n_bytes, RINGBUFFER_SIZE);
185 spa_ringbuffer_write_data(&v->ring,
186 v->buffer, RINGBUFFER_SIZE,
187 index & RINGBUFFER_MASK,
188 SPA_PTROFF(p, offs, void), n_bytes);
189 index += n_bytes;
190 spa_ringbuffer_write_update(&v->ring, index);
192 /* queue the buffer for playback */
193 pw_stream_queue_buffer(v->stream, b);
196 static void
197 on_stream_state_changed(void *data, enum pw_stream_state old,
198 enum pw_stream_state state, const char *error)
200 PWVoice *v = (PWVoice *) data;
202 trace_pw_state_changed(pw_stream_get_node_id(v->stream),
203 pw_stream_state_as_string(state));
206 static const struct pw_stream_events capture_stream_events = {
207 PW_VERSION_STREAM_EVENTS,
208 .destroy = stream_destroy,
209 .state_changed = on_stream_state_changed,
210 .process = capture_on_process
213 static const struct pw_stream_events playback_stream_events = {
214 PW_VERSION_STREAM_EVENTS,
215 .destroy = stream_destroy,
216 .state_changed = on_stream_state_changed,
217 .process = playback_on_process
220 static size_t
221 qpw_read(HWVoiceIn *hw, void *data, size_t len)
223 PWVoiceIn *pw = (PWVoiceIn *) hw;
224 PWVoice *v = &pw->v;
225 pwaudio *c = v->g;
226 const char *error = NULL;
227 size_t l;
228 int32_t avail;
229 uint32_t index;
231 pw_thread_loop_lock(c->thread_loop);
232 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
233 /* wait for stream to become ready */
234 l = 0;
235 goto done_unlock;
237 /* get no of available bytes to read data from buffer */
238 avail = spa_ringbuffer_get_read_index(&v->ring, &index);
240 trace_pw_read(avail, index, len);
242 if (avail < (int32_t) len) {
243 len = avail;
246 spa_ringbuffer_read_data(&v->ring,
247 v->buffer, RINGBUFFER_SIZE,
248 index & RINGBUFFER_MASK, data, len);
249 index += len;
250 spa_ringbuffer_read_update(&v->ring, index);
251 l = len;
253 done_unlock:
254 pw_thread_loop_unlock(c->thread_loop);
255 return l;
258 static size_t qpw_buffer_get_free(HWVoiceOut *hw)
260 PWVoiceOut *pw = (PWVoiceOut *)hw;
261 PWVoice *v = &pw->v;
262 pwaudio *c = v->g;
263 const char *error = NULL;
264 int32_t filled, avail;
265 uint32_t index;
267 pw_thread_loop_lock(c->thread_loop);
268 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
269 /* wait for stream to become ready */
270 avail = 0;
271 goto done_unlock;
274 filled = spa_ringbuffer_get_write_index(&v->ring, &index);
275 avail = v->highwater_mark - filled;
277 done_unlock:
278 pw_thread_loop_unlock(c->thread_loop);
279 return avail;
282 static size_t
283 qpw_write(HWVoiceOut *hw, void *data, size_t len)
285 PWVoiceOut *pw = (PWVoiceOut *) hw;
286 PWVoice *v = &pw->v;
287 pwaudio *c = v->g;
288 const char *error = NULL;
289 int32_t filled, avail;
290 uint32_t index;
292 pw_thread_loop_lock(c->thread_loop);
293 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
294 /* wait for stream to become ready */
295 len = 0;
296 goto done_unlock;
298 filled = spa_ringbuffer_get_write_index(&v->ring, &index);
299 avail = v->highwater_mark - filled;
301 trace_pw_write(filled, avail, index, len);
303 if (len > avail) {
304 len = avail;
307 if (filled < 0) {
308 error_report("%p: underrun write:%u filled:%d", pw, index, filled);
309 } else {
310 if ((uint32_t) filled + len > RINGBUFFER_SIZE) {
311 error_report("%p: overrun write:%u filled:%d + size:%zu > max:%u",
312 pw, index, filled, len, RINGBUFFER_SIZE);
316 spa_ringbuffer_write_data(&v->ring,
317 v->buffer, RINGBUFFER_SIZE,
318 index & RINGBUFFER_MASK, data, len);
319 index += len;
320 spa_ringbuffer_write_update(&v->ring, index);
322 done_unlock:
323 pw_thread_loop_unlock(c->thread_loop);
324 return len;
327 static int
328 audfmt_to_pw(AudioFormat fmt, int endianness)
330 int format;
332 switch (fmt) {
333 case AUDIO_FORMAT_S8:
334 format = SPA_AUDIO_FORMAT_S8;
335 break;
336 case AUDIO_FORMAT_U8:
337 format = SPA_AUDIO_FORMAT_U8;
338 break;
339 case AUDIO_FORMAT_S16:
340 format = endianness ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE;
341 break;
342 case AUDIO_FORMAT_U16:
343 format = endianness ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE;
344 break;
345 case AUDIO_FORMAT_S32:
346 format = endianness ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE;
347 break;
348 case AUDIO_FORMAT_U32:
349 format = endianness ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE;
350 break;
351 case AUDIO_FORMAT_F32:
352 format = endianness ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE;
353 break;
354 default:
355 dolog("Internal logic error: Bad audio format %d\n", fmt);
356 format = SPA_AUDIO_FORMAT_U8;
357 break;
359 return format;
362 static AudioFormat
363 pw_to_audfmt(enum spa_audio_format fmt, int *endianness,
364 uint32_t *sample_size)
366 switch (fmt) {
367 case SPA_AUDIO_FORMAT_S8:
368 *sample_size = 1;
369 return AUDIO_FORMAT_S8;
370 case SPA_AUDIO_FORMAT_U8:
371 *sample_size = 1;
372 return AUDIO_FORMAT_U8;
373 case SPA_AUDIO_FORMAT_S16_BE:
374 *sample_size = 2;
375 *endianness = 1;
376 return AUDIO_FORMAT_S16;
377 case SPA_AUDIO_FORMAT_S16_LE:
378 *sample_size = 2;
379 *endianness = 0;
380 return AUDIO_FORMAT_S16;
381 case SPA_AUDIO_FORMAT_U16_BE:
382 *sample_size = 2;
383 *endianness = 1;
384 return AUDIO_FORMAT_U16;
385 case SPA_AUDIO_FORMAT_U16_LE:
386 *sample_size = 2;
387 *endianness = 0;
388 return AUDIO_FORMAT_U16;
389 case SPA_AUDIO_FORMAT_S32_BE:
390 *sample_size = 4;
391 *endianness = 1;
392 return AUDIO_FORMAT_S32;
393 case SPA_AUDIO_FORMAT_S32_LE:
394 *sample_size = 4;
395 *endianness = 0;
396 return AUDIO_FORMAT_S32;
397 case SPA_AUDIO_FORMAT_U32_BE:
398 *sample_size = 4;
399 *endianness = 1;
400 return AUDIO_FORMAT_U32;
401 case SPA_AUDIO_FORMAT_U32_LE:
402 *sample_size = 4;
403 *endianness = 0;
404 return AUDIO_FORMAT_U32;
405 case SPA_AUDIO_FORMAT_F32_BE:
406 *sample_size = 4;
407 *endianness = 1;
408 return AUDIO_FORMAT_F32;
409 case SPA_AUDIO_FORMAT_F32_LE:
410 *sample_size = 4;
411 *endianness = 0;
412 return AUDIO_FORMAT_F32;
413 default:
414 *sample_size = 1;
415 dolog("Internal logic error: Bad spa_audio_format %d\n", fmt);
416 return AUDIO_FORMAT_U8;
420 static int
421 qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name,
422 const char *name, enum spa_direction dir)
424 int res;
425 uint32_t n_params;
426 const struct spa_pod *params[2];
427 uint8_t buffer[1024];
428 struct spa_pod_builder b;
429 uint64_t buf_samples;
430 struct pw_properties *props;
432 props = pw_properties_new(NULL, NULL);
433 if (!props) {
434 error_report("Failed to create PW properties: %s", g_strerror(errno));
435 return -1;
438 /* 75% of the timer period for faster updates */
439 buf_samples = (uint64_t)v->g->dev->timer_period * v->info.rate
440 * 3 / 4 / 1000000;
441 pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%" PRIu64 "/%u",
442 buf_samples, v->info.rate);
444 trace_pw_period(buf_samples, v->info.rate);
445 if (name) {
446 pw_properties_set(props, PW_KEY_TARGET_OBJECT, name);
448 v->stream = pw_stream_new(c->core, stream_name, props);
449 if (v->stream == NULL) {
450 error_report("Failed to create PW stream: %s", g_strerror(errno));
451 return -1;
454 if (dir == SPA_DIRECTION_INPUT) {
455 pw_stream_add_listener(v->stream,
456 &v->stream_listener, &capture_stream_events, v);
457 } else {
458 pw_stream_add_listener(v->stream,
459 &v->stream_listener, &playback_stream_events, v);
462 n_params = 0;
463 spa_pod_builder_init(&b, buffer, sizeof(buffer));
464 params[n_params++] = spa_format_audio_raw_build(&b,
465 SPA_PARAM_EnumFormat,
466 &v->info);
468 /* connect the stream to a sink or source */
469 res = pw_stream_connect(v->stream,
470 dir ==
471 SPA_DIRECTION_INPUT ? PW_DIRECTION_INPUT :
472 PW_DIRECTION_OUTPUT, PW_ID_ANY,
473 PW_STREAM_FLAG_AUTOCONNECT |
474 PW_STREAM_FLAG_INACTIVE |
475 PW_STREAM_FLAG_MAP_BUFFERS |
476 PW_STREAM_FLAG_RT_PROCESS, params, n_params);
477 if (res < 0) {
478 error_report("Failed to connect PW stream: %s", g_strerror(errno));
479 pw_stream_destroy(v->stream);
480 return -1;
483 return 0;
486 static void
487 qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS])
489 memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, },
490 sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS);
492 * TODO: This currently expects the only frontend supporting more than 2
493 * channels is the usb-audio. We will need some means to set channel
494 * order when a new frontend gains multi-channel support.
496 switch (channels) {
497 case 8:
498 position[6] = SPA_AUDIO_CHANNEL_SL;
499 position[7] = SPA_AUDIO_CHANNEL_SR;
500 /* fallthrough */
501 case 6:
502 position[2] = SPA_AUDIO_CHANNEL_FC;
503 position[3] = SPA_AUDIO_CHANNEL_LFE;
504 position[4] = SPA_AUDIO_CHANNEL_RL;
505 position[5] = SPA_AUDIO_CHANNEL_RR;
506 /* fallthrough */
507 case 2:
508 position[0] = SPA_AUDIO_CHANNEL_FL;
509 position[1] = SPA_AUDIO_CHANNEL_FR;
510 break;
511 case 1:
512 position[0] = SPA_AUDIO_CHANNEL_MONO;
513 break;
514 default:
515 dolog("Internal error: unsupported channel count %d\n", channels);
519 static int
520 qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
522 PWVoiceOut *pw = (PWVoiceOut *) hw;
523 PWVoice *v = &pw->v;
524 struct audsettings obt_as = *as;
525 pwaudio *c = v->g = drv_opaque;
526 AudiodevPipewireOptions *popts = &c->dev->u.pipewire;
527 AudiodevPipewirePerDirectionOptions *ppdo = popts->out;
528 int r;
530 pw_thread_loop_lock(c->thread_loop);
532 v->info.format = audfmt_to_pw(as->fmt, as->endianness);
533 v->info.channels = as->nchannels;
534 qpw_set_position(as->nchannels, v->info.position);
535 v->info.rate = as->freq;
537 obt_as.fmt =
538 pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size);
539 v->frame_size *= as->nchannels;
541 v->req = (uint64_t)c->dev->timer_period * v->info.rate
542 * 1 / 2 / 1000000 * v->frame_size;
544 /* call the function that creates a new stream for playback */
545 r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id,
546 ppdo->name, SPA_DIRECTION_OUTPUT);
547 if (r < 0) {
548 pw_thread_loop_unlock(c->thread_loop);
549 return -1;
552 /* report the audio format we support */
553 audio_pcm_init_info(&hw->info, &obt_as);
555 /* report the buffer size to qemu */
556 hw->samples = audio_buffer_frames(
557 qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
558 v->highwater_mark = MIN(RINGBUFFER_SIZE,
559 (ppdo->has_latency ? ppdo->latency : 46440)
560 * (uint64_t)v->info.rate / 1000000 * v->frame_size);
562 pw_thread_loop_unlock(c->thread_loop);
563 return 0;
566 static int
567 qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
569 PWVoiceIn *pw = (PWVoiceIn *) hw;
570 PWVoice *v = &pw->v;
571 struct audsettings obt_as = *as;
572 pwaudio *c = v->g = drv_opaque;
573 AudiodevPipewireOptions *popts = &c->dev->u.pipewire;
574 AudiodevPipewirePerDirectionOptions *ppdo = popts->in;
575 int r;
577 pw_thread_loop_lock(c->thread_loop);
579 v->info.format = audfmt_to_pw(as->fmt, as->endianness);
580 v->info.channels = as->nchannels;
581 qpw_set_position(as->nchannels, v->info.position);
582 v->info.rate = as->freq;
584 obt_as.fmt =
585 pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size);
586 v->frame_size *= as->nchannels;
588 /* call the function that creates a new stream for recording */
589 r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id,
590 ppdo->name, SPA_DIRECTION_INPUT);
591 if (r < 0) {
592 pw_thread_loop_unlock(c->thread_loop);
593 return -1;
596 /* report the audio format we support */
597 audio_pcm_init_info(&hw->info, &obt_as);
599 /* report the buffer size to qemu */
600 hw->samples = audio_buffer_frames(
601 qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
603 pw_thread_loop_unlock(c->thread_loop);
604 return 0;
607 static void
608 qpw_voice_fini(PWVoice *v)
610 pwaudio *c = v->g;
612 if (!v->stream) {
613 return;
615 pw_thread_loop_lock(c->thread_loop);
616 pw_stream_destroy(v->stream);
617 v->stream = NULL;
618 pw_thread_loop_unlock(c->thread_loop);
621 static void
622 qpw_fini_out(HWVoiceOut *hw)
624 qpw_voice_fini(&PW_VOICE_OUT(hw)->v);
627 static void
628 qpw_fini_in(HWVoiceIn *hw)
630 qpw_voice_fini(&PW_VOICE_IN(hw)->v);
633 static void
634 qpw_voice_set_enabled(PWVoice *v, bool enable)
636 pwaudio *c = v->g;
637 pw_thread_loop_lock(c->thread_loop);
638 pw_stream_set_active(v->stream, enable);
639 pw_thread_loop_unlock(c->thread_loop);
642 static void
643 qpw_enable_out(HWVoiceOut *hw, bool enable)
645 qpw_voice_set_enabled(&PW_VOICE_OUT(hw)->v, enable);
648 static void
649 qpw_enable_in(HWVoiceIn *hw, bool enable)
651 qpw_voice_set_enabled(&PW_VOICE_IN(hw)->v, enable);
654 static void
655 qpw_voice_set_volume(PWVoice *v, Volume *vol)
657 pwaudio *c = v->g;
658 int i, ret;
660 pw_thread_loop_lock(c->thread_loop);
661 v->volume.channels = vol->channels;
663 for (i = 0; i < vol->channels; ++i) {
664 v->volume.values[i] = (float)vol->vol[i] / 255;
667 ret = pw_stream_set_control(v->stream,
668 SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0);
669 trace_pw_vol(ret == 0 ? "success" : "failed");
671 v->muted = vol->mute;
672 float val = v->muted ? 1.f : 0.f;
673 ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0);
674 pw_thread_loop_unlock(c->thread_loop);
677 static void
678 qpw_volume_out(HWVoiceOut *hw, Volume *vol)
680 qpw_voice_set_volume(&PW_VOICE_OUT(hw)->v, vol);
683 static void
684 qpw_volume_in(HWVoiceIn *hw, Volume *vol)
686 qpw_voice_set_volume(&PW_VOICE_IN(hw)->v, vol);
689 static int wait_resync(pwaudio *pw)
691 int res;
692 pw->pending_seq = pw_core_sync(pw->core, PW_ID_CORE, pw->pending_seq);
694 while (true) {
695 pw_thread_loop_wait(pw->thread_loop);
697 res = pw->error;
698 if (res < 0) {
699 pw->error = 0;
700 return res;
702 if (pw->pending_seq == pw->last_seq) {
703 break;
706 return 0;
709 static void
710 on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
712 pwaudio *pw = data;
714 error_report("error id:%u seq:%d res:%d (%s): %s",
715 id, seq, res, spa_strerror(res), message);
717 /* stop and exit the thread loop */
718 pw_thread_loop_signal(pw->thread_loop, FALSE);
721 static void
722 on_core_done(void *data, uint32_t id, int seq)
724 pwaudio *pw = data;
725 assert(id == PW_ID_CORE);
726 pw->last_seq = seq;
727 if (pw->pending_seq == seq) {
728 /* stop and exit the thread loop */
729 pw_thread_loop_signal(pw->thread_loop, FALSE);
733 static const struct pw_core_events core_events = {
734 PW_VERSION_CORE_EVENTS,
735 .done = on_core_done,
736 .error = on_core_error,
739 static void *
740 qpw_audio_init(Audiodev *dev, Error **errp)
742 g_autofree pwaudio *pw = g_new0(pwaudio, 1);
744 assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE);
745 trace_pw_audio_init();
747 pw_init(NULL, NULL);
749 pw->dev = dev;
750 pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL);
751 if (pw->thread_loop == NULL) {
752 error_setg_errno(errp, errno, "Could not create PipeWire loop");
753 goto fail;
756 pw->context =
757 pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0);
758 if (pw->context == NULL) {
759 error_setg_errno(errp, errno, "Could not create PipeWire context");
760 goto fail;
763 if (pw_thread_loop_start(pw->thread_loop) < 0) {
764 error_setg_errno(errp, errno, "Could not start PipeWire loop");
765 goto fail;
768 pw_thread_loop_lock(pw->thread_loop);
770 pw->core = pw_context_connect(pw->context, NULL, 0);
771 if (pw->core == NULL) {
772 pw_thread_loop_unlock(pw->thread_loop);
773 goto fail_error;
776 if (pw_core_add_listener(pw->core, &pw->core_listener,
777 &core_events, pw) < 0) {
778 pw_thread_loop_unlock(pw->thread_loop);
779 goto fail_error;
781 if (wait_resync(pw) < 0) {
782 pw_thread_loop_unlock(pw->thread_loop);
785 pw_thread_loop_unlock(pw->thread_loop);
787 return g_steal_pointer(&pw);
789 fail_error:
790 error_setg(errp, "Failed to initialize PW context");
791 fail:
792 if (pw->thread_loop) {
793 pw_thread_loop_stop(pw->thread_loop);
795 g_clear_pointer(&pw->context, pw_context_destroy);
796 g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy);
797 return NULL;
800 static void
801 qpw_audio_fini(void *opaque)
803 pwaudio *pw = opaque;
805 if (pw->thread_loop) {
806 pw_thread_loop_stop(pw->thread_loop);
809 if (pw->core) {
810 spa_hook_remove(&pw->core_listener);
811 spa_zero(pw->core_listener);
812 pw_core_disconnect(pw->core);
815 if (pw->context) {
816 pw_context_destroy(pw->context);
818 pw_thread_loop_destroy(pw->thread_loop);
820 g_free(pw);
823 static struct audio_pcm_ops qpw_pcm_ops = {
824 .init_out = qpw_init_out,
825 .fini_out = qpw_fini_out,
826 .write = qpw_write,
827 .buffer_get_free = qpw_buffer_get_free,
828 .run_buffer_out = audio_generic_run_buffer_out,
829 .enable_out = qpw_enable_out,
830 .volume_out = qpw_volume_out,
831 .volume_in = qpw_volume_in,
833 .init_in = qpw_init_in,
834 .fini_in = qpw_fini_in,
835 .read = qpw_read,
836 .run_buffer_in = audio_generic_run_buffer_in,
837 .enable_in = qpw_enable_in
840 static struct audio_driver pw_audio_driver = {
841 .name = "pipewire",
842 .descr = "http://www.pipewire.org/",
843 .init = qpw_audio_init,
844 .fini = qpw_audio_fini,
845 .pcm_ops = &qpw_pcm_ops,
846 .max_voices_out = INT_MAX,
847 .max_voices_in = INT_MAX,
848 .voice_size_out = sizeof(PWVoiceOut),
849 .voice_size_in = sizeof(PWVoiceIn),
852 static void
853 register_audio_pw(void)
855 audio_driver_register(&pw_audio_driver);
858 type_init(register_audio_pw);