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"
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 static void *qpa_thread_out (void *arg)
62 HWVoiceOut *hw = &pa->hw;
65 threshold = conf.divisor ? hw->samples / conf.divisor : 0;
67 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
72 int decr, to_mix, rpos;
79 if (pa->live > threshold) {
83 if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) {
88 decr = to_mix = pa->live;
91 if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
97 int chunk = audio_MIN (to_mix, hw->samples - rpos);
98 struct st_sample *src = hw->mix_buf + rpos;
100 hw->clip (pa->pcm_buf, src, chunk);
102 if (pa_simple_write (pa->s, pa->pcm_buf,
103 chunk << hw->info.shift, &error) < 0) {
104 qpa_logerr (error, "pa_simple_write failed\n");
108 rpos = (rpos + chunk) % hw->samples;
112 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
122 audio_pt_unlock (&pa->pt, AUDIO_FUNC);
126 static int qpa_run_out (HWVoiceOut *hw)
129 PAVoiceOut *pa = (PAVoiceOut *) hw;
131 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
135 live = audio_pcm_hw_get_live_out (hw);
136 decr = audio_MIN (live, pa->decr);
138 pa->live = live - decr;
141 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
144 audio_pt_unlock (&pa->pt, AUDIO_FUNC);
149 static int qpa_write (SWVoiceOut *sw, void *buf, int len)
151 return audio_pcm_sw_write (sw, buf, len);
155 static void *qpa_thread_in (void *arg)
158 HWVoiceIn *hw = &pa->hw;
161 threshold = conf.divisor ? hw->samples / conf.divisor : 0;
163 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
168 int incr, to_grab, wpos;
175 if (pa->dead > threshold) {
179 if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) {
184 incr = to_grab = pa->dead;
187 if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
193 int chunk = audio_MIN (to_grab, hw->samples - wpos);
194 void *buf = advance (pa->pcm_buf, wpos);
196 if (pa_simple_read (pa->s, buf,
197 chunk << hw->info.shift, &error) < 0) {
198 qpa_logerr (error, "pa_simple_read failed\n");
202 hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume);
203 wpos = (wpos + chunk) % hw->samples;
207 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
217 audio_pt_unlock (&pa->pt, AUDIO_FUNC);
221 static int qpa_run_in (HWVoiceIn *hw)
223 int live, incr, dead;
224 PAVoiceIn *pa = (PAVoiceIn *) hw;
226 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
230 live = audio_pcm_hw_get_live_in (hw);
231 dead = hw->samples - live;
232 incr = audio_MIN (dead, pa->incr);
234 pa->dead = dead - incr;
237 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
240 audio_pt_unlock (&pa->pt, AUDIO_FUNC);
245 static int qpa_read (SWVoiceIn *sw, void *buf, int len)
247 return audio_pcm_sw_read (sw, buf, len);
250 static pa_sample_format_t audfmt_to_pa (audfmt_e afmt, int endianness)
257 format = PA_SAMPLE_U8;
261 format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
265 format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
268 dolog ("Internal logic error: Bad audio format %d\n", afmt);
269 format = PA_SAMPLE_U8;
275 static audfmt_e pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
280 case PA_SAMPLE_S16BE:
283 case PA_SAMPLE_S16LE:
286 case PA_SAMPLE_S32BE:
289 case PA_SAMPLE_S32LE:
293 dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt);
298 static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
301 static pa_sample_spec ss;
302 struct audsettings obt_as = *as;
303 PAVoiceOut *pa = (PAVoiceOut *) hw;
305 ss.format = audfmt_to_pa (as->fmt, as->endianness);
306 ss.channels = as->nchannels;
309 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
311 pa->s = pa_simple_new (
318 NULL, /* channel map */
319 NULL, /* buffering attributes */
323 qpa_logerr (error, "pa_simple_new for playback failed\n");
327 audio_pcm_init_info (&hw->info, &obt_as);
328 hw->samples = conf.samples;
329 pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
331 dolog ("Could not allocate buffer (%d bytes)\n",
332 hw->samples << hw->info.shift);
336 if (audio_pt_init (&pa->pt, qpa_thread_out, hw, AUDIO_CAP, AUDIO_FUNC)) {
343 qemu_free (pa->pcm_buf);
346 pa_simple_free (pa->s);
352 static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
355 static pa_sample_spec ss;
356 struct audsettings obt_as = *as;
357 PAVoiceIn *pa = (PAVoiceIn *) hw;
359 ss.format = audfmt_to_pa (as->fmt, as->endianness);
360 ss.channels = as->nchannels;
363 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
365 pa->s = pa_simple_new (
372 NULL, /* channel map */
373 NULL, /* buffering attributes */
377 qpa_logerr (error, "pa_simple_new for capture failed\n");
381 audio_pcm_init_info (&hw->info, &obt_as);
382 hw->samples = conf.samples;
383 pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
385 dolog ("Could not allocate buffer (%d bytes)\n",
386 hw->samples << hw->info.shift);
390 if (audio_pt_init (&pa->pt, qpa_thread_in, hw, AUDIO_CAP, AUDIO_FUNC)) {
397 qemu_free (pa->pcm_buf);
400 pa_simple_free (pa->s);
406 static void qpa_fini_out (HWVoiceOut *hw)
409 PAVoiceOut *pa = (PAVoiceOut *) hw;
411 audio_pt_lock (&pa->pt, AUDIO_FUNC);
413 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
414 audio_pt_join (&pa->pt, &ret, AUDIO_FUNC);
417 pa_simple_free (pa->s);
421 audio_pt_fini (&pa->pt, AUDIO_FUNC);
422 qemu_free (pa->pcm_buf);
426 static void qpa_fini_in (HWVoiceIn *hw)
429 PAVoiceIn *pa = (PAVoiceIn *) hw;
431 audio_pt_lock (&pa->pt, AUDIO_FUNC);
433 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
434 audio_pt_join (&pa->pt, &ret, AUDIO_FUNC);
437 pa_simple_free (pa->s);
441 audio_pt_fini (&pa->pt, AUDIO_FUNC);
442 qemu_free (pa->pcm_buf);
446 static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...)
453 static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
461 static void *qpa_audio_init (void)
466 static void qpa_audio_fini (void *opaque)
471 struct audio_option qpa_options[] = {
472 {"SAMPLES", AUD_OPT_INT, &conf.samples,
473 "buffer size in samples", NULL, 0},
475 {"DIVISOR", AUD_OPT_INT, &conf.divisor,
476 "threshold divisor", NULL, 0},
478 {"SERVER", AUD_OPT_STR, &conf.server,
479 "server address", NULL, 0},
481 {"SINK", AUD_OPT_STR, &conf.sink,
482 "sink device name", NULL, 0},
484 {"SOURCE", AUD_OPT_STR, &conf.source,
485 "source device name", NULL, 0},
487 {NULL, 0, NULL, NULL, NULL, 0}
490 static struct audio_pcm_ops qpa_pcm_ops = {
503 struct audio_driver pa_audio_driver = {
504 INIT_FIELD (name = ) "pa",
505 INIT_FIELD (descr = ) "http://www.pulseaudio.org/",
506 INIT_FIELD (options = ) qpa_options,
507 INIT_FIELD (init = ) qpa_audio_init,
508 INIT_FIELD (fini = ) qpa_audio_fini,
509 INIT_FIELD (pcm_ops = ) &qpa_pcm_ops,
510 INIT_FIELD (can_be_default = ) 0,
511 INIT_FIELD (max_voices_out = ) INT_MAX,
512 INIT_FIELD (max_voices_in = ) INT_MAX,
513 INIT_FIELD (voice_size_out = ) sizeof (PAVoiceOut),
514 INIT_FIELD (voice_size_in = ) sizeof (PAVoiceIn)