3 #include "qemu/osdep.h"
4 #include "qemu/module.h"
5 #include "qemu-common.h"
7 #include "qapi/opts-visitor.h"
9 #include <pulse/pulseaudio.h>
11 #define AUDIO_CAP "pulseaudio"
12 #include "audio_int.h"
14 typedef struct PAConnection
{
17 QTAILQ_ENTRY(PAConnection
) list
;
19 pa_threaded_mainloop
*mainloop
;
23 static QTAILQ_HEAD(PAConnectionHead
, PAConnection
) pa_conns
=
24 QTAILQ_HEAD_INITIALIZER(pa_conns
);
40 const void *read_data
;
45 static void qpa_conn_fini(PAConnection
*c
);
47 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err
, const char *fmt
, ...)
52 AUD_vlog (AUDIO_CAP
, fmt
, ap
);
55 AUD_log (AUDIO_CAP
, "Reason: %s\n", pa_strerror (err
));
58 #ifndef PA_CONTEXT_IS_GOOD
59 static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x
)
62 x
== PA_CONTEXT_CONNECTING
||
63 x
== PA_CONTEXT_AUTHORIZING
||
64 x
== PA_CONTEXT_SETTING_NAME
||
65 x
== PA_CONTEXT_READY
;
69 #ifndef PA_STREAM_IS_GOOD
70 static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x
)
73 x
== PA_STREAM_CREATING
||
78 #define CHECK_SUCCESS_GOTO(c, expression, label, msg) \
80 if (!(expression)) { \
81 qpa_logerr(pa_context_errno((c)->context), msg); \
86 #define CHECK_DEAD_GOTO(c, stream, label, msg) \
88 if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \
89 !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \
90 if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \
91 ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \
92 qpa_logerr(pa_context_errno((c)->context), msg); \
94 qpa_logerr(PA_ERR_BADSTATE, msg); \
100 static void *qpa_get_buffer_in(HWVoiceIn
*hw
, size_t *size
)
102 PAVoiceIn
*p
= (PAVoiceIn
*) hw
;
103 PAConnection
*c
= p
->g
->conn
;
106 pa_threaded_mainloop_lock(c
->mainloop
);
108 CHECK_DEAD_GOTO(c
, p
->stream
, unlock_and_fail
,
109 "pa_threaded_mainloop_lock failed\n");
111 if (!p
->read_length
) {
112 r
= pa_stream_peek(p
->stream
, &p
->read_data
, &p
->read_length
);
113 CHECK_SUCCESS_GOTO(c
, r
== 0, unlock_and_fail
,
114 "pa_stream_peek failed\n");
117 *size
= MIN(p
->read_length
, *size
);
119 pa_threaded_mainloop_unlock(c
->mainloop
);
120 return (void *) p
->read_data
;
123 pa_threaded_mainloop_unlock(c
->mainloop
);
128 static void qpa_put_buffer_in(HWVoiceIn
*hw
, void *buf
, size_t size
)
130 PAVoiceIn
*p
= (PAVoiceIn
*) hw
;
131 PAConnection
*c
= p
->g
->conn
;
134 pa_threaded_mainloop_lock(c
->mainloop
);
136 CHECK_DEAD_GOTO(c
, p
->stream
, unlock
,
137 "pa_threaded_mainloop_lock failed\n");
139 assert(buf
== p
->read_data
&& size
<= p
->read_length
);
141 p
->read_data
+= size
;
142 p
->read_length
-= size
;
144 if (size
&& !p
->read_length
) {
145 r
= pa_stream_drop(p
->stream
);
146 CHECK_SUCCESS_GOTO(c
, r
== 0, unlock
, "pa_stream_drop failed\n");
150 pa_threaded_mainloop_unlock(c
->mainloop
);
153 static size_t qpa_read(HWVoiceIn
*hw
, void *data
, size_t length
)
155 PAVoiceIn
*p
= (PAVoiceIn
*) hw
;
156 PAConnection
*c
= p
->g
->conn
;
159 pa_threaded_mainloop_lock(c
->mainloop
);
161 CHECK_DEAD_GOTO(c
, p
->stream
, unlock_and_fail
,
162 "pa_threaded_mainloop_lock failed\n");
163 if (pa_stream_get_state(p
->stream
) != PA_STREAM_READY
) {
164 /* wait for stream to become ready */
168 while (total
< length
) {
172 if (!p
->read_length
) {
173 r
= pa_stream_peek(p
->stream
, &p
->read_data
, &p
->read_length
);
174 CHECK_SUCCESS_GOTO(c
, r
== 0, unlock_and_fail
,
175 "pa_stream_peek failed\n");
176 if (!p
->read_length
) {
177 /* buffer is empty */
182 l
= MIN(p
->read_length
, length
- total
);
183 memcpy((char *)data
+ total
, p
->read_data
, l
);
189 if (!p
->read_length
) {
190 r
= pa_stream_drop(p
->stream
);
191 CHECK_SUCCESS_GOTO(c
, r
== 0, unlock_and_fail
,
192 "pa_stream_drop failed\n");
197 pa_threaded_mainloop_unlock(c
->mainloop
);
201 pa_threaded_mainloop_unlock(c
->mainloop
);
205 static void *qpa_get_buffer_out(HWVoiceOut
*hw
, size_t *size
)
207 PAVoiceOut
*p
= (PAVoiceOut
*) hw
;
208 PAConnection
*c
= p
->g
->conn
;
213 pa_threaded_mainloop_lock(c
->mainloop
);
215 CHECK_DEAD_GOTO(c
, p
->stream
, unlock_and_fail
,
216 "pa_threaded_mainloop_lock failed\n");
217 if (pa_stream_get_state(p
->stream
) != PA_STREAM_READY
) {
218 /* wait for stream to become ready */
224 l
= pa_stream_writable_size(p
->stream
);
225 CHECK_SUCCESS_GOTO(c
, l
!= (size_t) -1, unlock_and_fail
,
226 "pa_stream_writable_size failed\n");
229 r
= pa_stream_begin_write(p
->stream
, &ret
, size
);
230 CHECK_SUCCESS_GOTO(c
, r
>= 0, unlock_and_fail
,
231 "pa_stream_begin_write failed\n");
234 pa_threaded_mainloop_unlock(c
->mainloop
);
241 pa_threaded_mainloop_unlock(c
->mainloop
);
246 static size_t qpa_put_buffer_out(HWVoiceOut
*hw
, void *data
, size_t length
)
248 PAVoiceOut
*p
= (PAVoiceOut
*)hw
;
249 PAConnection
*c
= p
->g
->conn
;
252 pa_threaded_mainloop_lock(c
->mainloop
);
254 CHECK_DEAD_GOTO(c
, p
->stream
, unlock_and_fail
,
255 "pa_threaded_mainloop_lock failed\n");
257 r
= pa_stream_write(p
->stream
, data
, length
, NULL
, 0LL, PA_SEEK_RELATIVE
);
258 CHECK_SUCCESS_GOTO(c
, r
>= 0, unlock_and_fail
, "pa_stream_write failed\n");
260 pa_threaded_mainloop_unlock(c
->mainloop
);
264 pa_threaded_mainloop_unlock(c
->mainloop
);
268 static size_t qpa_write(HWVoiceOut
*hw
, void *data
, size_t length
)
270 PAVoiceOut
*p
= (PAVoiceOut
*) hw
;
271 PAConnection
*c
= p
->g
->conn
;
275 pa_threaded_mainloop_lock(c
->mainloop
);
277 CHECK_DEAD_GOTO(c
, p
->stream
, unlock_and_fail
,
278 "pa_threaded_mainloop_lock failed\n");
279 if (pa_stream_get_state(p
->stream
) != PA_STREAM_READY
) {
280 /* wait for stream to become ready */
285 l
= pa_stream_writable_size(p
->stream
);
287 CHECK_SUCCESS_GOTO(c
, l
!= (size_t) -1, unlock_and_fail
,
288 "pa_stream_writable_size failed\n");
294 r
= pa_stream_write(p
->stream
, data
, l
, NULL
, 0LL, PA_SEEK_RELATIVE
);
295 CHECK_SUCCESS_GOTO(c
, r
>= 0, unlock_and_fail
, "pa_stream_write failed\n");
298 pa_threaded_mainloop_unlock(c
->mainloop
);
302 pa_threaded_mainloop_unlock(c
->mainloop
);
306 static pa_sample_format_t
audfmt_to_pa (AudioFormat afmt
, int endianness
)
311 case AUDIO_FORMAT_S8
:
312 case AUDIO_FORMAT_U8
:
313 format
= PA_SAMPLE_U8
;
315 case AUDIO_FORMAT_S16
:
316 case AUDIO_FORMAT_U16
:
317 format
= endianness
? PA_SAMPLE_S16BE
: PA_SAMPLE_S16LE
;
319 case AUDIO_FORMAT_S32
:
320 case AUDIO_FORMAT_U32
:
321 format
= endianness
? PA_SAMPLE_S32BE
: PA_SAMPLE_S32LE
;
323 case AUDIO_FORMAT_F32
:
324 format
= endianness
? PA_SAMPLE_FLOAT32BE
: PA_SAMPLE_FLOAT32LE
;
327 dolog ("Internal logic error: Bad audio format %d\n", afmt
);
328 format
= PA_SAMPLE_U8
;
334 static AudioFormat
pa_to_audfmt (pa_sample_format_t fmt
, int *endianness
)
338 return AUDIO_FORMAT_U8
;
339 case PA_SAMPLE_S16BE
:
341 return AUDIO_FORMAT_S16
;
342 case PA_SAMPLE_S16LE
:
344 return AUDIO_FORMAT_S16
;
345 case PA_SAMPLE_S32BE
:
347 return AUDIO_FORMAT_S32
;
348 case PA_SAMPLE_S32LE
:
350 return AUDIO_FORMAT_S32
;
351 case PA_SAMPLE_FLOAT32BE
:
353 return AUDIO_FORMAT_F32
;
354 case PA_SAMPLE_FLOAT32LE
:
356 return AUDIO_FORMAT_F32
;
358 dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt
);
359 return AUDIO_FORMAT_U8
;
363 static void context_state_cb (pa_context
*c
, void *userdata
)
365 PAConnection
*conn
= userdata
;
367 switch (pa_context_get_state(c
)) {
368 case PA_CONTEXT_READY
:
369 case PA_CONTEXT_TERMINATED
:
370 case PA_CONTEXT_FAILED
:
371 pa_threaded_mainloop_signal(conn
->mainloop
, 0);
374 case PA_CONTEXT_UNCONNECTED
:
375 case PA_CONTEXT_CONNECTING
:
376 case PA_CONTEXT_AUTHORIZING
:
377 case PA_CONTEXT_SETTING_NAME
:
382 static void stream_state_cb (pa_stream
*s
, void * userdata
)
384 PAConnection
*c
= userdata
;
386 switch (pa_stream_get_state (s
)) {
388 case PA_STREAM_READY
:
389 case PA_STREAM_FAILED
:
390 case PA_STREAM_TERMINATED
:
391 pa_threaded_mainloop_signal(c
->mainloop
, 0);
394 case PA_STREAM_UNCONNECTED
:
395 case PA_STREAM_CREATING
:
400 static pa_stream
*qpa_simple_new (
403 pa_stream_direction_t dir
,
405 const pa_sample_spec
*ss
,
406 const pa_buffer_attr
*attr
,
410 pa_stream
*stream
= NULL
;
411 pa_stream_flags_t flags
;
414 pa_threaded_mainloop_lock(c
->mainloop
);
416 pa_channel_map_init(&map
);
417 map
.channels
= ss
->channels
;
420 * TODO: This currently expects the only frontend supporting more than 2
421 * channels is the usb-audio. We will need some means to set channel
422 * order when a new frontend gains multi-channel support.
424 switch (ss
->channels
) {
426 map
.map
[0] = PA_CHANNEL_POSITION_MONO
;
430 map
.map
[0] = PA_CHANNEL_POSITION_LEFT
;
431 map
.map
[1] = PA_CHANNEL_POSITION_RIGHT
;
435 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
436 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
437 map
.map
[2] = PA_CHANNEL_POSITION_CENTER
;
438 map
.map
[3] = PA_CHANNEL_POSITION_LFE
;
439 map
.map
[4] = PA_CHANNEL_POSITION_REAR_LEFT
;
440 map
.map
[5] = PA_CHANNEL_POSITION_REAR_RIGHT
;
444 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
445 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
446 map
.map
[2] = PA_CHANNEL_POSITION_CENTER
;
447 map
.map
[3] = PA_CHANNEL_POSITION_LFE
;
448 map
.map
[4] = PA_CHANNEL_POSITION_REAR_LEFT
;
449 map
.map
[5] = PA_CHANNEL_POSITION_REAR_RIGHT
;
450 map
.map
[6] = PA_CHANNEL_POSITION_SIDE_LEFT
;
451 map
.map
[7] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
455 dolog("Internal error: unsupported channel count %d\n", ss
->channels
);
459 stream
= pa_stream_new(c
->context
, name
, ss
, &map
);
464 pa_stream_set_state_callback(stream
, stream_state_cb
, c
);
467 PA_STREAM_INTERPOLATE_TIMING
468 | PA_STREAM_AUTO_TIMING_UPDATE
469 | PA_STREAM_EARLY_REQUESTS
;
472 /* don't move the stream if the user specified a sink/source */
473 flags
|= PA_STREAM_DONT_MOVE
;
476 if (dir
== PA_STREAM_PLAYBACK
) {
477 r
= pa_stream_connect_playback(stream
, dev
, attr
, flags
, NULL
, NULL
);
479 r
= pa_stream_connect_record(stream
, dev
, attr
, flags
);
486 pa_threaded_mainloop_unlock(c
->mainloop
);
491 pa_threaded_mainloop_unlock(c
->mainloop
);
494 pa_stream_unref (stream
);
497 *rerror
= pa_context_errno(c
->context
);
502 static int qpa_init_out(HWVoiceOut
*hw
, struct audsettings
*as
,
508 struct audsettings obt_as
= *as
;
509 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
510 paaudio
*g
= pa
->g
= drv_opaque
;
511 AudiodevPaOptions
*popts
= &g
->dev
->u
.pa
;
512 AudiodevPaPerDirectionOptions
*ppdo
= popts
->out
;
513 PAConnection
*c
= g
->conn
;
515 ss
.format
= audfmt_to_pa (as
->fmt
, as
->endianness
);
516 ss
.channels
= as
->nchannels
;
519 ba
.tlength
= pa_usec_to_bytes(ppdo
->latency
, &ss
);
520 ba
.minreq
= pa_usec_to_bytes(MIN(ppdo
->latency
>> 2,
521 (g
->dev
->timer_period
>> 2) * 3), &ss
);
525 obt_as
.fmt
= pa_to_audfmt (ss
.format
, &obt_as
.endianness
);
527 pa
->stream
= qpa_simple_new (
529 ppdo
->has_stream_name
? ppdo
->stream_name
: g
->dev
->id
,
531 ppdo
->has_name
? ppdo
->name
: NULL
,
533 &ba
, /* buffering attributes */
537 qpa_logerr (error
, "pa_simple_new for playback failed\n");
541 audio_pcm_init_info (&hw
->info
, &obt_as
);
543 * This is wrong. hw->samples counts in frames. hw->samples will be
544 * number of channels times larger than expected.
546 hw
->samples
= audio_buffer_samples(
547 qapi_AudiodevPaPerDirectionOptions_base(ppdo
), &obt_as
, 46440);
555 static int qpa_init_in(HWVoiceIn
*hw
, struct audsettings
*as
, void *drv_opaque
)
560 struct audsettings obt_as
= *as
;
561 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
562 paaudio
*g
= pa
->g
= drv_opaque
;
563 AudiodevPaOptions
*popts
= &g
->dev
->u
.pa
;
564 AudiodevPaPerDirectionOptions
*ppdo
= popts
->in
;
565 PAConnection
*c
= g
->conn
;
567 ss
.format
= audfmt_to_pa (as
->fmt
, as
->endianness
);
568 ss
.channels
= as
->nchannels
;
571 ba
.fragsize
= pa_usec_to_bytes((g
->dev
->timer_period
>> 1) * 3, &ss
);
572 ba
.maxlength
= pa_usec_to_bytes(
573 MAX(ppdo
->latency
, g
->dev
->timer_period
* 3), &ss
);
577 obt_as
.fmt
= pa_to_audfmt (ss
.format
, &obt_as
.endianness
);
579 pa
->stream
= qpa_simple_new (
581 ppdo
->has_stream_name
? ppdo
->stream_name
: g
->dev
->id
,
583 ppdo
->has_name
? ppdo
->name
: NULL
,
585 &ba
, /* buffering attributes */
589 qpa_logerr (error
, "pa_simple_new for capture failed\n");
593 audio_pcm_init_info (&hw
->info
, &obt_as
);
595 * This is wrong. hw->samples counts in frames. hw->samples will be
596 * number of channels times larger than expected.
598 hw
->samples
= audio_buffer_samples(
599 qapi_AudiodevPaPerDirectionOptions_base(ppdo
), &obt_as
, 46440);
607 static void qpa_simple_disconnect(PAConnection
*c
, pa_stream
*stream
)
612 * wait until actually connects. workaround pa bug #247
613 * https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/247
615 while (pa_stream_get_state(stream
) == PA_STREAM_CREATING
) {
616 pa_threaded_mainloop_wait(c
->mainloop
);
619 err
= pa_stream_disconnect(stream
);
621 dolog("Failed to disconnect! err=%d\n", err
);
623 pa_stream_unref(stream
);
626 static void qpa_fini_out (HWVoiceOut
*hw
)
628 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
631 PAConnection
*c
= pa
->g
->conn
;
633 pa_threaded_mainloop_lock(c
->mainloop
);
634 qpa_simple_disconnect(c
, pa
->stream
);
636 pa_threaded_mainloop_unlock(c
->mainloop
);
640 static void qpa_fini_in (HWVoiceIn
*hw
)
642 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
645 PAConnection
*c
= pa
->g
->conn
;
647 pa_threaded_mainloop_lock(c
->mainloop
);
648 if (pa
->read_length
) {
649 int r
= pa_stream_drop(pa
->stream
);
651 qpa_logerr(pa_context_errno(c
->context
),
652 "pa_stream_drop failed\n");
656 qpa_simple_disconnect(c
, pa
->stream
);
658 pa_threaded_mainloop_unlock(c
->mainloop
);
662 static void qpa_volume_out(HWVoiceOut
*hw
, Volume
*vol
)
664 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
667 PAConnection
*c
= pa
->g
->conn
;
670 #ifdef PA_CHECK_VERSION /* macro is present in 0.9.16+ */
671 pa_cvolume_init (&v
); /* function is present in 0.9.13+ */
674 v
.channels
= vol
->channels
;
675 for (i
= 0; i
< vol
->channels
; ++i
) {
676 v
.values
[i
] = ((PA_VOLUME_NORM
- PA_VOLUME_MUTED
) * vol
->vol
[i
]) / 255;
679 pa_threaded_mainloop_lock(c
->mainloop
);
681 op
= pa_context_set_sink_input_volume(c
->context
,
682 pa_stream_get_index(pa
->stream
),
685 qpa_logerr(pa_context_errno(c
->context
),
686 "set_sink_input_volume() failed\n");
688 pa_operation_unref(op
);
691 op
= pa_context_set_sink_input_mute(c
->context
,
692 pa_stream_get_index(pa
->stream
),
693 vol
->mute
, NULL
, NULL
);
695 qpa_logerr(pa_context_errno(c
->context
),
696 "set_sink_input_mute() failed\n");
698 pa_operation_unref(op
);
701 pa_threaded_mainloop_unlock(c
->mainloop
);
704 static void qpa_volume_in(HWVoiceIn
*hw
, Volume
*vol
)
706 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
709 PAConnection
*c
= pa
->g
->conn
;
712 #ifdef PA_CHECK_VERSION
713 pa_cvolume_init (&v
);
716 v
.channels
= vol
->channels
;
717 for (i
= 0; i
< vol
->channels
; ++i
) {
718 v
.values
[i
] = ((PA_VOLUME_NORM
- PA_VOLUME_MUTED
) * vol
->vol
[i
]) / 255;
721 pa_threaded_mainloop_lock(c
->mainloop
);
723 op
= pa_context_set_source_output_volume(c
->context
,
724 pa_stream_get_index(pa
->stream
),
727 qpa_logerr(pa_context_errno(c
->context
),
728 "set_source_output_volume() failed\n");
730 pa_operation_unref(op
);
733 op
= pa_context_set_source_output_mute(c
->context
,
734 pa_stream_get_index(pa
->stream
),
735 vol
->mute
, NULL
, NULL
);
737 qpa_logerr(pa_context_errno(c
->context
),
738 "set_source_output_mute() failed\n");
740 pa_operation_unref(op
);
743 pa_threaded_mainloop_unlock(c
->mainloop
);
746 static int qpa_validate_per_direction_opts(Audiodev
*dev
,
747 AudiodevPaPerDirectionOptions
*pdo
)
749 if (!pdo
->has_latency
) {
750 pdo
->has_latency
= true;
751 pdo
->latency
= 15000;
757 static void *qpa_conn_init(const char *server
)
760 PAConnection
*c
= g_malloc0(sizeof(PAConnection
));
761 QTAILQ_INSERT_TAIL(&pa_conns
, c
, list
);
763 c
->mainloop
= pa_threaded_mainloop_new();
768 vm_name
= qemu_get_vm_name();
769 c
->context
= pa_context_new(pa_threaded_mainloop_get_api(c
->mainloop
),
770 vm_name
? vm_name
: "qemu");
775 pa_context_set_state_callback(c
->context
, context_state_cb
, c
);
777 if (pa_context_connect(c
->context
, server
, 0, NULL
) < 0) {
778 qpa_logerr(pa_context_errno(c
->context
),
779 "pa_context_connect() failed\n");
783 pa_threaded_mainloop_lock(c
->mainloop
);
785 if (pa_threaded_mainloop_start(c
->mainloop
) < 0) {
786 goto unlock_and_fail
;
790 pa_context_state_t state
;
792 state
= pa_context_get_state(c
->context
);
794 if (state
== PA_CONTEXT_READY
) {
798 if (!PA_CONTEXT_IS_GOOD(state
)) {
799 qpa_logerr(pa_context_errno(c
->context
),
800 "Wrong context state\n");
801 goto unlock_and_fail
;
804 /* Wait until the context is ready */
805 pa_threaded_mainloop_wait(c
->mainloop
);
808 pa_threaded_mainloop_unlock(c
->mainloop
);
812 pa_threaded_mainloop_unlock(c
->mainloop
);
814 AUD_log (AUDIO_CAP
, "Failed to initialize PA context");
819 static void *qpa_audio_init(Audiodev
*dev
)
822 AudiodevPaOptions
*popts
= &dev
->u
.pa
;
826 assert(dev
->driver
== AUDIODEV_DRIVER_PA
);
828 if (!popts
->has_server
) {
833 runtime
= getenv("XDG_RUNTIME_DIR");
837 snprintf(pidfile
, sizeof(pidfile
), "%s/pulse/pid", runtime
);
838 if (stat(pidfile
, &st
) != 0) {
843 if (!qpa_validate_per_direction_opts(dev
, popts
->in
)) {
846 if (!qpa_validate_per_direction_opts(dev
, popts
->out
)) {
850 g
= g_malloc0(sizeof(paaudio
));
851 server
= popts
->has_server
? popts
->server
: NULL
;
855 QTAILQ_FOREACH(c
, &pa_conns
, list
) {
856 if (server
== NULL
|| c
->server
== NULL
?
857 server
== c
->server
:
858 strcmp(server
, c
->server
) == 0) {
864 g
->conn
= qpa_conn_init(server
);
875 static void qpa_conn_fini(PAConnection
*c
)
878 pa_threaded_mainloop_stop(c
->mainloop
);
882 pa_context_disconnect(c
->context
);
883 pa_context_unref(c
->context
);
887 pa_threaded_mainloop_free(c
->mainloop
);
890 QTAILQ_REMOVE(&pa_conns
, c
, list
);
894 static void qpa_audio_fini (void *opaque
)
897 PAConnection
*c
= g
->conn
;
899 if (--c
->refcount
== 0) {
906 static struct audio_pcm_ops qpa_pcm_ops
= {
907 .init_out
= qpa_init_out
,
908 .fini_out
= qpa_fini_out
,
910 .get_buffer_out
= qpa_get_buffer_out
,
911 .put_buffer_out
= qpa_put_buffer_out
,
912 .volume_out
= qpa_volume_out
,
914 .init_in
= qpa_init_in
,
915 .fini_in
= qpa_fini_in
,
917 .get_buffer_in
= qpa_get_buffer_in
,
918 .put_buffer_in
= qpa_put_buffer_in
,
919 .volume_in
= qpa_volume_in
922 static struct audio_driver pa_audio_driver
= {
924 .descr
= "http://www.pulseaudio.org/",
925 .init
= qpa_audio_init
,
926 .fini
= qpa_audio_fini
,
927 .pcm_ops
= &qpa_pcm_ops
,
929 .max_voices_out
= INT_MAX
,
930 .max_voices_in
= INT_MAX
,
931 .voice_size_out
= sizeof (PAVoiceOut
),
932 .voice_size_in
= sizeof (PAVoiceIn
),
935 static void register_audio_pa(void)
937 audio_driver_register(&pa_audio_driver
);
939 type_init(register_audio_pa
);