3 #include "qemu/osdep.h"
4 #include "qemu/module.h"
6 #include "qapi/opts-visitor.h"
8 #include <pulse/pulseaudio.h>
10 #define AUDIO_CAP "pulseaudio"
11 #include "audio_int.h"
13 typedef struct PAConnection
{
16 QTAILQ_ENTRY(PAConnection
) list
;
18 pa_threaded_mainloop
*mainloop
;
22 static QTAILQ_HEAD(PAConnectionHead
, PAConnection
) pa_conns
=
23 QTAILQ_HEAD_INITIALIZER(pa_conns
);
40 const void *read_data
;
46 static void qpa_conn_fini(PAConnection
*c
);
48 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err
, const char *fmt
, ...)
53 AUD_vlog (AUDIO_CAP
, fmt
, ap
);
56 AUD_log (AUDIO_CAP
, "Reason: %s\n", pa_strerror (err
));
59 #ifndef PA_CONTEXT_IS_GOOD
60 static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x
)
63 x
== PA_CONTEXT_CONNECTING
||
64 x
== PA_CONTEXT_AUTHORIZING
||
65 x
== PA_CONTEXT_SETTING_NAME
||
66 x
== PA_CONTEXT_READY
;
70 #ifndef PA_STREAM_IS_GOOD
71 static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x
)
74 x
== PA_STREAM_CREATING
||
79 #define CHECK_SUCCESS_GOTO(c, expression, label, msg) \
81 if (!(expression)) { \
82 qpa_logerr(pa_context_errno((c)->context), msg); \
87 #define CHECK_DEAD_GOTO(c, stream, label, msg) \
89 if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \
90 !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \
91 if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \
92 ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \
93 qpa_logerr(pa_context_errno((c)->context), msg); \
95 qpa_logerr(PA_ERR_BADSTATE, msg); \
101 static size_t qpa_read(HWVoiceIn
*hw
, void *data
, size_t length
)
103 PAVoiceIn
*p
= (PAVoiceIn
*) hw
;
104 PAConnection
*c
= p
->g
->conn
;
108 pa_threaded_mainloop_lock(c
->mainloop
);
110 CHECK_DEAD_GOTO(c
, p
->stream
, unlock_and_fail
,
111 "pa_threaded_mainloop_lock failed\n");
113 if (!p
->read_length
) {
114 r
= pa_stream_peek(p
->stream
, &p
->read_data
, &p
->read_length
);
115 CHECK_SUCCESS_GOTO(c
, r
== 0, unlock_and_fail
,
116 "pa_stream_peek failed\n");
119 l
= MIN(p
->read_length
, length
);
120 memcpy(data
, p
->read_data
, l
);
125 if (!p
->read_length
) {
126 r
= pa_stream_drop(p
->stream
);
127 CHECK_SUCCESS_GOTO(c
, r
== 0, unlock_and_fail
,
128 "pa_stream_drop failed\n");
131 pa_threaded_mainloop_unlock(c
->mainloop
);
135 pa_threaded_mainloop_unlock(c
->mainloop
);
139 static size_t qpa_write(HWVoiceOut
*hw
, void *data
, size_t length
)
141 PAVoiceOut
*p
= (PAVoiceOut
*) hw
;
142 PAConnection
*c
= p
->g
->conn
;
146 pa_threaded_mainloop_lock(c
->mainloop
);
148 CHECK_DEAD_GOTO(c
, p
->stream
, unlock_and_fail
,
149 "pa_threaded_mainloop_lock failed\n");
151 l
= pa_stream_writable_size(p
->stream
);
153 CHECK_SUCCESS_GOTO(c
, l
!= (size_t) -1, unlock_and_fail
,
154 "pa_stream_writable_size failed\n");
160 r
= pa_stream_write(p
->stream
, data
, l
, NULL
, 0LL, PA_SEEK_RELATIVE
);
161 CHECK_SUCCESS_GOTO(c
, r
>= 0, unlock_and_fail
, "pa_stream_write failed\n");
163 pa_threaded_mainloop_unlock(c
->mainloop
);
167 pa_threaded_mainloop_unlock(c
->mainloop
);
171 static pa_sample_format_t
audfmt_to_pa (AudioFormat afmt
, int endianness
)
176 case AUDIO_FORMAT_S8
:
177 case AUDIO_FORMAT_U8
:
178 format
= PA_SAMPLE_U8
;
180 case AUDIO_FORMAT_S16
:
181 case AUDIO_FORMAT_U16
:
182 format
= endianness
? PA_SAMPLE_S16BE
: PA_SAMPLE_S16LE
;
184 case AUDIO_FORMAT_S32
:
185 case AUDIO_FORMAT_U32
:
186 format
= endianness
? PA_SAMPLE_S32BE
: PA_SAMPLE_S32LE
;
189 dolog ("Internal logic error: Bad audio format %d\n", afmt
);
190 format
= PA_SAMPLE_U8
;
196 static AudioFormat
pa_to_audfmt (pa_sample_format_t fmt
, int *endianness
)
200 return AUDIO_FORMAT_U8
;
201 case PA_SAMPLE_S16BE
:
203 return AUDIO_FORMAT_S16
;
204 case PA_SAMPLE_S16LE
:
206 return AUDIO_FORMAT_S16
;
207 case PA_SAMPLE_S32BE
:
209 return AUDIO_FORMAT_S32
;
210 case PA_SAMPLE_S32LE
:
212 return AUDIO_FORMAT_S32
;
214 dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt
);
215 return AUDIO_FORMAT_U8
;
219 static void context_state_cb (pa_context
*c
, void *userdata
)
221 PAConnection
*conn
= userdata
;
223 switch (pa_context_get_state(c
)) {
224 case PA_CONTEXT_READY
:
225 case PA_CONTEXT_TERMINATED
:
226 case PA_CONTEXT_FAILED
:
227 pa_threaded_mainloop_signal(conn
->mainloop
, 0);
230 case PA_CONTEXT_UNCONNECTED
:
231 case PA_CONTEXT_CONNECTING
:
232 case PA_CONTEXT_AUTHORIZING
:
233 case PA_CONTEXT_SETTING_NAME
:
238 static void stream_state_cb (pa_stream
*s
, void * userdata
)
240 PAConnection
*c
= userdata
;
242 switch (pa_stream_get_state (s
)) {
244 case PA_STREAM_READY
:
245 case PA_STREAM_FAILED
:
246 case PA_STREAM_TERMINATED
:
247 pa_threaded_mainloop_signal(c
->mainloop
, 0);
250 case PA_STREAM_UNCONNECTED
:
251 case PA_STREAM_CREATING
:
256 static pa_stream
*qpa_simple_new (
259 pa_stream_direction_t dir
,
261 const pa_sample_spec
*ss
,
262 const pa_channel_map
*map
,
263 const pa_buffer_attr
*attr
,
268 pa_stream_flags_t flags
;
270 pa_threaded_mainloop_lock(c
->mainloop
);
272 stream
= pa_stream_new(c
->context
, name
, ss
, map
);
277 pa_stream_set_state_callback(stream
, stream_state_cb
, c
);
280 PA_STREAM_INTERPOLATE_TIMING
281 | PA_STREAM_AUTO_TIMING_UPDATE
282 | PA_STREAM_EARLY_REQUESTS
;
285 /* don't move the stream if the user specified a sink/source */
286 flags
|= PA_STREAM_DONT_MOVE
;
289 if (dir
== PA_STREAM_PLAYBACK
) {
290 r
= pa_stream_connect_playback(stream
, dev
, attr
, flags
, NULL
, NULL
);
292 r
= pa_stream_connect_record(stream
, dev
, attr
, flags
);
299 pa_threaded_mainloop_unlock(c
->mainloop
);
304 pa_threaded_mainloop_unlock(c
->mainloop
);
307 pa_stream_unref (stream
);
310 *rerror
= pa_context_errno(c
->context
);
315 static int qpa_init_out(HWVoiceOut
*hw
, struct audsettings
*as
,
321 struct audsettings obt_as
= *as
;
322 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
323 paaudio
*g
= pa
->g
= drv_opaque
;
324 AudiodevPaOptions
*popts
= &g
->dev
->u
.pa
;
325 AudiodevPaPerDirectionOptions
*ppdo
= popts
->out
;
326 PAConnection
*c
= g
->conn
;
328 ss
.format
= audfmt_to_pa (as
->fmt
, as
->endianness
);
329 ss
.channels
= as
->nchannels
;
332 ba
.tlength
= pa_usec_to_bytes(ppdo
->latency
, &ss
);
337 obt_as
.fmt
= pa_to_audfmt (ss
.format
, &obt_as
.endianness
);
339 pa
->stream
= qpa_simple_new (
343 ppdo
->has_name
? ppdo
->name
: NULL
,
345 NULL
, /* channel map */
346 &ba
, /* buffering attributes */
350 qpa_logerr (error
, "pa_simple_new for playback failed\n");
354 audio_pcm_init_info (&hw
->info
, &obt_as
);
355 hw
->samples
= pa
->samples
= audio_buffer_samples(
356 qapi_AudiodevPaPerDirectionOptions_base(ppdo
),
357 &obt_as
, ppdo
->buffer_length
);
365 static int qpa_init_in(HWVoiceIn
*hw
, struct audsettings
*as
, void *drv_opaque
)
370 struct audsettings obt_as
= *as
;
371 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
372 paaudio
*g
= pa
->g
= drv_opaque
;
373 AudiodevPaOptions
*popts
= &g
->dev
->u
.pa
;
374 AudiodevPaPerDirectionOptions
*ppdo
= popts
->in
;
375 PAConnection
*c
= g
->conn
;
377 ss
.format
= audfmt_to_pa (as
->fmt
, as
->endianness
);
378 ss
.channels
= as
->nchannels
;
381 ba
.fragsize
= pa_usec_to_bytes(ppdo
->latency
, &ss
);
382 ba
.maxlength
= pa_usec_to_bytes(ppdo
->latency
* 2, &ss
);
386 obt_as
.fmt
= pa_to_audfmt (ss
.format
, &obt_as
.endianness
);
388 pa
->stream
= qpa_simple_new (
392 ppdo
->has_name
? ppdo
->name
: NULL
,
394 NULL
, /* channel map */
395 &ba
, /* buffering attributes */
399 qpa_logerr (error
, "pa_simple_new for capture failed\n");
403 audio_pcm_init_info (&hw
->info
, &obt_as
);
404 hw
->samples
= pa
->samples
= audio_buffer_samples(
405 qapi_AudiodevPaPerDirectionOptions_base(ppdo
),
406 &obt_as
, ppdo
->buffer_length
);
414 static void qpa_simple_disconnect(PAConnection
*c
, pa_stream
*stream
)
418 pa_threaded_mainloop_lock(c
->mainloop
);
420 * wait until actually connects. workaround pa bug #247
421 * https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/247
423 while (pa_stream_get_state(stream
) == PA_STREAM_CREATING
) {
424 pa_threaded_mainloop_wait(c
->mainloop
);
427 err
= pa_stream_disconnect(stream
);
429 dolog("Failed to disconnect! err=%d\n", err
);
431 pa_stream_unref(stream
);
432 pa_threaded_mainloop_unlock(c
->mainloop
);
435 static void qpa_fini_out (HWVoiceOut
*hw
)
437 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
440 qpa_simple_disconnect(pa
->g
->conn
, pa
->stream
);
445 static void qpa_fini_in (HWVoiceIn
*hw
)
447 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
450 qpa_simple_disconnect(pa
->g
->conn
, pa
->stream
);
455 static void qpa_volume_out(HWVoiceOut
*hw
, struct mixeng_volume
*vol
)
457 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
460 PAConnection
*c
= pa
->g
->conn
;
462 #ifdef PA_CHECK_VERSION /* macro is present in 0.9.16+ */
463 pa_cvolume_init (&v
); /* function is present in 0.9.13+ */
467 v
.values
[0] = ((PA_VOLUME_NORM
- PA_VOLUME_MUTED
) * vol
->l
) / UINT32_MAX
;
468 v
.values
[1] = ((PA_VOLUME_NORM
- PA_VOLUME_MUTED
) * vol
->r
) / UINT32_MAX
;
470 pa_threaded_mainloop_lock(c
->mainloop
);
472 op
= pa_context_set_sink_input_volume(c
->context
,
473 pa_stream_get_index(pa
->stream
),
476 qpa_logerr(pa_context_errno(c
->context
),
477 "set_sink_input_volume() failed\n");
479 pa_operation_unref(op
);
482 op
= pa_context_set_sink_input_mute(c
->context
,
483 pa_stream_get_index(pa
->stream
),
484 vol
->mute
, NULL
, NULL
);
486 qpa_logerr(pa_context_errno(c
->context
),
487 "set_sink_input_mute() failed\n");
489 pa_operation_unref(op
);
492 pa_threaded_mainloop_unlock(c
->mainloop
);
495 static void qpa_volume_in(HWVoiceIn
*hw
, struct mixeng_volume
*vol
)
497 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
500 PAConnection
*c
= pa
->g
->conn
;
502 #ifdef PA_CHECK_VERSION
503 pa_cvolume_init (&v
);
507 v
.values
[0] = ((PA_VOLUME_NORM
- PA_VOLUME_MUTED
) * vol
->l
) / UINT32_MAX
;
508 v
.values
[1] = ((PA_VOLUME_NORM
- PA_VOLUME_MUTED
) * vol
->r
) / UINT32_MAX
;
510 pa_threaded_mainloop_lock(c
->mainloop
);
512 op
= pa_context_set_source_output_volume(c
->context
,
513 pa_stream_get_index(pa
->stream
),
516 qpa_logerr(pa_context_errno(c
->context
),
517 "set_source_output_volume() failed\n");
519 pa_operation_unref(op
);
522 op
= pa_context_set_source_output_mute(c
->context
,
523 pa_stream_get_index(pa
->stream
),
524 vol
->mute
, NULL
, NULL
);
526 qpa_logerr(pa_context_errno(c
->context
),
527 "set_source_output_mute() failed\n");
529 pa_operation_unref(op
);
532 pa_threaded_mainloop_unlock(c
->mainloop
);
535 static int qpa_validate_per_direction_opts(Audiodev
*dev
,
536 AudiodevPaPerDirectionOptions
*pdo
)
538 if (!pdo
->has_buffer_length
) {
539 pdo
->has_buffer_length
= true;
540 pdo
->buffer_length
= 46440;
542 if (!pdo
->has_latency
) {
543 pdo
->has_latency
= true;
544 pdo
->latency
= 15000;
550 static void *qpa_conn_init(const char *server
)
552 PAConnection
*c
= g_malloc0(sizeof(PAConnection
));
553 QTAILQ_INSERT_TAIL(&pa_conns
, c
, list
);
555 c
->mainloop
= pa_threaded_mainloop_new();
560 c
->context
= pa_context_new(pa_threaded_mainloop_get_api(c
->mainloop
),
566 pa_context_set_state_callback(c
->context
, context_state_cb
, c
);
568 if (pa_context_connect(c
->context
, server
, 0, NULL
) < 0) {
569 qpa_logerr(pa_context_errno(c
->context
),
570 "pa_context_connect() failed\n");
574 pa_threaded_mainloop_lock(c
->mainloop
);
576 if (pa_threaded_mainloop_start(c
->mainloop
) < 0) {
577 goto unlock_and_fail
;
581 pa_context_state_t state
;
583 state
= pa_context_get_state(c
->context
);
585 if (state
== PA_CONTEXT_READY
) {
589 if (!PA_CONTEXT_IS_GOOD(state
)) {
590 qpa_logerr(pa_context_errno(c
->context
),
591 "Wrong context state\n");
592 goto unlock_and_fail
;
595 /* Wait until the context is ready */
596 pa_threaded_mainloop_wait(c
->mainloop
);
599 pa_threaded_mainloop_unlock(c
->mainloop
);
603 pa_threaded_mainloop_unlock(c
->mainloop
);
605 AUD_log (AUDIO_CAP
, "Failed to initialize PA context");
610 static void *qpa_audio_init(Audiodev
*dev
)
613 AudiodevPaOptions
*popts
= &dev
->u
.pa
;
617 assert(dev
->driver
== AUDIODEV_DRIVER_PA
);
619 if (!popts
->has_server
) {
624 runtime
= getenv("XDG_RUNTIME_DIR");
628 snprintf(pidfile
, sizeof(pidfile
), "%s/pulse/pid", runtime
);
629 if (stat(pidfile
, &st
) != 0) {
634 if (!qpa_validate_per_direction_opts(dev
, popts
->in
)) {
637 if (!qpa_validate_per_direction_opts(dev
, popts
->out
)) {
641 g
= g_malloc0(sizeof(paaudio
));
642 server
= popts
->has_server
? popts
->server
: NULL
;
646 QTAILQ_FOREACH(c
, &pa_conns
, list
) {
647 if (server
== NULL
|| c
->server
== NULL
?
648 server
== c
->server
:
649 strcmp(server
, c
->server
) == 0) {
655 g
->conn
= qpa_conn_init(server
);
666 static void qpa_conn_fini(PAConnection
*c
)
669 pa_threaded_mainloop_stop(c
->mainloop
);
673 pa_context_disconnect(c
->context
);
674 pa_context_unref(c
->context
);
678 pa_threaded_mainloop_free(c
->mainloop
);
681 QTAILQ_REMOVE(&pa_conns
, c
, list
);
685 static void qpa_audio_fini (void *opaque
)
688 PAConnection
*c
= g
->conn
;
690 if (--c
->refcount
== 0) {
697 static struct audio_pcm_ops qpa_pcm_ops
= {
698 .init_out
= qpa_init_out
,
699 .fini_out
= qpa_fini_out
,
701 .volume_out
= qpa_volume_out
,
703 .init_in
= qpa_init_in
,
704 .fini_in
= qpa_fini_in
,
706 .volume_in
= qpa_volume_in
709 static struct audio_driver pa_audio_driver
= {
711 .descr
= "http://www.pulseaudio.org/",
712 .init
= qpa_audio_init
,
713 .fini
= qpa_audio_fini
,
714 .pcm_ops
= &qpa_pcm_ops
,
716 .max_voices_out
= INT_MAX
,
717 .max_voices_in
= INT_MAX
,
718 .voice_size_out
= sizeof (PAVoiceOut
),
719 .voice_size_in
= sizeof (PAVoiceIn
),
722 static void register_audio_pa(void)
724 audio_driver_register(&pa_audio_driver
);
726 type_init(register_audio_pa
);