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
{
70 stream_destroy(void *data
)
72 PWVoice
*v
= (PWVoice
*) data
;
73 spa_hook_remove(&v
->stream_listener
);
77 /* output data processing function to read stuffs from the buffer */
79 playback_on_process(void *data
)
84 struct spa_buffer
*buf
;
85 uint32_t req
, index
, n_bytes
;
90 /* obtain a buffer to read from */
91 b
= pw_stream_dequeue_buffer(v
->stream
);
93 error_report("out of buffers: %s", strerror(errno
));
98 p
= buf
->datas
[0].data
;
102 /* calculate the total no of bytes to read data from buffer */
103 req
= b
->requested
* v
->frame_size
;
107 n_bytes
= SPA_MIN(req
, buf
->datas
[0].maxsize
);
109 /* get no of available bytes to read data from buffer */
110 avail
= spa_ringbuffer_get_read_index(&v
->ring
, &index
);
113 PWVoiceOut
*vo
= container_of(data
, PWVoiceOut
, v
);
114 audio_pcm_info_clear_buf(&vo
->hw
.info
, p
, n_bytes
/ v
->frame_size
);
116 if ((uint32_t) avail
< n_bytes
) {
118 * PipeWire immediately calls this callback again if we provide
119 * less than n_bytes. Then audio_pcm_info_clear_buf() fills the
120 * rest of the buffer with silence.
125 spa_ringbuffer_read_data(&v
->ring
,
126 v
->buffer
, RINGBUFFER_SIZE
,
127 index
& RINGBUFFER_MASK
, p
, n_bytes
);
130 spa_ringbuffer_read_update(&v
->ring
, index
);
133 buf
->datas
[0].chunk
->offset
= 0;
134 buf
->datas
[0].chunk
->stride
= v
->frame_size
;
135 buf
->datas
[0].chunk
->size
= n_bytes
;
137 /* queue the buffer for playback */
138 pw_stream_queue_buffer(v
->stream
, b
);
141 /* output data processing function to generate stuffs in the buffer */
143 capture_on_process(void *data
)
145 PWVoice
*v
= (PWVoice
*) data
;
148 struct spa_buffer
*buf
;
150 uint32_t index
, offs
, n_bytes
;
154 /* obtain a buffer */
155 b
= pw_stream_dequeue_buffer(v
->stream
);
157 error_report("out of buffers: %s", strerror(errno
));
161 /* Write data into buffer */
163 p
= buf
->datas
[0].data
;
167 offs
= SPA_MIN(buf
->datas
[0].chunk
->offset
, buf
->datas
[0].maxsize
);
168 n_bytes
= SPA_MIN(buf
->datas
[0].chunk
->size
, buf
->datas
[0].maxsize
- offs
);
170 filled
= spa_ringbuffer_get_write_index(&v
->ring
, &index
);
174 error_report("%p: underrun write:%u filled:%d", p
, index
, filled
);
176 if ((uint32_t) filled
+ n_bytes
> RINGBUFFER_SIZE
) {
177 error_report("%p: overrun write:%u filled:%d + size:%u > max:%u",
178 p
, index
, filled
, n_bytes
, RINGBUFFER_SIZE
);
181 spa_ringbuffer_write_data(&v
->ring
,
182 v
->buffer
, RINGBUFFER_SIZE
,
183 index
& RINGBUFFER_MASK
,
184 SPA_PTROFF(p
, offs
, void), n_bytes
);
186 spa_ringbuffer_write_update(&v
->ring
, index
);
188 /* queue the buffer for playback */
189 pw_stream_queue_buffer(v
->stream
, b
);
193 on_stream_state_changed(void *data
, enum pw_stream_state old
,
194 enum pw_stream_state state
, const char *error
)
196 PWVoice
*v
= (PWVoice
*) data
;
198 trace_pw_state_changed(pw_stream_get_node_id(v
->stream
),
199 pw_stream_state_as_string(state
));
202 case PW_STREAM_STATE_ERROR
:
203 case PW_STREAM_STATE_UNCONNECTED
:
205 case PW_STREAM_STATE_PAUSED
:
206 case PW_STREAM_STATE_CONNECTING
:
207 case PW_STREAM_STATE_STREAMING
:
212 static const struct pw_stream_events capture_stream_events
= {
213 PW_VERSION_STREAM_EVENTS
,
214 .destroy
= stream_destroy
,
215 .state_changed
= on_stream_state_changed
,
216 .process
= capture_on_process
219 static const struct pw_stream_events playback_stream_events
= {
220 PW_VERSION_STREAM_EVENTS
,
221 .destroy
= stream_destroy
,
222 .state_changed
= on_stream_state_changed
,
223 .process
= playback_on_process
227 qpw_read(HWVoiceIn
*hw
, void *data
, size_t len
)
229 PWVoiceIn
*pw
= (PWVoiceIn
*) hw
;
232 const char *error
= NULL
;
237 pw_thread_loop_lock(c
->thread_loop
);
238 if (pw_stream_get_state(v
->stream
, &error
) != PW_STREAM_STATE_STREAMING
) {
239 /* wait for stream to become ready */
243 /* get no of available bytes to read data from buffer */
244 avail
= spa_ringbuffer_get_read_index(&v
->ring
, &index
);
246 trace_pw_read(avail
, index
, len
);
248 if (avail
< (int32_t) len
) {
252 spa_ringbuffer_read_data(&v
->ring
,
253 v
->buffer
, RINGBUFFER_SIZE
,
254 index
& RINGBUFFER_MASK
, data
, len
);
256 spa_ringbuffer_read_update(&v
->ring
, index
);
260 pw_thread_loop_unlock(c
->thread_loop
);
264 static size_t qpw_buffer_get_free(HWVoiceOut
*hw
)
266 PWVoiceOut
*pw
= (PWVoiceOut
*)hw
;
269 const char *error
= NULL
;
270 int32_t filled
, avail
;
273 pw_thread_loop_lock(c
->thread_loop
);
274 if (pw_stream_get_state(v
->stream
, &error
) != PW_STREAM_STATE_STREAMING
) {
275 /* wait for stream to become ready */
280 filled
= spa_ringbuffer_get_write_index(&v
->ring
, &index
);
281 avail
= v
->highwater_mark
- filled
;
284 pw_thread_loop_unlock(c
->thread_loop
);
289 qpw_write(HWVoiceOut
*hw
, void *data
, size_t len
)
291 PWVoiceOut
*pw
= (PWVoiceOut
*) hw
;
294 const char *error
= NULL
;
295 int32_t filled
, avail
;
298 pw_thread_loop_lock(c
->thread_loop
);
299 if (pw_stream_get_state(v
->stream
, &error
) != PW_STREAM_STATE_STREAMING
) {
300 /* wait for stream to become ready */
304 filled
= spa_ringbuffer_get_write_index(&v
->ring
, &index
);
305 avail
= v
->highwater_mark
- filled
;
307 trace_pw_write(filled
, avail
, index
, len
);
314 error_report("%p: underrun write:%u filled:%d", pw
, index
, filled
);
316 if ((uint32_t) filled
+ len
> RINGBUFFER_SIZE
) {
317 error_report("%p: overrun write:%u filled:%d + size:%zu > max:%u",
318 pw
, index
, filled
, len
, RINGBUFFER_SIZE
);
322 spa_ringbuffer_write_data(&v
->ring
,
323 v
->buffer
, RINGBUFFER_SIZE
,
324 index
& RINGBUFFER_MASK
, data
, len
);
326 spa_ringbuffer_write_update(&v
->ring
, index
);
329 pw_thread_loop_unlock(c
->thread_loop
);
334 audfmt_to_pw(AudioFormat fmt
, int endianness
)
339 case AUDIO_FORMAT_S8
:
340 format
= SPA_AUDIO_FORMAT_S8
;
342 case AUDIO_FORMAT_U8
:
343 format
= SPA_AUDIO_FORMAT_U8
;
345 case AUDIO_FORMAT_S16
:
346 format
= endianness
? SPA_AUDIO_FORMAT_S16_BE
: SPA_AUDIO_FORMAT_S16_LE
;
348 case AUDIO_FORMAT_U16
:
349 format
= endianness
? SPA_AUDIO_FORMAT_U16_BE
: SPA_AUDIO_FORMAT_U16_LE
;
351 case AUDIO_FORMAT_S32
:
352 format
= endianness
? SPA_AUDIO_FORMAT_S32_BE
: SPA_AUDIO_FORMAT_S32_LE
;
354 case AUDIO_FORMAT_U32
:
355 format
= endianness
? SPA_AUDIO_FORMAT_U32_BE
: SPA_AUDIO_FORMAT_U32_LE
;
357 case AUDIO_FORMAT_F32
:
358 format
= endianness
? SPA_AUDIO_FORMAT_F32_BE
: SPA_AUDIO_FORMAT_F32_LE
;
361 dolog("Internal logic error: Bad audio format %d\n", fmt
);
362 format
= SPA_AUDIO_FORMAT_U8
;
369 pw_to_audfmt(enum spa_audio_format fmt
, int *endianness
,
370 uint32_t *sample_size
)
373 case SPA_AUDIO_FORMAT_S8
:
375 return AUDIO_FORMAT_S8
;
376 case SPA_AUDIO_FORMAT_U8
:
378 return AUDIO_FORMAT_U8
;
379 case SPA_AUDIO_FORMAT_S16_BE
:
382 return AUDIO_FORMAT_S16
;
383 case SPA_AUDIO_FORMAT_S16_LE
:
386 return AUDIO_FORMAT_S16
;
387 case SPA_AUDIO_FORMAT_U16_BE
:
390 return AUDIO_FORMAT_U16
;
391 case SPA_AUDIO_FORMAT_U16_LE
:
394 return AUDIO_FORMAT_U16
;
395 case SPA_AUDIO_FORMAT_S32_BE
:
398 return AUDIO_FORMAT_S32
;
399 case SPA_AUDIO_FORMAT_S32_LE
:
402 return AUDIO_FORMAT_S32
;
403 case SPA_AUDIO_FORMAT_U32_BE
:
406 return AUDIO_FORMAT_U32
;
407 case SPA_AUDIO_FORMAT_U32_LE
:
410 return AUDIO_FORMAT_U32
;
411 case SPA_AUDIO_FORMAT_F32_BE
:
414 return AUDIO_FORMAT_F32
;
415 case SPA_AUDIO_FORMAT_F32_LE
:
418 return AUDIO_FORMAT_F32
;
421 dolog("Internal logic error: Bad spa_audio_format %d\n", fmt
);
422 return AUDIO_FORMAT_U8
;
427 create_stream(pwaudio
*c
, PWVoice
*v
, const char *stream_name
,
428 const char *name
, enum spa_direction dir
)
432 const struct spa_pod
*params
[2];
433 uint8_t buffer
[1024];
434 struct spa_pod_builder b
;
435 uint64_t buf_samples
;
436 struct pw_properties
*props
;
438 props
= pw_properties_new(NULL
, NULL
);
440 /* 75% of the timer period for faster updates */
441 buf_samples
= (uint64_t)v
->g
->dev
->timer_period
* v
->info
.rate
443 pw_properties_setf(props
, PW_KEY_NODE_LATENCY
, "%" PRIu64
"/%u",
444 buf_samples
, v
->info
.rate
);
446 trace_pw_period(buf_samples
, v
->info
.rate
);
448 pw_properties_set(props
, PW_KEY_TARGET_OBJECT
, name
);
450 v
->stream
= pw_stream_new(c
->core
, stream_name
, props
);
452 if (v
->stream
== NULL
) {
456 if (dir
== SPA_DIRECTION_INPUT
) {
457 pw_stream_add_listener(v
->stream
,
458 &v
->stream_listener
, &capture_stream_events
, v
);
460 pw_stream_add_listener(v
->stream
,
461 &v
->stream_listener
, &playback_stream_events
, v
);
465 spa_pod_builder_init(&b
, buffer
, sizeof(buffer
));
466 params
[n_params
++] = spa_format_audio_raw_build(&b
,
467 SPA_PARAM_EnumFormat
,
470 /* connect the stream to a sink or source */
471 res
= pw_stream_connect(v
->stream
,
473 SPA_DIRECTION_INPUT
? PW_DIRECTION_INPUT
:
474 PW_DIRECTION_OUTPUT
, PW_ID_ANY
,
475 PW_STREAM_FLAG_AUTOCONNECT
|
476 PW_STREAM_FLAG_INACTIVE
|
477 PW_STREAM_FLAG_MAP_BUFFERS
|
478 PW_STREAM_FLAG_RT_PROCESS
, params
, n_params
);
480 pw_stream_destroy(v
->stream
);
488 qpw_stream_new(pwaudio
*c
, PWVoice
*v
, const char *stream_name
,
489 const char *name
, enum spa_direction dir
)
493 switch (v
->info
.channels
) {
495 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_FL
;
496 v
->info
.position
[1] = SPA_AUDIO_CHANNEL_FR
;
497 v
->info
.position
[2] = SPA_AUDIO_CHANNEL_FC
;
498 v
->info
.position
[3] = SPA_AUDIO_CHANNEL_LFE
;
499 v
->info
.position
[4] = SPA_AUDIO_CHANNEL_RL
;
500 v
->info
.position
[5] = SPA_AUDIO_CHANNEL_RR
;
501 v
->info
.position
[6] = SPA_AUDIO_CHANNEL_SL
;
502 v
->info
.position
[7] = SPA_AUDIO_CHANNEL_SR
;
505 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_FL
;
506 v
->info
.position
[1] = SPA_AUDIO_CHANNEL_FR
;
507 v
->info
.position
[2] = SPA_AUDIO_CHANNEL_FC
;
508 v
->info
.position
[3] = SPA_AUDIO_CHANNEL_LFE
;
509 v
->info
.position
[4] = SPA_AUDIO_CHANNEL_RL
;
510 v
->info
.position
[5] = SPA_AUDIO_CHANNEL_RR
;
513 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_FL
;
514 v
->info
.position
[1] = SPA_AUDIO_CHANNEL_FR
;
515 v
->info
.position
[2] = SPA_AUDIO_CHANNEL_FC
;
516 v
->info
.position
[3] = SPA_AUDIO_CHANNEL_LFE
;
517 v
->info
.position
[4] = SPA_AUDIO_CHANNEL_RC
;
520 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_FL
;
521 v
->info
.position
[1] = SPA_AUDIO_CHANNEL_FR
;
522 v
->info
.position
[2] = SPA_AUDIO_CHANNEL_FC
;
523 v
->info
.position
[3] = SPA_AUDIO_CHANNEL_RC
;
526 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_FL
;
527 v
->info
.position
[1] = SPA_AUDIO_CHANNEL_FR
;
528 v
->info
.position
[2] = SPA_AUDIO_CHANNEL_LFE
;
531 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_FL
;
532 v
->info
.position
[1] = SPA_AUDIO_CHANNEL_FR
;
535 v
->info
.position
[0] = SPA_AUDIO_CHANNEL_MONO
;
538 for (size_t i
= 0; i
< v
->info
.channels
; i
++) {
539 v
->info
.position
[i
] = SPA_AUDIO_CHANNEL_UNKNOWN
;
544 /* create a new unconnected pwstream */
545 r
= create_stream(c
, v
, stream_name
, name
, dir
);
547 AUD_log(AUDIO_CAP
, "Failed to create stream.");
555 qpw_init_out(HWVoiceOut
*hw
, struct audsettings
*as
, void *drv_opaque
)
557 PWVoiceOut
*pw
= (PWVoiceOut
*) hw
;
559 struct audsettings obt_as
= *as
;
560 pwaudio
*c
= v
->g
= drv_opaque
;
561 AudiodevPipewireOptions
*popts
= &c
->dev
->u
.pipewire
;
562 AudiodevPipewirePerDirectionOptions
*ppdo
= popts
->out
;
565 pw_thread_loop_lock(c
->thread_loop
);
567 v
->info
.format
= audfmt_to_pw(as
->fmt
, as
->endianness
);
568 v
->info
.channels
= as
->nchannels
;
569 v
->info
.rate
= as
->freq
;
572 pw_to_audfmt(v
->info
.format
, &obt_as
.endianness
, &v
->frame_size
);
573 v
->frame_size
*= as
->nchannels
;
575 v
->req
= (uint64_t)c
->dev
->timer_period
* v
->info
.rate
576 * 1 / 2 / 1000000 * v
->frame_size
;
578 /* call the function that creates a new stream for playback */
579 r
= qpw_stream_new(c
, v
, ppdo
->stream_name
? : c
->dev
->id
,
580 ppdo
->name
, SPA_DIRECTION_OUTPUT
);
582 error_report("qpw_stream_new for playback failed");
583 pw_thread_loop_unlock(c
->thread_loop
);
587 /* report the audio format we support */
588 audio_pcm_init_info(&hw
->info
, &obt_as
);
590 /* report the buffer size to qemu */
591 hw
->samples
= audio_buffer_frames(
592 qapi_AudiodevPipewirePerDirectionOptions_base(ppdo
), &obt_as
, 46440);
593 v
->highwater_mark
= MIN(RINGBUFFER_SIZE
,
594 (ppdo
->has_latency
? ppdo
->latency
: 46440)
595 * (uint64_t)v
->info
.rate
/ 1000000 * v
->frame_size
);
597 pw_thread_loop_unlock(c
->thread_loop
);
602 qpw_init_in(HWVoiceIn
*hw
, struct audsettings
*as
, void *drv_opaque
)
604 PWVoiceIn
*pw
= (PWVoiceIn
*) hw
;
606 struct audsettings obt_as
= *as
;
607 pwaudio
*c
= v
->g
= drv_opaque
;
608 AudiodevPipewireOptions
*popts
= &c
->dev
->u
.pipewire
;
609 AudiodevPipewirePerDirectionOptions
*ppdo
= popts
->in
;
612 pw_thread_loop_lock(c
->thread_loop
);
614 v
->info
.format
= audfmt_to_pw(as
->fmt
, as
->endianness
);
615 v
->info
.channels
= as
->nchannels
;
616 v
->info
.rate
= as
->freq
;
619 pw_to_audfmt(v
->info
.format
, &obt_as
.endianness
, &v
->frame_size
);
620 v
->frame_size
*= as
->nchannels
;
622 /* call the function that creates a new stream for recording */
623 r
= qpw_stream_new(c
, v
, ppdo
->stream_name
? : c
->dev
->id
,
624 ppdo
->name
, SPA_DIRECTION_INPUT
);
626 error_report("qpw_stream_new for recording failed");
627 pw_thread_loop_unlock(c
->thread_loop
);
631 /* report the audio format we support */
632 audio_pcm_init_info(&hw
->info
, &obt_as
);
634 /* report the buffer size to qemu */
635 hw
->samples
= audio_buffer_frames(
636 qapi_AudiodevPipewirePerDirectionOptions_base(ppdo
), &obt_as
, 46440);
638 pw_thread_loop_unlock(c
->thread_loop
);
643 qpw_fini_out(HWVoiceOut
*hw
)
645 PWVoiceOut
*pw
= (PWVoiceOut
*) hw
;
650 pw_thread_loop_lock(c
->thread_loop
);
651 pw_stream_destroy(v
->stream
);
653 pw_thread_loop_unlock(c
->thread_loop
);
658 qpw_fini_in(HWVoiceIn
*hw
)
660 PWVoiceIn
*pw
= (PWVoiceIn
*) hw
;
665 pw_thread_loop_lock(c
->thread_loop
);
666 pw_stream_destroy(v
->stream
);
668 pw_thread_loop_unlock(c
->thread_loop
);
673 qpw_enable_out(HWVoiceOut
*hw
, bool enable
)
675 PWVoiceOut
*po
= (PWVoiceOut
*) hw
;
678 pw_thread_loop_lock(c
->thread_loop
);
679 pw_stream_set_active(v
->stream
, enable
);
680 pw_thread_loop_unlock(c
->thread_loop
);
684 qpw_enable_in(HWVoiceIn
*hw
, bool enable
)
686 PWVoiceIn
*pi
= (PWVoiceIn
*) hw
;
689 pw_thread_loop_lock(c
->thread_loop
);
690 pw_stream_set_active(v
->stream
, enable
);
691 pw_thread_loop_unlock(c
->thread_loop
);
695 qpw_volume_out(HWVoiceOut
*hw
, Volume
*vol
)
697 PWVoiceOut
*pw
= (PWVoiceOut
*) hw
;
702 pw_thread_loop_lock(c
->thread_loop
);
703 v
->volume
.channels
= vol
->channels
;
705 for (i
= 0; i
< vol
->channels
; ++i
) {
706 v
->volume
.values
[i
] = (float)vol
->vol
[i
] / 255;
709 ret
= pw_stream_set_control(v
->stream
,
710 SPA_PROP_channelVolumes
, v
->volume
.channels
, v
->volume
.values
, 0);
711 trace_pw_vol(ret
== 0 ? "success" : "failed");
713 v
->muted
= vol
->mute
;
714 float val
= v
->muted
? 1.f
: 0.f
;
715 ret
= pw_stream_set_control(v
->stream
, SPA_PROP_mute
, 1, &val
, 0);
716 pw_thread_loop_unlock(c
->thread_loop
);
720 qpw_volume_in(HWVoiceIn
*hw
, Volume
*vol
)
722 PWVoiceIn
*pw
= (PWVoiceIn
*) hw
;
727 pw_thread_loop_lock(c
->thread_loop
);
728 v
->volume
.channels
= vol
->channels
;
730 for (i
= 0; i
< vol
->channels
; ++i
) {
731 v
->volume
.values
[i
] = (float)vol
->vol
[i
] / 255;
734 ret
= pw_stream_set_control(v
->stream
,
735 SPA_PROP_channelVolumes
, v
->volume
.channels
, v
->volume
.values
, 0);
736 trace_pw_vol(ret
== 0 ? "success" : "failed");
738 v
->muted
= vol
->mute
;
739 float val
= v
->muted
? 1.f
: 0.f
;
740 ret
= pw_stream_set_control(v
->stream
, SPA_PROP_mute
, 1, &val
, 0);
741 pw_thread_loop_unlock(c
->thread_loop
);
744 static int wait_resync(pwaudio
*pw
)
747 pw
->pending_seq
= pw_core_sync(pw
->core
, PW_ID_CORE
, pw
->pending_seq
);
750 pw_thread_loop_wait(pw
->thread_loop
);
757 if (pw
->pending_seq
== pw
->last_seq
) {
764 on_core_error(void *data
, uint32_t id
, int seq
, int res
, const char *message
)
768 error_report("error id:%u seq:%d res:%d (%s): %s",
769 id
, seq
, res
, spa_strerror(res
), message
);
771 /* stop and exit the thread loop */
772 pw_thread_loop_signal(pw
->thread_loop
, FALSE
);
776 on_core_done(void *data
, uint32_t id
, int seq
)
779 assert(id
== PW_ID_CORE
);
781 if (pw
->pending_seq
== seq
) {
782 /* stop and exit the thread loop */
783 pw_thread_loop_signal(pw
->thread_loop
, FALSE
);
787 static const struct pw_core_events core_events
= {
788 PW_VERSION_CORE_EVENTS
,
789 .done
= on_core_done
,
790 .error
= on_core_error
,
794 qpw_audio_init(Audiodev
*dev
)
796 g_autofree pwaudio
*pw
= g_new0(pwaudio
, 1);
799 trace_pw_audio_init();
800 assert(dev
->driver
== AUDIODEV_DRIVER_PIPEWIRE
);
803 pw
->thread_loop
= pw_thread_loop_new("Pipewire thread loop", NULL
);
804 if (pw
->thread_loop
== NULL
) {
805 error_report("Could not create Pipewire loop");
810 pw_context_new(pw_thread_loop_get_loop(pw
->thread_loop
), NULL
, 0);
811 if (pw
->context
== NULL
) {
812 error_report("Could not create Pipewire context");
816 if (pw_thread_loop_start(pw
->thread_loop
) < 0) {
817 error_report("Could not start Pipewire loop");
821 pw_thread_loop_lock(pw
->thread_loop
);
823 pw
->core
= pw_context_connect(pw
->context
, NULL
, 0);
824 if (pw
->core
== NULL
) {
825 pw_thread_loop_unlock(pw
->thread_loop
);
829 if (pw_core_add_listener(pw
->core
, &pw
->core_listener
,
830 &core_events
, pw
) < 0) {
831 pw_thread_loop_unlock(pw
->thread_loop
);
834 if (wait_resync(pw
) < 0) {
835 pw_thread_loop_unlock(pw
->thread_loop
);
838 pw_thread_loop_unlock(pw
->thread_loop
);
840 return g_steal_pointer(&pw
);
843 AUD_log(AUDIO_CAP
, "Failed to initialize PW context");
844 if (pw
->thread_loop
) {
845 pw_thread_loop_stop(pw
->thread_loop
);
848 g_clear_pointer(&pw
->context
, pw_context_destroy
);
850 if (pw
->thread_loop
) {
851 g_clear_pointer(&pw
->thread_loop
, pw_thread_loop_destroy
);
857 qpw_audio_fini(void *opaque
)
859 pwaudio
*pw
= opaque
;
861 if (pw
->thread_loop
) {
862 pw_thread_loop_stop(pw
->thread_loop
);
866 spa_hook_remove(&pw
->core_listener
);
867 spa_zero(pw
->core_listener
);
868 pw_core_disconnect(pw
->core
);
872 pw_context_destroy(pw
->context
);
874 pw_thread_loop_destroy(pw
->thread_loop
);
879 static struct audio_pcm_ops qpw_pcm_ops
= {
880 .init_out
= qpw_init_out
,
881 .fini_out
= qpw_fini_out
,
883 .buffer_get_free
= qpw_buffer_get_free
,
884 .run_buffer_out
= audio_generic_run_buffer_out
,
885 .enable_out
= qpw_enable_out
,
886 .volume_out
= qpw_volume_out
,
887 .volume_in
= qpw_volume_in
,
889 .init_in
= qpw_init_in
,
890 .fini_in
= qpw_fini_in
,
892 .run_buffer_in
= audio_generic_run_buffer_in
,
893 .enable_in
= qpw_enable_in
896 static struct audio_driver pw_audio_driver
= {
898 .descr
= "http://www.pipewire.org/",
899 .init
= qpw_audio_init
,
900 .fini
= qpw_audio_fini
,
901 .pcm_ops
= &qpw_pcm_ops
,
903 .max_voices_out
= INT_MAX
,
904 .max_voices_in
= INT_MAX
,
905 .voice_size_out
= sizeof(PWVoiceOut
),
906 .voice_size_in
= sizeof(PWVoiceIn
),
910 register_audio_pw(void)
912 audio_driver_register(&pw_audio_driver
);
915 type_init(register_audio_pw
);