1 /* public domain */
2 #include "qemu-common.h"
3 #include "audio.h"
4
5 #include <pulse/simple.h>
6 #include <pulse/error.h>
7 #include <dlfcn.h>
8
9 #define AUDIO_CAP "pulseaudio"
10 #include "audio_int.h"
11 #include "audio_pt_int.h"
12
13 #define DEBUG 1
14
15 #if DEBUG
16 # include "qemu_debug.h"
17 # include <stdio.h>
18 # define D(...) VERBOSE_PRINT(audio,__VA_ARGS__)
19 # define D_ACTIVE VERBOSE_CHECK(audio)
20 # define O(...) VERBOSE_PRINT(audioout,__VA_ARGS__)
21 # define I(...) VERBOSE_PRINT(audioin,__VA_ARGS__)
22 #else
23 # define D(...) ((void)0)
24 # define D_ACTIVE 0
25 # define O(...) ((void)0)
26 # define I(...) ((void)0)
27 #endif
28
29 #define DYNLINK_FUNCTIONS \
30 DYNLINK_FUNC(pa_simple*,pa_simple_new,(const char* server,const char* name, pa_stream_direction_t dir, const char* dev, const char* stream_name, const pa_sample_spec* ss, const pa_channel_map* map, const pa_buffer_attr *attr, int *error)) \
31 DYNLINK_FUNC(void,pa_simple_free,(pa_simple* s))\
32 DYNLINK_FUNC(int,pa_simple_write,(pa_simple* s, const void* data, size_t bytes, int* error))\
33 DYNLINK_FUNC(int,pa_simple_read,(pa_simple* s,void* data, size_t bytes, int* error))\
34 DYNLINK_FUNC(const char*,pa_strerror,(int error))\
35
36 #define DYNLINK_FUNCTIONS_INIT \
37 pa_dynlink_init
38
39 static void* pa_lib;
40
41 #include "dynlink.h"
42
43 typedef struct {
44 HWVoiceOut hw;
45 int done;
46 int live;
47 int decr;
48 int rpos;
49 pa_simple *s;
50 void *pcm_buf;
51 struct audio_pt pt;
52 } PAVoiceOut;
53
54 typedef struct {
55 HWVoiceIn hw;
56 int done;
57 int dead;
58 int incr;
59 int wpos;
60 pa_simple *s;
61 void *pcm_buf;
62 struct audio_pt pt;
63 } PAVoiceIn;
64
65 static struct {
66 int samples;
67 int divisor;
68 char *server;
69 char *sink;
70 char *source;
71 } conf = {
72 .samples = 1024,
73 .divisor = 2,
74 };
75
qpa_logerr(int err,const char * fmt,...)76 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
77 {
78 va_list ap;
79
80 va_start (ap, fmt);
81 AUD_vlog (AUDIO_CAP, fmt, ap);
82 va_end (ap);
83
84 AUD_log (AUDIO_CAP, "Reason: %s\n", FF(pa_strerror) (err));
85 }
86
qpa_thread_out(void * arg)87 static void *qpa_thread_out (void *arg)
88 {
89 PAVoiceOut *pa = arg;
90 HWVoiceOut *hw = &pa->hw;
91 int threshold;
92
93 threshold = conf.divisor ? hw->samples / conf.divisor : 0;
94
95 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
96 return NULL;
97 }
98
99 for (;;) {
100 int decr, to_mix, rpos;
101
102 for (;;) {
103 if (pa->done) {
104 goto exit;
105 }
106
107 if (pa->live > threshold) {
108 break;
109 }
110
111 if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) {
112 goto exit;
113 }
114 }
115
116 decr = to_mix = pa->live;
117 rpos = hw->rpos;
118
119 if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
120 return NULL;
121 }
122
123 while (to_mix) {
124 int error;
125 int chunk = audio_MIN (to_mix, hw->samples - rpos);
126 struct st_sample *src = hw->mix_buf + rpos;
127
128 hw->clip (pa->pcm_buf, src, chunk);
129
130 if (FF(pa_simple_write) (pa->s, pa->pcm_buf,
131 chunk << hw->info.shift, &error) < 0) {
132 qpa_logerr (error, "pa_simple_write failed\n");
133 return NULL;
134 }
135
136 rpos = (rpos + chunk) % hw->samples;
137 to_mix -= chunk;
138 }
139
140 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
141 return NULL;
142 }
143
144 pa->rpos = rpos;
145 pa->live -= decr;
146 pa->decr += decr;
147 }
148
149 exit:
150 audio_pt_unlock (&pa->pt, AUDIO_FUNC);
151 return NULL;
152 }
153
qpa_run_out(HWVoiceOut * hw,int live)154 static int qpa_run_out (HWVoiceOut *hw, int live)
155 {
156 int decr;
157 PAVoiceOut *pa = (PAVoiceOut *) hw;
158
159 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
160 return 0;
161 }
162
163 decr = audio_MIN (live, pa->decr);
164 pa->decr -= decr;
165 pa->live = live - decr;
166 hw->rpos = pa->rpos;
167 if (pa->live > 0) {
168 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
169 }
170 else {
171 audio_pt_unlock (&pa->pt, AUDIO_FUNC);
172 }
173 return decr;
174 }
175
qpa_write(SWVoiceOut * sw,void * buf,int len)176 static int qpa_write (SWVoiceOut *sw, void *buf, int len)
177 {
178 return audio_pcm_sw_write (sw, buf, len);
179 }
180
181 /* capture */
qpa_thread_in(void * arg)182 static void *qpa_thread_in (void *arg)
183 {
184 PAVoiceIn *pa = arg;
185 HWVoiceIn *hw = &pa->hw;
186 int threshold;
187
188 threshold = conf.divisor ? hw->samples / conf.divisor : 0;
189
190 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
191 return NULL;
192 }
193
194 for (;;) {
195 int incr, to_grab, wpos;
196
197 for (;;) {
198 if (pa->done) {
199 goto exit;
200 }
201
202 if (pa->dead > threshold) {
203 break;
204 }
205
206 if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) {
207 goto exit;
208 }
209 }
210
211 incr = to_grab = pa->dead;
212 wpos = hw->wpos;
213
214 if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
215 return NULL;
216 }
217
218 while (to_grab) {
219 int error;
220 int chunk = audio_MIN (to_grab, hw->samples - wpos);
221 void *buf = advance (pa->pcm_buf, wpos);
222
223 if (FF(pa_simple_read) (pa->s, buf,
224 chunk << hw->info.shift, &error) < 0) {
225 qpa_logerr (error, "pa_simple_read failed\n");
226 return NULL;
227 }
228
229 hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume);
230 wpos = (wpos + chunk) % hw->samples;
231 to_grab -= chunk;
232 }
233
234 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
235 return NULL;
236 }
237
238 pa->wpos = wpos;
239 pa->dead -= incr;
240 pa->incr += incr;
241 }
242
243 exit:
244 audio_pt_unlock (&pa->pt, AUDIO_FUNC);
245 return NULL;
246 }
247
qpa_run_in(HWVoiceIn * hw)248 static int qpa_run_in (HWVoiceIn *hw)
249 {
250 int live, incr, dead;
251 PAVoiceIn *pa = (PAVoiceIn *) hw;
252
253 if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
254 return 0;
255 }
256
257 live = audio_pcm_hw_get_live_in (hw);
258 dead = hw->samples - live;
259 incr = audio_MIN (dead, pa->incr);
260 pa->incr -= incr;
261 pa->dead = dead - incr;
262 hw->wpos = pa->wpos;
263 if (pa->dead > 0) {
264 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
265 }
266 else {
267 audio_pt_unlock (&pa->pt, AUDIO_FUNC);
268 }
269 return incr;
270 }
271
qpa_read(SWVoiceIn * sw,void * buf,int len)272 static int qpa_read (SWVoiceIn *sw, void *buf, int len)
273 {
274 return audio_pcm_sw_read (sw, buf, len);
275 }
276
audfmt_to_pa(audfmt_e afmt,int endianness)277 static pa_sample_format_t audfmt_to_pa (audfmt_e afmt, int endianness)
278 {
279 int format;
280
281 switch (afmt) {
282 case AUD_FMT_S8:
283 case AUD_FMT_U8:
284 format = PA_SAMPLE_U8;
285 break;
286 case AUD_FMT_S16:
287 case AUD_FMT_U16:
288 format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
289 break;
290 case AUD_FMT_S32:
291 case AUD_FMT_U32:
292 format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
293 break;
294 default:
295 dolog ("Internal logic error: Bad audio format %d\n", afmt);
296 format = PA_SAMPLE_U8;
297 break;
298 }
299 return format;
300 }
301
pa_to_audfmt(pa_sample_format_t fmt,int * endianness)302 static audfmt_e pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
303 {
304 switch (fmt) {
305 case PA_SAMPLE_U8:
306 return AUD_FMT_U8;
307 case PA_SAMPLE_S16BE:
308 *endianness = 1;
309 return AUD_FMT_S16;
310 case PA_SAMPLE_S16LE:
311 *endianness = 0;
312 return AUD_FMT_S16;
313 case PA_SAMPLE_S32BE:
314 *endianness = 1;
315 return AUD_FMT_S32;
316 case PA_SAMPLE_S32LE:
317 *endianness = 0;
318 return AUD_FMT_S32;
319 default:
320 dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt);
321 return AUD_FMT_U8;
322 }
323 }
324
qpa_init_out(HWVoiceOut * hw,struct audsettings * as)325 static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
326 {
327 int error;
328 static pa_sample_spec ss;
329 struct audsettings obt_as = *as;
330 PAVoiceOut *pa = (PAVoiceOut *) hw;
331
332 ss.format = audfmt_to_pa (as->fmt, as->endianness);
333 ss.channels = as->nchannels;
334 ss.rate = as->freq;
335
336 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
337
338 pa->s = FF(pa_simple_new) (
339 conf.server,
340 "qemu",
341 PA_STREAM_PLAYBACK,
342 conf.sink,
343 "pcm.playback",
344 &ss,
345 NULL, /* channel map */
346 NULL, /* buffering attributes */
347 &error
348 );
349 if (!pa->s) {
350 qpa_logerr (error, "pa_simple_new for playback failed\n");
351 goto fail1;
352 }
353
354 audio_pcm_init_info (&hw->info, &obt_as);
355 hw->samples = conf.samples;
356 pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
357 if (!pa->pcm_buf) {
358 dolog ("Could not allocate buffer (%d bytes)\n",
359 hw->samples << hw->info.shift);
360 goto fail2;
361 }
362
363 if (audio_pt_init (&pa->pt, qpa_thread_out, hw, AUDIO_CAP, AUDIO_FUNC)) {
364 goto fail3;
365 }
366
367 return 0;
368
369 fail3:
370 qemu_free (pa->pcm_buf);
371 pa->pcm_buf = NULL;
372 fail2:
373 FF(pa_simple_free) (pa->s);
374 pa->s = NULL;
375 fail1:
376 return -1;
377 }
378
qpa_init_in(HWVoiceIn * hw,struct audsettings * as)379 static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
380 {
381 int error;
382 static pa_sample_spec ss;
383 struct audsettings obt_as = *as;
384 PAVoiceIn *pa = (PAVoiceIn *) hw;
385
386 ss.format = audfmt_to_pa (as->fmt, as->endianness);
387 ss.channels = as->nchannels;
388 ss.rate = as->freq;
389
390 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
391
392 pa->s = FF(pa_simple_new) (
393 conf.server,
394 "qemu",
395 PA_STREAM_RECORD,
396 conf.source,
397 "pcm.capture",
398 &ss,
399 NULL, /* channel map */
400 NULL, /* buffering attributes */
401 &error
402 );
403 if (!pa->s) {
404 qpa_logerr (error, "pa_simple_new for capture failed\n");
405 goto fail1;
406 }
407
408 audio_pcm_init_info (&hw->info, &obt_as);
409 hw->samples = conf.samples;
410 pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
411 if (!pa->pcm_buf) {
412 dolog ("Could not allocate buffer (%d bytes)\n",
413 hw->samples << hw->info.shift);
414 goto fail2;
415 }
416
417 if (audio_pt_init (&pa->pt, qpa_thread_in, hw, AUDIO_CAP, AUDIO_FUNC)) {
418 goto fail3;
419 }
420
421 return 0;
422
423 fail3:
424 qemu_free (pa->pcm_buf);
425 pa->pcm_buf = NULL;
426 fail2:
427 FF(pa_simple_free) (pa->s);
428 pa->s = NULL;
429 fail1:
430 return -1;
431 }
432
qpa_fini_out(HWVoiceOut * hw)433 static void qpa_fini_out (HWVoiceOut *hw)
434 {
435 void *ret;
436 PAVoiceOut *pa = (PAVoiceOut *) hw;
437
438 audio_pt_lock (&pa->pt, AUDIO_FUNC);
439 pa->done = 1;
440 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
441 audio_pt_join (&pa->pt, &ret, AUDIO_FUNC);
442
443 if (pa->s) {
444 FF(pa_simple_free) (pa->s);
445 pa->s = NULL;
446 }
447
448 audio_pt_fini (&pa->pt, AUDIO_FUNC);
449 qemu_free (pa->pcm_buf);
450 pa->pcm_buf = NULL;
451 }
452
qpa_fini_in(HWVoiceIn * hw)453 static void qpa_fini_in (HWVoiceIn *hw)
454 {
455 void *ret;
456 PAVoiceIn *pa = (PAVoiceIn *) hw;
457
458 audio_pt_lock (&pa->pt, AUDIO_FUNC);
459 pa->done = 1;
460 audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
461 audio_pt_join (&pa->pt, &ret, AUDIO_FUNC);
462
463 if (pa->s) {
464 FF(pa_simple_free) (pa->s);
465 pa->s = NULL;
466 }
467
468 audio_pt_fini (&pa->pt, AUDIO_FUNC);
469 qemu_free (pa->pcm_buf);
470 pa->pcm_buf = NULL;
471 }
472
qpa_ctl_out(HWVoiceOut * hw,int cmd,...)473 static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...)
474 {
475 (void) hw;
476 (void) cmd;
477 return 0;
478 }
479
qpa_ctl_in(HWVoiceIn * hw,int cmd,...)480 static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
481 {
482 (void) hw;
483 (void) cmd;
484 return 0;
485 }
486
487 /* common */
qpa_audio_init(void)488 static void *qpa_audio_init (void)
489 {
490 void* result = NULL;
491
492 D("%s: entering", __FUNCTION__);
493 pa_lib = dlopen( "libpulse-simple.so", RTLD_NOW );
494 if (pa_lib == NULL)
495 pa_lib = dlopen( "libpulse-simple.so.0", RTLD_NOW );
496
497 if (pa_lib == NULL) {
498 D("could not find libpulse on this system\n");
499 goto Exit;
500 }
501
502 if (pa_dynlink_init(pa_lib) < 0)
503 goto Fail;
504
505 {
506 pa_sample_spec ss;
507 int error;
508 pa_simple* simple;
509
510 ss.format = PA_SAMPLE_U8;
511 ss.rate = 44100;
512 ss.channels = 1;
513
514 /* try to open it for playback */
515 simple = FF(pa_simple_new) (
516 conf.server,
517 "qemu",
518 PA_STREAM_PLAYBACK,
519 conf.sink,
520 "pcm.playback",
521 &ss,
522 NULL, /* channel map */
523 NULL, /* buffering attributes */
524 &error
525 );
526
527 if (simple == NULL) {
528 D("%s: error opening open pulse audio library: %s",
529 __FUNCTION__, FF(pa_strerror)(error));
530 goto Fail;
531 }
532 FF(pa_simple_free)(simple);
533 }
534
535 result = &conf;
536 goto Exit;
537
538 Fail:
539 D("%s: failed to open library\n", __FUNCTION__);
540 dlclose(pa_lib);
541
542 Exit:
543 D("%s: exiting", __FUNCTION__);
544 return result;
545 }
546
qpa_audio_fini(void * opaque)547 static void qpa_audio_fini (void *opaque)
548 {
549 if (pa_lib != NULL) {
550 dlclose(pa_lib);
551 pa_lib = NULL;
552 }
553 (void) opaque;
554 (void) opaque;
555 }
556
557 struct audio_option qpa_options[] = {
558 {
559 .name = "SAMPLES",
560 .tag = AUD_OPT_INT,
561 .valp = &conf.samples,
562 .descr = "buffer size in samples"
563 },
564 {
565 .name = "DIVISOR",
566 .tag = AUD_OPT_INT,
567 .valp = &conf.divisor,
568 .descr = "threshold divisor"
569 },
570 {
571 .name = "SERVER",
572 .tag = AUD_OPT_STR,
573 .valp = &conf.server,
574 .descr = "server address"
575 },
576 {
577 .name = "SINK",
578 .tag = AUD_OPT_STR,
579 .valp = &conf.sink,
580 .descr = "sink device name"
581 },
582 {
583 .name = "SOURCE",
584 .tag = AUD_OPT_STR,
585 .valp = &conf.source,
586 .descr = "source device name"
587 },
588 { /* End of list */ }
589 };
590
591 static struct audio_pcm_ops qpa_pcm_ops = {
592 .init_out = qpa_init_out,
593 .fini_out = qpa_fini_out,
594 .run_out = qpa_run_out,
595 .write = qpa_write,
596 .ctl_out = qpa_ctl_out,
597
598 .init_in = qpa_init_in,
599 .fini_in = qpa_fini_in,
600 .run_in = qpa_run_in,
601 .read = qpa_read,
602 .ctl_in = qpa_ctl_in
603 };
604
605 struct audio_driver pa_audio_driver = {
606 .name = "pa",
607 .descr = "http://www.pulseaudio.org/",
608 .options = qpa_options,
609 .init = qpa_audio_init,
610 .fini = qpa_audio_fini,
611 .pcm_ops = &qpa_pcm_ops,
612 .can_be_default = 1,
613 .max_voices_out = INT_MAX,
614 .max_voices_in = INT_MAX,
615 .voice_size_out = sizeof (PAVoiceOut),
616 .voice_size_in = sizeof (PAVoiceIn)
617 };
618