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