2 #include "qemu-common.h"
5 #include <pulse/simple.h>
6 #include <pulse/error.h>
8 #define AUDIO_CAP "pulseaudio"
10 #include "audio_pt_int.h"
45 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err
, const char *fmt
, ...)
50 AUD_vlog (AUDIO_CAP
, fmt
, ap
);
53 AUD_log (AUDIO_CAP
, "Reason: %s\n", pa_strerror (err
));
56 static void *qpa_thread_out (void *arg
)
59 HWVoiceOut
*hw
= &pa
->hw
;
62 threshold
= conf
.divisor
? hw
->samples
/ conf
.divisor
: 0;
64 if (audio_pt_lock (&pa
->pt
, AUDIO_FUNC
)) {
69 int decr
, to_mix
, rpos
;
76 if (pa
->live
> threshold
) {
80 if (audio_pt_wait (&pa
->pt
, AUDIO_FUNC
)) {
85 decr
= to_mix
= pa
->live
;
88 if (audio_pt_unlock (&pa
->pt
, AUDIO_FUNC
)) {
94 int chunk
= audio_MIN (to_mix
, hw
->samples
- rpos
);
95 struct st_sample
*src
= hw
->mix_buf
+ rpos
;
97 hw
->clip (pa
->pcm_buf
, src
, chunk
);
99 if (pa_simple_write (pa
->s
, pa
->pcm_buf
,
100 chunk
<< hw
->info
.shift
, &error
) < 0) {
101 qpa_logerr (error
, "pa_simple_write failed\n");
105 rpos
= (rpos
+ chunk
) % hw
->samples
;
109 if (audio_pt_lock (&pa
->pt
, AUDIO_FUNC
)) {
119 audio_pt_unlock (&pa
->pt
, AUDIO_FUNC
);
123 static int qpa_run_out (HWVoiceOut
*hw
, int live
)
126 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
128 if (audio_pt_lock (&pa
->pt
, AUDIO_FUNC
)) {
132 decr
= audio_MIN (live
, pa
->decr
);
134 pa
->live
= live
- decr
;
137 audio_pt_unlock_and_signal (&pa
->pt
, AUDIO_FUNC
);
140 audio_pt_unlock (&pa
->pt
, AUDIO_FUNC
);
145 static int qpa_write (SWVoiceOut
*sw
, void *buf
, int len
)
147 return audio_pcm_sw_write (sw
, buf
, len
);
151 static void *qpa_thread_in (void *arg
)
154 HWVoiceIn
*hw
= &pa
->hw
;
157 threshold
= conf
.divisor
? hw
->samples
/ conf
.divisor
: 0;
159 if (audio_pt_lock (&pa
->pt
, AUDIO_FUNC
)) {
164 int incr
, to_grab
, wpos
;
171 if (pa
->dead
> threshold
) {
175 if (audio_pt_wait (&pa
->pt
, AUDIO_FUNC
)) {
180 incr
= to_grab
= pa
->dead
;
183 if (audio_pt_unlock (&pa
->pt
, AUDIO_FUNC
)) {
189 int chunk
= audio_MIN (to_grab
, hw
->samples
- wpos
);
190 void *buf
= advance (pa
->pcm_buf
, wpos
);
192 if (pa_simple_read (pa
->s
, buf
,
193 chunk
<< hw
->info
.shift
, &error
) < 0) {
194 qpa_logerr (error
, "pa_simple_read failed\n");
198 hw
->conv (hw
->conv_buf
+ wpos
, buf
, chunk
, &nominal_volume
);
199 wpos
= (wpos
+ chunk
) % hw
->samples
;
203 if (audio_pt_lock (&pa
->pt
, AUDIO_FUNC
)) {
213 audio_pt_unlock (&pa
->pt
, AUDIO_FUNC
);
217 static int qpa_run_in (HWVoiceIn
*hw
)
219 int live
, incr
, dead
;
220 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
222 if (audio_pt_lock (&pa
->pt
, AUDIO_FUNC
)) {
226 live
= audio_pcm_hw_get_live_in (hw
);
227 dead
= hw
->samples
- live
;
228 incr
= audio_MIN (dead
, pa
->incr
);
230 pa
->dead
= dead
- incr
;
233 audio_pt_unlock_and_signal (&pa
->pt
, AUDIO_FUNC
);
236 audio_pt_unlock (&pa
->pt
, AUDIO_FUNC
);
241 static int qpa_read (SWVoiceIn
*sw
, void *buf
, int len
)
243 return audio_pcm_sw_read (sw
, buf
, len
);
246 static pa_sample_format_t
audfmt_to_pa (audfmt_e afmt
, int endianness
)
253 format
= PA_SAMPLE_U8
;
257 format
= endianness
? PA_SAMPLE_S16BE
: PA_SAMPLE_S16LE
;
261 format
= endianness
? PA_SAMPLE_S32BE
: PA_SAMPLE_S32LE
;
264 dolog ("Internal logic error: Bad audio format %d\n", afmt
);
265 format
= PA_SAMPLE_U8
;
271 static audfmt_e
pa_to_audfmt (pa_sample_format_t fmt
, int *endianness
)
276 case PA_SAMPLE_S16BE
:
279 case PA_SAMPLE_S16LE
:
282 case PA_SAMPLE_S32BE
:
285 case PA_SAMPLE_S32LE
:
289 dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt
);
294 static int qpa_init_out (HWVoiceOut
*hw
, struct audsettings
*as
)
297 static pa_sample_spec ss
;
298 struct audsettings obt_as
= *as
;
299 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
301 ss
.format
= audfmt_to_pa (as
->fmt
, as
->endianness
);
302 ss
.channels
= as
->nchannels
;
305 obt_as
.fmt
= pa_to_audfmt (ss
.format
, &obt_as
.endianness
);
307 pa
->s
= pa_simple_new (
314 NULL
, /* channel map */
315 NULL
, /* buffering attributes */
319 qpa_logerr (error
, "pa_simple_new for playback failed\n");
323 audio_pcm_init_info (&hw
->info
, &obt_as
);
324 hw
->samples
= conf
.samples
;
325 pa
->pcm_buf
= audio_calloc (AUDIO_FUNC
, hw
->samples
, 1 << hw
->info
.shift
);
327 dolog ("Could not allocate buffer (%d bytes)\n",
328 hw
->samples
<< hw
->info
.shift
);
332 if (audio_pt_init (&pa
->pt
, qpa_thread_out
, hw
, AUDIO_CAP
, AUDIO_FUNC
)) {
339 qemu_free (pa
->pcm_buf
);
342 pa_simple_free (pa
->s
);
348 static int qpa_init_in (HWVoiceIn
*hw
, struct audsettings
*as
)
351 static pa_sample_spec ss
;
352 struct audsettings obt_as
= *as
;
353 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
355 ss
.format
= audfmt_to_pa (as
->fmt
, as
->endianness
);
356 ss
.channels
= as
->nchannels
;
359 obt_as
.fmt
= pa_to_audfmt (ss
.format
, &obt_as
.endianness
);
361 pa
->s
= pa_simple_new (
368 NULL
, /* channel map */
369 NULL
, /* buffering attributes */
373 qpa_logerr (error
, "pa_simple_new for capture failed\n");
377 audio_pcm_init_info (&hw
->info
, &obt_as
);
378 hw
->samples
= conf
.samples
;
379 pa
->pcm_buf
= audio_calloc (AUDIO_FUNC
, hw
->samples
, 1 << hw
->info
.shift
);
381 dolog ("Could not allocate buffer (%d bytes)\n",
382 hw
->samples
<< hw
->info
.shift
);
386 if (audio_pt_init (&pa
->pt
, qpa_thread_in
, hw
, AUDIO_CAP
, AUDIO_FUNC
)) {
393 qemu_free (pa
->pcm_buf
);
396 pa_simple_free (pa
->s
);
402 static void qpa_fini_out (HWVoiceOut
*hw
)
405 PAVoiceOut
*pa
= (PAVoiceOut
*) hw
;
407 audio_pt_lock (&pa
->pt
, AUDIO_FUNC
);
409 audio_pt_unlock_and_signal (&pa
->pt
, AUDIO_FUNC
);
410 audio_pt_join (&pa
->pt
, &ret
, AUDIO_FUNC
);
413 pa_simple_free (pa
->s
);
417 audio_pt_fini (&pa
->pt
, AUDIO_FUNC
);
418 qemu_free (pa
->pcm_buf
);
422 static void qpa_fini_in (HWVoiceIn
*hw
)
425 PAVoiceIn
*pa
= (PAVoiceIn
*) hw
;
427 audio_pt_lock (&pa
->pt
, AUDIO_FUNC
);
429 audio_pt_unlock_and_signal (&pa
->pt
, AUDIO_FUNC
);
430 audio_pt_join (&pa
->pt
, &ret
, AUDIO_FUNC
);
433 pa_simple_free (pa
->s
);
437 audio_pt_fini (&pa
->pt
, AUDIO_FUNC
);
438 qemu_free (pa
->pcm_buf
);
442 static int qpa_ctl_out (HWVoiceOut
*hw
, int cmd
, ...)
449 static int qpa_ctl_in (HWVoiceIn
*hw
, int cmd
, ...)
457 static void *qpa_audio_init (void)
462 static void qpa_audio_fini (void *opaque
)
467 struct audio_option qpa_options
[] = {
471 .valp
= &conf
.samples
,
472 .descr
= "buffer size in samples"
477 .valp
= &conf
.divisor
,
478 .descr
= "threshold divisor"
483 .valp
= &conf
.server
,
484 .descr
= "server address"
490 .descr
= "sink device name"
495 .valp
= &conf
.source
,
496 .descr
= "source device name"
498 { /* End of list */ }
501 static struct audio_pcm_ops qpa_pcm_ops
= {
502 .init_out
= qpa_init_out
,
503 .fini_out
= qpa_fini_out
,
504 .run_out
= qpa_run_out
,
506 .ctl_out
= qpa_ctl_out
,
508 .init_in
= qpa_init_in
,
509 .fini_in
= qpa_fini_in
,
510 .run_in
= qpa_run_in
,
515 struct audio_driver pa_audio_driver
= {
517 .descr
= "http://www.pulseaudio.org/",
518 .options
= qpa_options
,
519 .init
= qpa_audio_init
,
520 .fini
= qpa_audio_fini
,
521 .pcm_ops
= &qpa_pcm_ops
,
523 .max_voices_out
= INT_MAX
,
524 .max_voices_in
= INT_MAX
,
525 .voice_size_out
= sizeof (PAVoiceOut
),
526 .voice_size_in
= sizeof (PAVoiceIn
)