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
11 #include "qemu/osdep.h"
12 #include "qemu/module.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>
21 #include <pipewire/pipewire.h>
24 #define AUDIO_CAP "pipewire"
25 #define RINGBUFFER_SIZE (1u << 22)
26 #define RINGBUFFER_MASK (RINGBUFFER_SIZE - 1)
28 #include "audio_int.h"
30 typedef struct pwvolume
{
32 float values
[SPA_AUDIO_MAX_CHANNELS
];
35 typedef struct pwaudio
{
37 struct pw_thread_loop
*thread_loop
;
38 struct pw_context
*context
;
41 struct spa_hook core_listener
;
42 int last_seq
, pending_seq
, error
;
45 typedef struct PWVoice
{
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
];
59 typedef struct PWVoiceOut
{
64 typedef struct PWVoiceIn
{
69 #define PW_VOICE_IN(v) ((PWVoiceIn *)v)
70 #define PW_VOICE_OUT(v) ((PWVoiceOut *)v)
73 stream_destroy(void *data
)
75 PWVoice
*v
= (PWVoice
*) data
;
76 spa_hook_remove(&v
->stream_listener
);
80 /* output data processing function to read stuffs from the buffer */
82 playback_on_process(void *data
)
87 struct spa_buffer
*buf
;
88 uint32_t req
, index
, n_bytes
;
93 /* obtain a buffer to read from */
94 b
= pw_stream_dequeue_buffer(v
->stream
);
96 error_report("out of buffers: %s", strerror(errno
));
101 p
= buf
->datas
[0].data
;
105 /* calculate the total no of bytes to read data from buffer */
106 req
= b
->requested
* v
->frame_size
;
110 n_bytes
= SPA_MIN(req
, buf
->datas
[0].maxsize
);
112 /* get no of available bytes to read data from buffer */
113 avail
= spa_ringbuffer_get_read_index(&v
->ring
, &index
);
116 PWVoiceOut
*vo
= container_of(data
, PWVoiceOut
, v
);
117 audio_pcm_info_clear_buf(&vo
->hw
.info
, p
, n_bytes
/ v
->frame_size
);
119 if ((uint32_t) avail
< n_bytes
) {
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.
128 spa_ringbuffer_read_data(&v
->ring
,
129 v
->buffer
, RINGBUFFER_SIZE
,
130 index
& RINGBUFFER_MASK
, p
, n_bytes
);
133 spa_ringbuffer_read_update(&v
->ring
, index
);
136 buf
->datas
[0].chunk
->offset
= 0;
137 buf
->datas
[0].chunk
->stride
= v
->frame_size
;
138 buf
->datas
[0].chunk
->size
= n_bytes
;
140 /* queue the buffer for playback */
141 pw_stream_queue_buffer(v
->stream
, b
);
144 /* output data processing function to generate stuffs in the buffer */
146 capture_on_process(void *data
)
148 PWVoice
*v
= (PWVoice
*) data
;
151 struct spa_buffer
*buf
;
153 uint32_t index
, offs
, n_bytes
;
157 /* obtain a buffer */
158 b
= pw_stream_dequeue_buffer(v
->stream
);
160 error_report("out of buffers: %s", strerror(errno
));
164 /* Write data into buffer */
166 p
= buf
->datas
[0].data
;
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
);
173 filled
= spa_ringbuffer_get_write_index(&v
->ring
, &index
);
177 error_report("%p: underrun write:%u filled:%d", p
, index
, filled
);
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
);
184 spa_ringbuffer_write_data(&v
->ring
,
185 v
->buffer
, RINGBUFFER_SIZE
,
186 index
& RINGBUFFER_MASK
,
187 SPA_PTROFF(p
, offs
, void), n_bytes
);
189 spa_ringbuffer_write_update(&v
->ring
, index
);
191 /* queue the buffer for playback */
192 pw_stream_queue_buffer(v
->stream
, b
);
196 on_stream_state_changed(void *data
, enum pw_stream_state old
,
197 enum pw_stream_state state
, const char *error
)
199 PWVoice
*v
= (PWVoice
*) data
;
201 trace_pw_state_changed(pw_stream_get_node_id(v
->stream
),
202 pw_stream_state_as_string(state
));
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
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
220 qpw_read(HWVoiceIn
*hw
, void *data
, size_t len
)
222 PWVoiceIn
*pw
= (PWVoiceIn
*) hw
;
225 const char *error
= NULL
;
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 */
236 /* get no of available bytes to read data from buffer */
237 avail
= spa_ringbuffer_get_read_index(&v
->ring
, &index
);
239 trace_pw_read(avail
, index
, len
);
241 if (avail
< (int32_t) len
) {
245 spa_ringbuffer_read_data(&v
->ring
,
246 v
->buffer
, RINGBUFFER_SIZE
,
247 index
& RINGBUFFER_MASK
, data
, len
);
249 spa_ringbuffer_read_update(&v
->ring
, index
);
253 pw_thread_loop_unlock(c
->thread_loop
);
257 static size_t qpw_buffer_get_free(HWVoiceOut
*hw
)
259 PWVoiceOut
*pw
= (PWVoiceOut
*)hw
;
262 const char *error
= NULL
;
263 int32_t filled
, avail
;
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 */
273 filled
= spa_ringbuffer_get_write_index(&v
->ring
, &index
);
274 avail
= v
->highwater_mark
- filled
;
277 pw_thread_loop_unlock(c
->thread_loop
);
282 qpw_write(HWVoiceOut
*hw
, void *data
, size_t len
)
284 PWVoiceOut
*pw
= (PWVoiceOut
*) hw
;
287 const char *error
= NULL
;
288 int32_t filled
, avail
;
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 */
297 filled
= spa_ringbuffer_get_write_index(&v
->ring
, &index
);
298 avail
= v
->highwater_mark
- filled
;
300 trace_pw_write(filled
, avail
, index
, len
);
307 error_report("%p: underrun write:%u filled:%d", pw
, index
, filled
);
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
);
315 spa_ringbuffer_write_data(&v
->ring
,
316 v
->buffer
, RINGBUFFER_SIZE
,
317 index
& RINGBUFFER_MASK
, data
, len
);
319 spa_ringbuffer_write_update(&v
->ring
, index
);
322 pw_thread_loop_unlock(c
->thread_loop
);
327 audfmt_to_pw(AudioFormat fmt
, int endianness
)
332 case AUDIO_FORMAT_S8
:
333 format
= SPA_AUDIO_FORMAT_S8
;
335 case AUDIO_FORMAT_U8
:
336 format
= SPA_AUDIO_FORMAT_U8
;
338 case AUDIO_FORMAT_S16
:
339 format
= endianness
? SPA_AUDIO_FORMAT_S16_BE
: SPA_AUDIO_FORMAT_S16_LE
;
341 case AUDIO_FORMAT_U16
:
342 format
= endianness
? SPA_AUDIO_FORMAT_U16_BE
: SPA_AUDIO_FORMAT_U16_LE
;
344 case AUDIO_FORMAT_S32
:
345 format
= endianness
? SPA_AUDIO_FORMAT_S32_BE
: SPA_AUDIO_FORMAT_S32_LE
;
347 case AUDIO_FORMAT_U32
:
348 format
= endianness
? SPA_AUDIO_FORMAT_U32_BE
: SPA_AUDIO_FORMAT_U32_LE
;
350 case AUDIO_FORMAT_F32
:
351 format
= endianness
? SPA_AUDIO_FORMAT_F32_BE
: SPA_AUDIO_FORMAT_F32_LE
;
354 dolog("Internal logic error: Bad audio format %d\n", fmt
);
355 format
= SPA_AUDIO_FORMAT_U8
;
362 pw_to_audfmt(enum spa_audio_format fmt
, int *endianness
,
363 uint32_t *sample_size
)
366 case SPA_AUDIO_FORMAT_S8
:
368 return AUDIO_FORMAT_S8
;
369 case SPA_AUDIO_FORMAT_U8
:
371 return AUDIO_FORMAT_U8
;
372 case SPA_AUDIO_FORMAT_S16_BE
:
375 return AUDIO_FORMAT_S16
;
376 case SPA_AUDIO_FORMAT_S16_LE
:
379 return AUDIO_FORMAT_S16
;
380 case SPA_AUDIO_FORMAT_U16_BE
:
383 return AUDIO_FORMAT_U16
;
384 case SPA_AUDIO_FORMAT_U16_LE
:
387 return AUDIO_FORMAT_U16
;
388 case SPA_AUDIO_FORMAT_S32_BE
:
391 return AUDIO_FORMAT_S32
;
392 case SPA_AUDIO_FORMAT_S32_LE
:
395 return AUDIO_FORMAT_S32
;
396 case SPA_AUDIO_FORMAT_U32_BE
:
399 return AUDIO_FORMAT_U32
;
400 case SPA_AUDIO_FORMAT_U32_LE
:
403 return AUDIO_FORMAT_U32
;
404 case SPA_AUDIO_FORMAT_F32_BE
:
407 return AUDIO_FORMAT_F32
;
408 case SPA_AUDIO_FORMAT_F32_LE
:
411 return AUDIO_FORMAT_F32
;
414 dolog("Internal logic error: Bad spa_audio_format %d\n", fmt
);
415 return AUDIO_FORMAT_U8
;
420 create_stream(pwaudio
*c
, PWVoice
*v
, const char *stream_name
,
421 const char *name
, enum spa_direction dir
)
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
;
431 props
= pw_properties_new(NULL
, NULL
);
433 error_report("Failed to create PW properties: %s", g_strerror(errno
));
437 /* 75% of the timer period for faster updates */
438 buf_samples
= (uint64_t)v
->g
->dev
->timer_period
* v
->info
.rate
440 pw_properties_setf(props
, PW_KEY_NODE_LATENCY
, "%" PRIu64
"/%u",
441 buf_samples
, v
->info
.rate
);
443 trace_pw_period(buf_samples
, v
->info
.rate
);
445 pw_properties_set(props
, PW_KEY_TARGET_OBJECT
, name
);
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
));
453 if (dir
== SPA_DIRECTION_INPUT
) {
454 pw_stream_add_listener(v
->stream
,
455 &v
->stream_listener
, &capture_stream_events
, v
);
457 pw_stream_add_listener(v
->stream
,
458 &v
->stream_listener
, &playback_stream_events
, v
);
462 spa_pod_builder_init(&b
, buffer
, sizeof(buffer
));
463 params
[n_params
++] = spa_format_audio_raw_build(&b
,
464 SPA_PARAM_EnumFormat
,
467 /* connect the stream to a sink or source */
468 res
= pw_stream_connect(v
->stream
,
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
);
477 error_report("Failed to connect PW stream: %s", g_strerror(errno
));
478 pw_stream_destroy(v
->stream
);
486 qpw_stream_new(pwaudio
*c
, PWVoice
*v
, const char *stream_name
,
487 const char *name
, enum spa_direction dir
)
489 switch (v
->info
.channels
) {
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
;
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
;
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
;
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
;
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
;
527 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_FL
;
528 v
->info
.position
[1] = SPA_AUDIO_CHANNEL_FR
;
531 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_MONO
;
534 for (size_t i
= 0; i
< v
->info
.channels
; i
++) {
535 v
->info
.position
[i
] = SPA_AUDIO_CHANNEL_UNKNOWN
;
540 return create_stream(c
, v
, stream_name
, name
, dir
);
544 qpw_init_out(HWVoiceOut
*hw
, struct audsettings
*as
, void *drv_opaque
)
546 PWVoiceOut
*pw
= (PWVoiceOut
*) hw
;
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
;
554 pw_thread_loop_lock(c
->thread_loop
);
556 v
->info
.format
= audfmt_to_pw(as
->fmt
, as
->endianness
);
557 v
->info
.channels
= as
->nchannels
;
558 v
->info
.rate
= as
->freq
;
561 pw_to_audfmt(v
->info
.format
, &obt_as
.endianness
, &v
->frame_size
);
562 v
->frame_size
*= as
->nchannels
;
564 v
->req
= (uint64_t)c
->dev
->timer_period
* v
->info
.rate
565 * 1 / 2 / 1000000 * v
->frame_size
;
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
);
571 pw_thread_loop_unlock(c
->thread_loop
);
575 /* report the audio format we support */
576 audio_pcm_init_info(&hw
->info
, &obt_as
);
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
);
585 pw_thread_loop_unlock(c
->thread_loop
);
590 qpw_init_in(HWVoiceIn
*hw
, struct audsettings
*as
, void *drv_opaque
)
592 PWVoiceIn
*pw
= (PWVoiceIn
*) hw
;
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
;
600 pw_thread_loop_lock(c
->thread_loop
);
602 v
->info
.format
= audfmt_to_pw(as
->fmt
, as
->endianness
);
603 v
->info
.channels
= as
->nchannels
;
604 v
->info
.rate
= as
->freq
;
607 pw_to_audfmt(v
->info
.format
, &obt_as
.endianness
, &v
->frame_size
);
608 v
->frame_size
*= as
->nchannels
;
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
);
614 pw_thread_loop_unlock(c
->thread_loop
);
618 /* report the audio format we support */
619 audio_pcm_init_info(&hw
->info
, &obt_as
);
621 /* report the buffer size to qemu */
622 hw
->samples
= audio_buffer_frames(
623 qapi_AudiodevPipewirePerDirectionOptions_base(ppdo
), &obt_as
, 46440);
625 pw_thread_loop_unlock(c
->thread_loop
);
630 qpw_voice_fini(PWVoice
*v
)
637 pw_thread_loop_lock(c
->thread_loop
);
638 pw_stream_destroy(v
->stream
);
640 pw_thread_loop_unlock(c
->thread_loop
);
644 qpw_fini_out(HWVoiceOut
*hw
)
646 qpw_voice_fini(&PW_VOICE_OUT(hw
)->v
);
650 qpw_fini_in(HWVoiceIn
*hw
)
652 qpw_voice_fini(&PW_VOICE_IN(hw
)->v
);
656 qpw_voice_set_enabled(PWVoice
*v
, bool enable
)
659 pw_thread_loop_lock(c
->thread_loop
);
660 pw_stream_set_active(v
->stream
, enable
);
661 pw_thread_loop_unlock(c
->thread_loop
);
665 qpw_enable_out(HWVoiceOut
*hw
, bool enable
)
667 qpw_voice_set_enabled(&PW_VOICE_OUT(hw
)->v
, enable
);
671 qpw_enable_in(HWVoiceIn
*hw
, bool enable
)
673 qpw_voice_set_enabled(&PW_VOICE_IN(hw
)->v
, enable
);
677 qpw_voice_set_volume(PWVoice
*v
, Volume
*vol
)
682 pw_thread_loop_lock(c
->thread_loop
);
683 v
->volume
.channels
= vol
->channels
;
685 for (i
= 0; i
< vol
->channels
; ++i
) {
686 v
->volume
.values
[i
] = (float)vol
->vol
[i
] / 255;
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");
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
);
700 qpw_volume_out(HWVoiceOut
*hw
, Volume
*vol
)
702 qpw_voice_set_volume(&PW_VOICE_OUT(hw
)->v
, vol
);
706 qpw_volume_in(HWVoiceIn
*hw
, Volume
*vol
)
708 qpw_voice_set_volume(&PW_VOICE_IN(hw
)->v
, vol
);
711 static int wait_resync(pwaudio
*pw
)
714 pw
->pending_seq
= pw_core_sync(pw
->core
, PW_ID_CORE
, pw
->pending_seq
);
717 pw_thread_loop_wait(pw
->thread_loop
);
724 if (pw
->pending_seq
== pw
->last_seq
) {
732 on_core_error(void *data
, uint32_t id
, int seq
, int res
, const char *message
)
736 error_report("error id:%u seq:%d res:%d (%s): %s",
737 id
, seq
, res
, spa_strerror(res
), message
);
739 /* stop and exit the thread loop */
740 pw_thread_loop_signal(pw
->thread_loop
, FALSE
);
744 on_core_done(void *data
, uint32_t id
, int seq
)
747 assert(id
== PW_ID_CORE
);
749 if (pw
->pending_seq
== seq
) {
750 /* stop and exit the thread loop */
751 pw_thread_loop_signal(pw
->thread_loop
, FALSE
);
755 static const struct pw_core_events core_events
= {
756 PW_VERSION_CORE_EVENTS
,
757 .done
= on_core_done
,
758 .error
= on_core_error
,
762 qpw_audio_init(Audiodev
*dev
)
764 g_autofree pwaudio
*pw
= g_new0(pwaudio
, 1);
766 assert(dev
->driver
== AUDIODEV_DRIVER_PIPEWIRE
);
767 trace_pw_audio_init();
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
));
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
));
785 if (pw_thread_loop_start(pw
->thread_loop
) < 0) {
786 error_report("Could not start PipeWire loop: %s", g_strerror(errno
));
790 pw_thread_loop_lock(pw
->thread_loop
);
792 pw
->core
= pw_context_connect(pw
->context
, NULL
, 0);
793 if (pw
->core
== NULL
) {
794 pw_thread_loop_unlock(pw
->thread_loop
);
798 if (pw_core_add_listener(pw
->core
, &pw
->core_listener
,
799 &core_events
, pw
) < 0) {
800 pw_thread_loop_unlock(pw
->thread_loop
);
803 if (wait_resync(pw
) < 0) {
804 pw_thread_loop_unlock(pw
->thread_loop
);
807 pw_thread_loop_unlock(pw
->thread_loop
);
809 return g_steal_pointer(&pw
);
812 AUD_log(AUDIO_CAP
, "Failed to initialize PW context");
813 if (pw
->thread_loop
) {
814 pw_thread_loop_stop(pw
->thread_loop
);
816 g_clear_pointer(&pw
->context
, pw_context_destroy
);
817 g_clear_pointer(&pw
->thread_loop
, pw_thread_loop_destroy
);
822 qpw_audio_fini(void *opaque
)
824 pwaudio
*pw
= opaque
;
826 if (pw
->thread_loop
) {
827 pw_thread_loop_stop(pw
->thread_loop
);
831 spa_hook_remove(&pw
->core_listener
);
832 spa_zero(pw
->core_listener
);
833 pw_core_disconnect(pw
->core
);
837 pw_context_destroy(pw
->context
);
839 pw_thread_loop_destroy(pw
->thread_loop
);
844 static struct audio_pcm_ops qpw_pcm_ops
= {
845 .init_out
= qpw_init_out
,
846 .fini_out
= qpw_fini_out
,
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
,
854 .init_in
= qpw_init_in
,
855 .fini_in
= qpw_fini_in
,
857 .run_buffer_in
= audio_generic_run_buffer_in
,
858 .enable_in
= qpw_enable_in
861 static struct audio_driver pw_audio_driver
= {
863 .descr
= "http://www.pipewire.org/",
864 .init
= qpw_audio_init
,
865 .fini
= qpw_audio_fini
,
866 .pcm_ops
= &qpw_pcm_ops
,
868 .max_voices_out
= INT_MAX
,
869 .max_voices_in
= INT_MAX
,
870 .voice_size_out
= sizeof(PWVoiceOut
),
871 .voice_size_in
= sizeof(PWVoiceIn
),
875 register_audio_pw(void)
877 audio_driver_register(&pw_audio_driver
);
880 type_init(register_audio_pw
);