xref: /openbmc/qemu/audio/pwaudio.c (revision c1774bdb)
1 /*
2  * QEMU PipeWire audio driver
3  *
4  * Copyright (c) 2023 Red Hat Inc.
5  *
6  * Author: Dorinda Bassey       <dbassey@redhat.com>
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
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>
21 
22 #include <pipewire/pipewire.h>
23 #include "trace.h"
24 
25 #define AUDIO_CAP "pipewire"
26 #define RINGBUFFER_SIZE    (1u << 22)
27 #define RINGBUFFER_MASK    (RINGBUFFER_SIZE - 1)
28 
29 #include "audio_int.h"
30 
31 typedef struct pwvolume {
32     uint32_t channels;
33     float values[SPA_AUDIO_MAX_CHANNELS];
34 } pwvolume;
35 
36 typedef struct pwaudio {
37     Audiodev *dev;
38     struct pw_thread_loop *thread_loop;
39     struct pw_context *context;
40 
41     struct pw_core *core;
42     struct spa_hook core_listener;
43     int last_seq, pending_seq, error;
44 } pwaudio;
45 
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];
55 
56     pwvolume volume;
57     bool muted;
58 } PWVoice;
59 
60 typedef struct PWVoiceOut {
61     HWVoiceOut hw;
62     PWVoice v;
63 } PWVoiceOut;
64 
65 typedef struct PWVoiceIn {
66     HWVoiceIn hw;
67     PWVoice v;
68 } PWVoiceIn;
69 
70 #define PW_VOICE_IN(v) ((PWVoiceIn *)v)
71 #define PW_VOICE_OUT(v) ((PWVoiceOut *)v)
72 
73 static void
74 stream_destroy(void *data)
75 {
76     PWVoice *v = (PWVoice *) data;
77     spa_hook_remove(&v->stream_listener);
78     v->stream = NULL;
79 }
80 
81 /* output data processing function to read stuffs from the buffer */
82 static void
83 playback_on_process(void *data)
84 {
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;
91 
92     assert(v->stream);
93 
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;
99     }
100 
101     buf = b->buffer;
102     p = buf->datas[0].data;
103     if (p == NULL) {
104         return;
105     }
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;
110     }
111     n_bytes = SPA_MIN(req, buf->datas[0].maxsize);
112 
113     /* get no of available bytes to read data from buffer */
114     avail = spa_ringbuffer_get_read_index(&v->ring, &index);
115 
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) {
121             /*
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.
125              */
126             n_bytes = avail;
127         }
128 
129         spa_ringbuffer_read_data(&v->ring,
130                                     v->buffer, RINGBUFFER_SIZE,
131                                     index & RINGBUFFER_MASK, p, n_bytes);
132 
133         index += n_bytes;
134         spa_ringbuffer_read_update(&v->ring, index);
135 
136     }
137     buf->datas[0].chunk->offset = 0;
138     buf->datas[0].chunk->stride = v->frame_size;
139     buf->datas[0].chunk->size = n_bytes;
140 
141     /* queue the buffer for playback */
142     pw_stream_queue_buffer(v->stream, b);
143 }
144 
145 /* output data processing function to generate stuffs in the buffer */
146 static void
147 capture_on_process(void *data)
148 {
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;
155 
156     assert(v->stream);
157 
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;
163     }
164 
165     /* Write data into buffer */
166     buf = b->buffer;
167     p = buf->datas[0].data;
168     if (p == NULL) {
169         return;
170     }
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);
173 
174     filled = spa_ringbuffer_get_write_index(&v->ring, &index);
175 
176 
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);
183         }
184     }
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);
191 
192     /* queue the buffer for playback */
193     pw_stream_queue_buffer(v->stream, b);
194 }
195 
196 static void
197 on_stream_state_changed(void *data, enum pw_stream_state old,
198                         enum pw_stream_state state, const char *error)
199 {
200     PWVoice *v = (PWVoice *) data;
201 
202     trace_pw_state_changed(pw_stream_get_node_id(v->stream),
203                            pw_stream_state_as_string(state));
204 }
205 
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
211 };
212 
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
218 };
219 
220 static size_t
221 qpw_read(HWVoiceIn *hw, void *data, size_t len)
222 {
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;
230 
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;
236     }
237     /* get no of available bytes to read data from buffer */
238     avail = spa_ringbuffer_get_read_index(&v->ring, &index);
239 
240     trace_pw_read(avail, index, len);
241 
242     if (avail < (int32_t) len) {
243         len = avail;
244     }
245 
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;
252 
253 done_unlock:
254     pw_thread_loop_unlock(c->thread_loop);
255     return l;
256 }
257 
258 static size_t qpw_buffer_get_free(HWVoiceOut *hw)
259 {
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;
266 
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;
272     }
273 
274     filled = spa_ringbuffer_get_write_index(&v->ring, &index);
275     avail = v->highwater_mark - filled;
276 
277 done_unlock:
278     pw_thread_loop_unlock(c->thread_loop);
279     return avail;
280 }
281 
282 static size_t
283 qpw_write(HWVoiceOut *hw, void *data, size_t len)
284 {
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;
291 
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;
297     }
298     filled = spa_ringbuffer_get_write_index(&v->ring, &index);
299     avail = v->highwater_mark - filled;
300 
301     trace_pw_write(filled, avail, index, len);
302 
303     if (len > avail) {
304         len = avail;
305     }
306 
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);
313         }
314     }
315 
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);
321 
322 done_unlock:
323     pw_thread_loop_unlock(c->thread_loop);
324     return len;
325 }
326 
327 static int
328 audfmt_to_pw(AudioFormat fmt, int endianness)
329 {
330     int format;
331 
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;
358     }
359     return format;
360 }
361 
362 static AudioFormat
363 pw_to_audfmt(enum spa_audio_format fmt, int *endianness,
364              uint32_t *sample_size)
365 {
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;
417     }
418 }
419 
420 static int
421 qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name,
422                const char *name, enum spa_direction dir)
423 {
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;
431 
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;
436     }
437 
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);
443 
444     trace_pw_period(buf_samples, v->info.rate);
445     if (name) {
446         pw_properties_set(props, PW_KEY_TARGET_OBJECT, name);
447     }
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;
452     }
453 
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);
460     }
461 
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);
467 
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;
481     }
482 
483     return 0;
484 }
485 
486 static void
487 qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS])
488 {
489     memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, },
490            sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS);
491     /*
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.
495      */
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);
516     }
517 }
518 
519 static int
520 qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
521 {
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;
529 
530     pw_thread_loop_lock(c->thread_loop);
531 
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;
536 
537     obt_as.fmt =
538         pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size);
539     v->frame_size *= as->nchannels;
540 
541     v->req = (uint64_t)c->dev->timer_period * v->info.rate
542         * 1 / 2 / 1000000 * v->frame_size;
543 
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;
550     }
551 
552     /* report the audio format we support */
553     audio_pcm_init_info(&hw->info, &obt_as);
554 
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);
561 
562     pw_thread_loop_unlock(c->thread_loop);
563     return 0;
564 }
565 
566 static int
567 qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
568 {
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;
576 
577     pw_thread_loop_lock(c->thread_loop);
578 
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;
583 
584     obt_as.fmt =
585         pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size);
586     v->frame_size *= as->nchannels;
587 
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;
594     }
595 
596     /* report the audio format we support */
597     audio_pcm_init_info(&hw->info, &obt_as);
598 
599     /* report the buffer size to qemu */
600     hw->samples = audio_buffer_frames(
601         qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
602 
603     pw_thread_loop_unlock(c->thread_loop);
604     return 0;
605 }
606 
607 static void
608 qpw_voice_fini(PWVoice *v)
609 {
610     pwaudio *c = v->g;
611 
612     if (!v->stream) {
613         return;
614     }
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);
619 }
620 
621 static void
622 qpw_fini_out(HWVoiceOut *hw)
623 {
624     qpw_voice_fini(&PW_VOICE_OUT(hw)->v);
625 }
626 
627 static void
628 qpw_fini_in(HWVoiceIn *hw)
629 {
630     qpw_voice_fini(&PW_VOICE_IN(hw)->v);
631 }
632 
633 static void
634 qpw_voice_set_enabled(PWVoice *v, bool enable)
635 {
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);
640 }
641 
642 static void
643 qpw_enable_out(HWVoiceOut *hw, bool enable)
644 {
645     qpw_voice_set_enabled(&PW_VOICE_OUT(hw)->v, enable);
646 }
647 
648 static void
649 qpw_enable_in(HWVoiceIn *hw, bool enable)
650 {
651     qpw_voice_set_enabled(&PW_VOICE_IN(hw)->v, enable);
652 }
653 
654 static void
655 qpw_voice_set_volume(PWVoice *v, Volume *vol)
656 {
657     pwaudio *c = v->g;
658     int i, ret;
659 
660     pw_thread_loop_lock(c->thread_loop);
661     v->volume.channels = vol->channels;
662 
663     for (i = 0; i < vol->channels; ++i) {
664         v->volume.values[i] = (float)vol->vol[i] / 255;
665     }
666 
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");
670 
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);
675 }
676 
677 static void
678 qpw_volume_out(HWVoiceOut *hw, Volume *vol)
679 {
680     qpw_voice_set_volume(&PW_VOICE_OUT(hw)->v, vol);
681 }
682 
683 static void
684 qpw_volume_in(HWVoiceIn *hw, Volume *vol)
685 {
686     qpw_voice_set_volume(&PW_VOICE_IN(hw)->v, vol);
687 }
688 
689 static int wait_resync(pwaudio *pw)
690 {
691     int res;
692     pw->pending_seq = pw_core_sync(pw->core, PW_ID_CORE, pw->pending_seq);
693 
694     while (true) {
695         pw_thread_loop_wait(pw->thread_loop);
696 
697         res = pw->error;
698         if (res < 0) {
699             pw->error = 0;
700             return res;
701         }
702         if (pw->pending_seq == pw->last_seq) {
703             break;
704         }
705     }
706     return 0;
707 }
708 
709 static void
710 on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
711 {
712     pwaudio *pw = data;
713 
714     error_report("error id:%u seq:%d res:%d (%s): %s",
715                 id, seq, res, spa_strerror(res), message);
716 
717     /* stop and exit the thread loop */
718     pw_thread_loop_signal(pw->thread_loop, FALSE);
719 }
720 
721 static void
722 on_core_done(void *data, uint32_t id, int seq)
723 {
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);
730     }
731 }
732 
733 static const struct pw_core_events core_events = {
734     PW_VERSION_CORE_EVENTS,
735     .done = on_core_done,
736     .error = on_core_error,
737 };
738 
739 static void *
740 qpw_audio_init(Audiodev *dev, Error **errp)
741 {
742     g_autofree pwaudio *pw = g_new0(pwaudio, 1);
743 
744     assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE);
745     trace_pw_audio_init();
746 
747     pw_init(NULL, NULL);
748 
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;
754     }
755 
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;
761     }
762 
763     if (pw_thread_loop_start(pw->thread_loop) < 0) {
764         error_setg_errno(errp, errno, "Could not start PipeWire loop");
765         goto fail;
766     }
767 
768     pw_thread_loop_lock(pw->thread_loop);
769 
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;
774     }
775 
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;
780     }
781     if (wait_resync(pw) < 0) {
782         pw_thread_loop_unlock(pw->thread_loop);
783     }
784 
785     pw_thread_loop_unlock(pw->thread_loop);
786 
787     return g_steal_pointer(&pw);
788 
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);
794     }
795     g_clear_pointer(&pw->context, pw_context_destroy);
796     g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy);
797     return NULL;
798 }
799 
800 static void
801 qpw_audio_fini(void *opaque)
802 {
803     pwaudio *pw = opaque;
804 
805     if (pw->thread_loop) {
806         pw_thread_loop_stop(pw->thread_loop);
807     }
808 
809     if (pw->core) {
810         spa_hook_remove(&pw->core_listener);
811         spa_zero(pw->core_listener);
812         pw_core_disconnect(pw->core);
813     }
814 
815     if (pw->context) {
816         pw_context_destroy(pw->context);
817     }
818     pw_thread_loop_destroy(pw->thread_loop);
819 
820     g_free(pw);
821 }
822 
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,
832 
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
838 };
839 
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),
850 };
851 
852 static void
853 register_audio_pw(void)
854 {
855     audio_driver_register(&pw_audio_driver);
856 }
857 
858 type_init(register_audio_pw);
859