master
c 864 lines 23.8 KB
Raw
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 "qemu/audio.h"
14 #include "qemu/error-report.h"
15 #include "qapi/error.h"
16 #include "qom/object.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
24 #include "audio_int.h"
25 #include "trace.h"
26
27 #define RINGBUFFER_SIZE (1u << 22)
28 #define RINGBUFFER_MASK (RINGBUFFER_SIZE - 1)
29
30 #define TYPE_AUDIO_PW "audio-pipewire"
31 OBJECT_DECLARE_SIMPLE_TYPE(AudioPw, AUDIO_PW)
32
33 static AudioBackendClass *audio_pw_parent_class;
34
35 struct AudioPw {
36 AudioMixengBackend parent_obj;
37
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 };
45
46
47 typedef struct pwvolume {
48 uint32_t channels;
49 float values[SPA_AUDIO_MAX_CHANNELS];
50 } pwvolume;
51
52 typedef struct PWVoice {
53 struct pw_stream *stream;
54 struct spa_hook stream_listener;
55 struct spa_audio_info_raw info;
56 uint32_t highwater_mark;
57 uint32_t frame_size, req;
58 struct spa_ringbuffer ring;
59 uint8_t buffer[RINGBUFFER_SIZE];
60
61 pwvolume volume;
62 bool muted;
63 } PWVoice;
64
65 typedef struct PWVoiceOut {
66 HWVoiceOut hw;
67 PWVoice v;
68 } PWVoiceOut;
69
70 typedef struct PWVoiceIn {
71 HWVoiceIn hw;
72 PWVoice v;
73 } PWVoiceIn;
74
75 #define PW_VOICE_IN(v) ((PWVoiceIn *)v)
76 #define PW_VOICE_OUT(v) ((PWVoiceOut *)v)
77
78 static void
79 stream_destroy(void *data)
80 {
81 PWVoice *v = (PWVoice *) data;
82 spa_hook_remove(&v->stream_listener);
83 v->stream = NULL;
84 }
85
86 /* output data processing function to read stuffs from the buffer */
87 static void
88 playback_on_process(void *data)
89 {
90 PWVoice *v = data;
91 void *p;
92 struct pw_buffer *b;
93 struct spa_buffer *buf;
94 uint32_t req, index, n_bytes;
95 int32_t avail;
96
97 assert(v->stream);
98
99 /* obtain a buffer to read from */
100 b = pw_stream_dequeue_buffer(v->stream);
101 if (b == NULL) {
102 error_report("out of buffers: %s", strerror(errno));
103 return;
104 }
105
106 buf = b->buffer;
107 p = buf->datas[0].data;
108 if (p == NULL) {
109 return;
110 }
111 /* calculate the total no of bytes to read data from buffer */
112 req = b->requested * v->frame_size;
113 if (req == 0) {
114 req = v->req;
115 }
116 n_bytes = SPA_MIN(req, buf->datas[0].maxsize);
117
118 /* get no of available bytes to read data from buffer */
119 avail = spa_ringbuffer_get_read_index(&v->ring, &index);
120
121 if (avail <= 0) {
122 PWVoiceOut *vo = container_of(data, PWVoiceOut, v);
123 audio_pcm_info_clear_buf(&vo->hw.info, p, n_bytes / v->frame_size);
124 } else {
125 if ((uint32_t) avail < n_bytes) {
126 /*
127 * PipeWire immediately calls this callback again if we provide
128 * less than n_bytes. Then audio_pcm_info_clear_buf() fills the
129 * rest of the buffer with silence.
130 */
131 n_bytes = avail;
132 }
133
134 spa_ringbuffer_read_data(&v->ring,
135 v->buffer, RINGBUFFER_SIZE,
136 index & RINGBUFFER_MASK, p, n_bytes);
137
138 index += n_bytes;
139 spa_ringbuffer_read_update(&v->ring, index);
140
141 }
142 buf->datas[0].chunk->offset = 0;
143 buf->datas[0].chunk->stride = v->frame_size;
144 buf->datas[0].chunk->size = n_bytes;
145
146 /* queue the buffer for playback */
147 pw_stream_queue_buffer(v->stream, b);
148 }
149
150 /* output data processing function to generate stuffs in the buffer */
151 static void
152 capture_on_process(void *data)
153 {
154 PWVoice *v = (PWVoice *) data;
155 void *p;
156 struct pw_buffer *b;
157 struct spa_buffer *buf;
158 int32_t filled;
159 uint32_t index, offs, n_bytes;
160
161 assert(v->stream);
162
163 /* obtain a buffer */
164 b = pw_stream_dequeue_buffer(v->stream);
165 if (b == NULL) {
166 error_report("out of buffers: %s", strerror(errno));
167 return;
168 }
169
170 /* Write data into buffer */
171 buf = b->buffer;
172 p = buf->datas[0].data;
173 if (p == NULL) {
174 return;
175 }
176 offs = SPA_MIN(buf->datas[0].chunk->offset, buf->datas[0].maxsize);
177 n_bytes = SPA_MIN(buf->datas[0].chunk->size, buf->datas[0].maxsize - offs);
178
179 filled = spa_ringbuffer_get_write_index(&v->ring, &index);
180
181
182 if (filled < 0) {
183 error_report("%p: underrun write:%u filled:%d", p, index, filled);
184 } else {
185 if ((uint32_t) filled + n_bytes > RINGBUFFER_SIZE) {
186 error_report("%p: overrun write:%u filled:%d + size:%u > max:%u",
187 p, index, filled, n_bytes, RINGBUFFER_SIZE);
188 }
189 }
190 spa_ringbuffer_write_data(&v->ring,
191 v->buffer, RINGBUFFER_SIZE,
192 index & RINGBUFFER_MASK,
193 SPA_PTROFF(p, offs, void), n_bytes);
194 index += n_bytes;
195 spa_ringbuffer_write_update(&v->ring, index);
196
197 /* queue the buffer for playback */
198 pw_stream_queue_buffer(v->stream, b);
199 }
200
201 static void
202 on_stream_state_changed(void *data, enum pw_stream_state old,
203 enum pw_stream_state state, const char *error)
204 {
205 PWVoice *v = (PWVoice *) data;
206
207 trace_pw_state_changed(pw_stream_get_node_id(v->stream),
208 pw_stream_state_as_string(state));
209 }
210
211 static const struct pw_stream_events capture_stream_events = {
212 PW_VERSION_STREAM_EVENTS,
213 .destroy = stream_destroy,
214 .state_changed = on_stream_state_changed,
215 .process = capture_on_process
216 };
217
218 static const struct pw_stream_events playback_stream_events = {
219 PW_VERSION_STREAM_EVENTS,
220 .destroy = stream_destroy,
221 .state_changed = on_stream_state_changed,
222 .process = playback_on_process
223 };
224
225 static size_t
226 qpw_read(HWVoiceIn *hw, void *data, size_t len)
227 {
228 AudioPw *c = AUDIO_PW(hw->s);
229 PWVoiceIn *pw = (PWVoiceIn *) hw;
230 PWVoice *v = &pw->v;
231 const char *error = NULL;
232 size_t l;
233 int32_t avail;
234 uint32_t index;
235
236 pw_thread_loop_lock(c->thread_loop);
237 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
238 /* wait for stream to become ready */
239 l = 0;
240 goto done_unlock;
241 }
242 /* get no of available bytes to read data from buffer */
243 avail = spa_ringbuffer_get_read_index(&v->ring, &index);
244
245 trace_pw_read(avail, index, len);
246
247 if (avail < (int32_t) len) {
248 len = avail;
249 }
250
251 spa_ringbuffer_read_data(&v->ring,
252 v->buffer, RINGBUFFER_SIZE,
253 index & RINGBUFFER_MASK, data, len);
254 index += len;
255 spa_ringbuffer_read_update(&v->ring, index);
256 l = len;
257
258 done_unlock:
259 pw_thread_loop_unlock(c->thread_loop);
260 return l;
261 }
262
263 static size_t qpw_buffer_get_free(HWVoiceOut *hw)
264 {
265 AudioPw *c = AUDIO_PW(hw->s);
266 PWVoiceOut *pw = (PWVoiceOut *)hw;
267 PWVoice *v = &pw->v;
268 const char *error = NULL;
269 int32_t filled, avail;
270 uint32_t index;
271
272 pw_thread_loop_lock(c->thread_loop);
273 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
274 /* wait for stream to become ready */
275 avail = 0;
276 goto done_unlock;
277 }
278
279 filled = spa_ringbuffer_get_write_index(&v->ring, &index);
280 avail = v->highwater_mark - filled;
281
282 done_unlock:
283 pw_thread_loop_unlock(c->thread_loop);
284 return avail;
285 }
286
287 static size_t
288 qpw_write(HWVoiceOut *hw, void *data, size_t len)
289 {
290 AudioPw *c = AUDIO_PW(hw->s);
291 PWVoiceOut *pw = (PWVoiceOut *) hw;
292 PWVoice *v = &pw->v;
293 const char *error = NULL;
294 int32_t filled, avail;
295 uint32_t index;
296
297 pw_thread_loop_lock(c->thread_loop);
298 if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
299 /* wait for stream to become ready */
300 len = 0;
301 goto done_unlock;
302 }
303 filled = spa_ringbuffer_get_write_index(&v->ring, &index);
304 avail = v->highwater_mark - filled;
305
306 trace_pw_write(filled, avail, index, len);
307
308 if (len > avail) {
309 len = avail;
310 }
311
312 if (filled < 0) {
313 error_report("%p: underrun write:%u filled:%d", pw, index, filled);
314 } else {
315 if ((uint32_t) filled + len > RINGBUFFER_SIZE) {
316 error_report("%p: overrun write:%u filled:%d + size:%zu > max:%u",
317 pw, index, filled, len, RINGBUFFER_SIZE);
318 }
319 }
320
321 spa_ringbuffer_write_data(&v->ring,
322 v->buffer, RINGBUFFER_SIZE,
323 index & RINGBUFFER_MASK, data, len);
324 index += len;
325 spa_ringbuffer_write_update(&v->ring, index);
326
327 done_unlock:
328 pw_thread_loop_unlock(c->thread_loop);
329 return len;
330 }
331
332 static int
333 audfmt_to_pw(AudioFormat fmt, bool big_endian)
334 {
335 int format;
336
337 switch (fmt) {
338 case AUDIO_FORMAT_S8:
339 format = SPA_AUDIO_FORMAT_S8;
340 break;
341 case AUDIO_FORMAT_U8:
342 format = SPA_AUDIO_FORMAT_U8;
343 break;
344 case AUDIO_FORMAT_S16:
345 format = big_endian ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE;
346 break;
347 case AUDIO_FORMAT_U16:
348 format = big_endian ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE;
349 break;
350 case AUDIO_FORMAT_S32:
351 format = big_endian ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE;
352 break;
353 case AUDIO_FORMAT_U32:
354 format = big_endian ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE;
355 break;
356 case AUDIO_FORMAT_F32:
357 format = big_endian ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE;
358 break;
359 default:
360 error_report("pipewire: internal logic error: bad audio format %d", fmt);
361 format = SPA_AUDIO_FORMAT_U8;
362 break;
363 }
364 return format;
365 }
366
367 static AudioFormat
368 pw_to_audfmt(enum spa_audio_format fmt, bool *big_endian,
369 uint32_t *sample_size)
370 {
371 switch (fmt) {
372 case SPA_AUDIO_FORMAT_S8:
373 *sample_size = 1;
374 return AUDIO_FORMAT_S8;
375 case SPA_AUDIO_FORMAT_U8:
376 *sample_size = 1;
377 return AUDIO_FORMAT_U8;
378 case SPA_AUDIO_FORMAT_S16_BE:
379 *sample_size = 2;
380 *big_endian = true;
381 return AUDIO_FORMAT_S16;
382 case SPA_AUDIO_FORMAT_S16_LE:
383 *sample_size = 2;
384 *big_endian = false;
385 return AUDIO_FORMAT_S16;
386 case SPA_AUDIO_FORMAT_U16_BE:
387 *sample_size = 2;
388 *big_endian = true;
389 return AUDIO_FORMAT_U16;
390 case SPA_AUDIO_FORMAT_U16_LE:
391 *sample_size = 2;
392 *big_endian = false;
393 return AUDIO_FORMAT_U16;
394 case SPA_AUDIO_FORMAT_S32_BE:
395 *sample_size = 4;
396 *big_endian = true;
397 return AUDIO_FORMAT_S32;
398 case SPA_AUDIO_FORMAT_S32_LE:
399 *sample_size = 4;
400 *big_endian = false;
401 return AUDIO_FORMAT_S32;
402 case SPA_AUDIO_FORMAT_U32_BE:
403 *sample_size = 4;
404 *big_endian = true;
405 return AUDIO_FORMAT_U32;
406 case SPA_AUDIO_FORMAT_U32_LE:
407 *sample_size = 4;
408 *big_endian = false;
409 return AUDIO_FORMAT_U32;
410 case SPA_AUDIO_FORMAT_F32_BE:
411 *sample_size = 4;
412 *big_endian = true;
413 return AUDIO_FORMAT_F32;
414 case SPA_AUDIO_FORMAT_F32_LE:
415 *sample_size = 4;
416 *big_endian = false;
417 return AUDIO_FORMAT_F32;
418 default:
419 *sample_size = 1;
420 error_report("pipewire: internal logic error: bad spa_audio_format %d", fmt);
421 return AUDIO_FORMAT_U8;
422 }
423 }
424
425 static int
426 qpw_stream_new(AudioPw *c, PWVoice *v, const char *stream_name,
427 const char *name, enum spa_direction dir)
428 {
429 int res;
430 uint32_t n_params;
431 const struct spa_pod *params[2];
432 uint8_t buffer[1024];
433 struct spa_pod_builder b;
434 uint64_t buf_samples;
435 struct pw_properties *props;
436
437 props = pw_properties_new(NULL, NULL);
438 if (!props) {
439 error_report("Failed to create PW properties: %s", g_strerror(errno));
440 return -1;
441 }
442
443 /* 75% of the timer period for faster updates */
444 buf_samples = (uint64_t)AUDIO_MIXENG_BACKEND(c)->dev->timer_period
445 * v->info.rate * 3 / 4 / 1000000;
446 pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%" PRIu64 "/%u",
447 buf_samples, v->info.rate);
448
449 trace_pw_period(buf_samples, v->info.rate);
450 if (name) {
451 pw_properties_set(props, PW_KEY_TARGET_OBJECT, name);
452 }
453 v->stream = pw_stream_new(c->core, stream_name, props);
454 if (v->stream == NULL) {
455 error_report("Failed to create PW stream: %s", g_strerror(errno));
456 return -1;
457 }
458
459 if (dir == SPA_DIRECTION_INPUT) {
460 pw_stream_add_listener(v->stream,
461 &v->stream_listener, &capture_stream_events, v);
462 } else {
463 pw_stream_add_listener(v->stream,
464 &v->stream_listener, &playback_stream_events, v);
465 }
466
467 n_params = 0;
468 spa_pod_builder_init(&b, buffer, sizeof(buffer));
469 params[n_params++] = spa_format_audio_raw_build(&b,
470 SPA_PARAM_EnumFormat,
471 &v->info);
472
473 /* connect the stream to a sink or source */
474 res = pw_stream_connect(v->stream,
475 dir ==
476 SPA_DIRECTION_INPUT ? PW_DIRECTION_INPUT :
477 PW_DIRECTION_OUTPUT, PW_ID_ANY,
478 PW_STREAM_FLAG_AUTOCONNECT |
479 PW_STREAM_FLAG_INACTIVE |
480 PW_STREAM_FLAG_MAP_BUFFERS |
481 PW_STREAM_FLAG_RT_PROCESS, params, n_params);
482 if (res < 0) {
483 error_report("Failed to connect PW stream: %s", g_strerror(errno));
484 pw_stream_destroy(v->stream);
485 return -1;
486 }
487
488 return 0;
489 }
490
491 static void
492 qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS])
493 {
494 memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, },
495 sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS);
496 /*
497 * TODO: This currently expects the only frontend supporting more than 2
498 * channels is the usb-audio. We will need some means to set channel
499 * order when a new frontend gains multi-channel support.
500 */
501 switch (channels) {
502 case 8:
503 position[6] = SPA_AUDIO_CHANNEL_SL;
504 position[7] = SPA_AUDIO_CHANNEL_SR;
505 /* fallthrough */
506 case 6:
507 position[2] = SPA_AUDIO_CHANNEL_FC;
508 position[3] = SPA_AUDIO_CHANNEL_LFE;
509 position[4] = SPA_AUDIO_CHANNEL_RL;
510 position[5] = SPA_AUDIO_CHANNEL_RR;
511 /* fallthrough */
512 case 2:
513 position[0] = SPA_AUDIO_CHANNEL_FL;
514 position[1] = SPA_AUDIO_CHANNEL_FR;
515 break;
516 case 1:
517 position[0] = SPA_AUDIO_CHANNEL_MONO;
518 break;
519 default:
520 error_report("pipewire: unsupported channel count %d", channels);
521 }
522 }
523
524 static int
525 qpw_init_out(HWVoiceOut *hw, struct audsettings *as)
526 {
527 AudioPw *c = AUDIO_PW(hw->s);
528 PWVoiceOut *pw = (PWVoiceOut *) hw;
529 PWVoice *v = &pw->v;
530 struct audsettings obt_as = *as;
531 AudiodevPipewireOptions *popts = &AUDIO_MIXENG_BACKEND(c)->dev->u.pipewire;
532 AudiodevPipewirePerDirectionOptions *ppdo = popts->out;
533 int r;
534
535 pw_thread_loop_lock(c->thread_loop);
536
537 v->info.format = audfmt_to_pw(as->fmt, as->big_endian);
538 v->info.channels = as->nchannels;
539 qpw_set_position(as->nchannels, v->info.position);
540 v->info.rate = as->freq;
541
542 obt_as.fmt =
543 pw_to_audfmt(v->info.format, &obt_as.big_endian, &v->frame_size);
544 v->frame_size *= as->nchannels;
545
546 v->req = (uint64_t)AUDIO_MIXENG_BACKEND(c)->dev->timer_period * v->info.rate
547 * 1 / 2 / 1000000 * v->frame_size;
548
549 /* call the function that creates a new stream for playback */
550 r = qpw_stream_new(c, v, ppdo->stream_name ?: AUDIO_MIXENG_BACKEND(c)->dev->id,
551 ppdo->name, SPA_DIRECTION_OUTPUT);
552 if (r < 0) {
553 pw_thread_loop_unlock(c->thread_loop);
554 return -1;
555 }
556
557 /* report the audio format we support */
558 audio_pcm_init_info(&hw->info, &obt_as);
559
560 /* report the buffer size to qemu */
561 hw->samples = audio_buffer_frames(
562 qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
563 v->highwater_mark = MIN(RINGBUFFER_SIZE,
564 (ppdo->has_latency ? ppdo->latency : 46440)
565 * (uint64_t)v->info.rate / 1000000 * v->frame_size);
566
567 pw_thread_loop_unlock(c->thread_loop);
568 return 0;
569 }
570
571 static int
572 qpw_init_in(HWVoiceIn *hw, struct audsettings *as)
573 {
574 AudioPw *c = AUDIO_PW(hw->s);
575 PWVoiceIn *pw = (PWVoiceIn *) hw;
576 PWVoice *v = &pw->v;
577 struct audsettings obt_as = *as;
578 AudiodevPipewireOptions *popts = &AUDIO_MIXENG_BACKEND(c)->dev->u.pipewire;
579 AudiodevPipewirePerDirectionOptions *ppdo = popts->in;
580 int r;
581
582 pw_thread_loop_lock(c->thread_loop);
583
584 v->info.format = audfmt_to_pw(as->fmt, as->big_endian);
585 v->info.channels = as->nchannels;
586 qpw_set_position(as->nchannels, v->info.position);
587 v->info.rate = as->freq;
588
589 obt_as.fmt =
590 pw_to_audfmt(v->info.format, &obt_as.big_endian, &v->frame_size);
591 v->frame_size *= as->nchannels;
592
593 /* call the function that creates a new stream for recording */
594 r = qpw_stream_new(c, v, ppdo->stream_name ? : AUDIO_MIXENG_BACKEND(c)->dev->id,
595 ppdo->name, SPA_DIRECTION_INPUT);
596 if (r < 0) {
597 pw_thread_loop_unlock(c->thread_loop);
598 return -1;
599 }
600
601 /* report the audio format we support */
602 audio_pcm_init_info(&hw->info, &obt_as);
603
604 /* report the buffer size to qemu */
605 hw->samples = audio_buffer_frames(
606 qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
607
608 pw_thread_loop_unlock(c->thread_loop);
609 return 0;
610 }
611
612 static void
613 qpw_voice_fini(AudioPw *c, PWVoice *v)
614 {
615 if (!v->stream) {
616 return;
617 }
618 pw_thread_loop_lock(c->thread_loop);
619 pw_stream_destroy(v->stream);
620 v->stream = NULL;
621 pw_thread_loop_unlock(c->thread_loop);
622 }
623
624 static void
625 qpw_fini_out(HWVoiceOut *hw)
626 {
627 qpw_voice_fini(AUDIO_PW(hw->s), &PW_VOICE_OUT(hw)->v);
628 }
629
630 static void
631 qpw_fini_in(HWVoiceIn *hw)
632 {
633 qpw_voice_fini(AUDIO_PW(hw->s), &PW_VOICE_IN(hw)->v);
634 }
635
636 static void
637 qpw_voice_set_enabled(AudioPw *c, PWVoice *v, bool enable)
638 {
639 pw_thread_loop_lock(c->thread_loop);
640 pw_stream_set_active(v->stream, enable);
641 pw_thread_loop_unlock(c->thread_loop);
642 }
643
644 static void
645 qpw_enable_out(HWVoiceOut *hw, bool enable)
646 {
647 qpw_voice_set_enabled(AUDIO_PW(hw->s), &PW_VOICE_OUT(hw)->v, enable);
648 }
649
650 static void
651 qpw_enable_in(HWVoiceIn *hw, bool enable)
652 {
653 qpw_voice_set_enabled(AUDIO_PW(hw->s), &PW_VOICE_IN(hw)->v, enable);
654 }
655
656 static void
657 qpw_voice_set_volume(AudioPw *c, PWVoice *v, Volume *vol)
658 {
659 int i, ret;
660
661 pw_thread_loop_lock(c->thread_loop);
662 v->volume.channels = vol->channels;
663
664 for (i = 0; i < vol->channels; ++i) {
665 v->volume.values[i] = (float)vol->vol[i] / 255;
666 }
667
668 ret = pw_stream_set_control(v->stream,
669 SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0);
670 trace_pw_vol(ret == 0 ? "success" : "failed");
671
672 v->muted = vol->mute;
673 float val = v->muted ? 1.f : 0.f;
674 ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0);
675 pw_thread_loop_unlock(c->thread_loop);
676 }
677
678 static void
679 qpw_volume_out(HWVoiceOut *hw, Volume *vol)
680 {
681 qpw_voice_set_volume(AUDIO_PW(hw->s), &PW_VOICE_OUT(hw)->v, vol);
682 }
683
684 static void
685 qpw_volume_in(HWVoiceIn *hw, Volume *vol)
686 {
687 qpw_voice_set_volume(AUDIO_PW(hw->s), &PW_VOICE_IN(hw)->v, vol);
688 }
689
690 static int wait_resync(AudioPw *pw)
691 {
692 int res;
693 pw->pending_seq = pw_core_sync(pw->core, PW_ID_CORE, pw->pending_seq);
694
695 while (true) {
696 pw_thread_loop_wait(pw->thread_loop);
697
698 res = pw->error;
699 if (res < 0) {
700 pw->error = 0;
701 return res;
702 }
703 if (pw->pending_seq == pw->last_seq) {
704 break;
705 }
706 }
707 return 0;
708 }
709
710 static void
711 on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
712 {
713 AudioPw *pw = data;
714
715 error_report("error id:%u seq:%d res:%d (%s): %s",
716 id, seq, res, spa_strerror(res), message);
717
718 /* stop and exit the thread loop */
719 pw_thread_loop_signal(pw->thread_loop, FALSE);
720 }
721
722 static void
723 on_core_done(void *data, uint32_t id, int seq)
724 {
725 AudioPw *pw = data;
726 assert(id == PW_ID_CORE);
727 pw->last_seq = seq;
728 if (pw->pending_seq == seq) {
729 /* stop and exit the thread loop */
730 pw_thread_loop_signal(pw->thread_loop, FALSE);
731 }
732 }
733
734 static const struct pw_core_events core_events = {
735 PW_VERSION_CORE_EVENTS,
736 .done = on_core_done,
737 .error = on_core_error,
738 };
739
740 static bool
741 audio_pw_realize(AudioBackend *abe, Audiodev *dev, Error **errp)
742 {
743 AudioPw *pw = AUDIO_PW(abe);
744
745 assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE);
746 trace_pw_audio_init();
747
748 if (!audio_pw_parent_class->realize(abe, dev, errp)) {
749 return false;
750 }
751
752 pw_init(NULL, NULL);
753
754 pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL);
755 if (pw->thread_loop == NULL) {
756 error_setg_errno(errp, errno, "Could not create PipeWire loop");
757 goto fail;
758 }
759
760 pw->context =
761 pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0);
762 if (pw->context == NULL) {
763 error_setg_errno(errp, errno, "Could not create PipeWire context");
764 goto fail;
765 }
766
767 if (pw_thread_loop_start(pw->thread_loop) < 0) {
768 error_setg_errno(errp, errno, "Could not start PipeWire loop");
769 goto fail;
770 }
771
772 pw_thread_loop_lock(pw->thread_loop);
773
774 pw->core = pw_context_connect(pw->context, NULL, 0);
775 if (pw->core == NULL) {
776 pw_thread_loop_unlock(pw->thread_loop);
777 error_setg_errno(errp, errno, "Failed to connect to PipeWire instance");
778 goto fail;
779 }
780
781 if (pw_core_add_listener(pw->core, &pw->core_listener,
782 &core_events, pw) < 0) {
783 pw_thread_loop_unlock(pw->thread_loop);
784 error_setg(errp, "Failed to add PipeWire listener");
785 goto fail;
786 }
787 if (wait_resync(pw) < 0) {
788 pw_thread_loop_unlock(pw->thread_loop);
789 }
790
791 pw_thread_loop_unlock(pw->thread_loop);
792 return true;
793
794 fail:
795 if (pw->thread_loop) {
796 pw_thread_loop_stop(pw->thread_loop);
797 }
798 g_clear_pointer(&pw->context, pw_context_destroy);
799 g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy);
800 return false;
801 }
802
803 static void
804 audio_pw_finalize(Object *obj)
805 {
806 AudioPw *pw = AUDIO_PW(obj);
807
808 if (pw->thread_loop) {
809 pw_thread_loop_stop(pw->thread_loop);
810 }
811
812 if (pw->core) {
813 spa_hook_remove(&pw->core_listener);
814 spa_zero(pw->core_listener);
815 pw_core_disconnect(pw->core);
816 }
817
818 if (pw->context) {
819 pw_context_destroy(pw->context);
820 }
821 g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy);
822 }
823
824 static void audio_pw_class_init(ObjectClass *klass, const void *data)
825 {
826 AudioBackendClass *b = AUDIO_BACKEND_CLASS(klass);
827 AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
828
829 audio_pw_parent_class = AUDIO_BACKEND_CLASS(object_class_get_parent(klass));
830
831 b->realize = audio_pw_realize;
832 k->max_voices_out = INT_MAX;
833 k->max_voices_in = INT_MAX;
834 k->voice_size_out = sizeof(PWVoiceOut);
835 k->voice_size_in = sizeof(PWVoiceIn);
836
837 k->init_out = qpw_init_out;
838 k->fini_out = qpw_fini_out;
839 k->write = qpw_write;
840 k->buffer_get_free = qpw_buffer_get_free;
841 k->run_buffer_out = audio_generic_run_buffer_out;
842 k->enable_out = qpw_enable_out;
843 k->volume_out = qpw_volume_out;
844
845 k->init_in = qpw_init_in;
846 k->fini_in = qpw_fini_in;
847 k->read = qpw_read;
848 k->run_buffer_in = audio_generic_run_buffer_in;
849 k->enable_in = qpw_enable_in;
850 k->volume_in = qpw_volume_in;
851 }
852
853 static const TypeInfo audio_types[] = {
854 {
855 .name = TYPE_AUDIO_PW,
856 .parent = TYPE_AUDIO_MIXENG_BACKEND,
857 .instance_size = sizeof(AudioPw),
858 .class_init = audio_pw_class_init,
859 .instance_finalize = audio_pw_finalize,
860 },
861 };
862
863 DEFINE_TYPES(audio_types)
864 module_obj(TYPE_AUDIO_PW);