Commit b8e59f18de9ebd0286e14ff42db217b34d4f8272
1 parent
923e4521
Pulseaudio driver
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4827 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
532 additions
and
1 deletions
Makefile
@@ -98,6 +98,11 @@ AUDIO_PT = yes | @@ -98,6 +98,11 @@ AUDIO_PT = yes | ||
98 | AUDIO_PT_INT = yes | 98 | AUDIO_PT_INT = yes |
99 | AUDIO_OBJS += esdaudio.o | 99 | AUDIO_OBJS += esdaudio.o |
100 | endif | 100 | endif |
101 | +ifdef CONFIG_PA | ||
102 | +AUDIO_PT = yes | ||
103 | +AUDIO_PT_INT = yes | ||
104 | +AUDIO_OBJS += paaudio.o | ||
105 | +endif | ||
101 | ifdef AUDIO_PT | 106 | ifdef AUDIO_PT |
102 | LDFLAGS += -pthread | 107 | LDFLAGS += -pthread |
103 | endif | 108 | endif |
Makefile.target
@@ -270,6 +270,7 @@ libqemu.a: $(LIBOBJS) | @@ -270,6 +270,7 @@ libqemu.a: $(LIBOBJS) | ||
270 | $(AR) rcs $@ $(LIBOBJS) | 270 | $(AR) rcs $@ $(LIBOBJS) |
271 | 271 | ||
272 | translate.o: translate.c cpu.h $(OPC_H) | 272 | translate.o: translate.c cpu.h $(OPC_H) |
273 | +translate.o: CFLAGS:=${CFLAGS} -O1 #-fno-unit-at-a-time | ||
273 | 274 | ||
274 | translate-all.o: translate-all.c cpu.h $(OPC_H) | 275 | translate-all.o: translate-all.c cpu.h $(OPC_H) |
275 | 276 | ||
@@ -480,6 +481,9 @@ endif | @@ -480,6 +481,9 @@ endif | ||
480 | ifdef CONFIG_ESD | 481 | ifdef CONFIG_ESD |
481 | LIBS += -lesd | 482 | LIBS += -lesd |
482 | endif | 483 | endif |
484 | +ifdef CONFIG_PA | ||
485 | +LIBS += -lpulse-simple | ||
486 | +endif | ||
483 | ifdef CONFIG_DSOUND | 487 | ifdef CONFIG_DSOUND |
484 | LIBS += -lole32 -ldxguid | 488 | LIBS += -lole32 -ldxguid |
485 | endif | 489 | endif |
audio/audio_int.h
@@ -203,6 +203,7 @@ extern struct audio_driver alsa_audio_driver; | @@ -203,6 +203,7 @@ extern struct audio_driver alsa_audio_driver; | ||
203 | extern struct audio_driver coreaudio_audio_driver; | 203 | extern struct audio_driver coreaudio_audio_driver; |
204 | extern struct audio_driver dsound_audio_driver; | 204 | extern struct audio_driver dsound_audio_driver; |
205 | extern struct audio_driver esd_audio_driver; | 205 | extern struct audio_driver esd_audio_driver; |
206 | +extern struct audio_driver pa_audio_driver; | ||
206 | extern volume_t nominal_volume; | 207 | extern volume_t nominal_volume; |
207 | 208 | ||
208 | void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as); | 209 | void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as); |
audio/paaudio.c
0 → 100644
1 | +/* public domain */ | ||
2 | +#include "qemu-common.h" | ||
3 | +#include "audio.h" | ||
4 | + | ||
5 | +#include <pulse/simple.h> | ||
6 | +#include <pulse/error.h> | ||
7 | + | ||
8 | +#define AUDIO_CAP "pulseaudio" | ||
9 | +#include "audio_int.h" | ||
10 | +#include "audio_pt_int.h" | ||
11 | + | ||
12 | +typedef struct { | ||
13 | + HWVoiceOut hw; | ||
14 | + int done; | ||
15 | + int live; | ||
16 | + int decr; | ||
17 | + int rpos; | ||
18 | + pa_simple *s; | ||
19 | + void *pcm_buf; | ||
20 | + struct audio_pt pt; | ||
21 | +} PAVoiceOut; | ||
22 | + | ||
23 | +typedef struct { | ||
24 | + HWVoiceIn hw; | ||
25 | + int done; | ||
26 | + int dead; | ||
27 | + int incr; | ||
28 | + int wpos; | ||
29 | + pa_simple *s; | ||
30 | + void *pcm_buf; | ||
31 | + struct audio_pt pt; | ||
32 | +} PAVoiceIn; | ||
33 | + | ||
34 | +static struct { | ||
35 | + int samples; | ||
36 | + int divisor; | ||
37 | + char *server; | ||
38 | + char *sink; | ||
39 | + char *source; | ||
40 | +} conf = { | ||
41 | + 1024, | ||
42 | + 2, | ||
43 | + NULL, | ||
44 | + NULL, | ||
45 | + NULL | ||
46 | +}; | ||
47 | + | ||
48 | +static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...) | ||
49 | +{ | ||
50 | + va_list ap; | ||
51 | + | ||
52 | + va_start (ap, fmt); | ||
53 | + AUD_vlog (AUDIO_CAP, fmt, ap); | ||
54 | + va_end (ap); | ||
55 | + | ||
56 | + AUD_log (AUDIO_CAP, "Reason: %s\n", pa_strerror (err)); | ||
57 | +} | ||
58 | + | ||
59 | +static void *qpa_thread_out (void *arg) | ||
60 | +{ | ||
61 | + PAVoiceOut *pa = arg; | ||
62 | + HWVoiceOut *hw = &pa->hw; | ||
63 | + int threshold; | ||
64 | + | ||
65 | + threshold = conf.divisor ? hw->samples / conf.divisor : 0; | ||
66 | + | ||
67 | + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { | ||
68 | + return NULL; | ||
69 | + } | ||
70 | + | ||
71 | + for (;;) { | ||
72 | + int decr, to_mix, rpos; | ||
73 | + | ||
74 | + for (;;) { | ||
75 | + if (pa->done) { | ||
76 | + goto exit; | ||
77 | + } | ||
78 | + | ||
79 | + if (pa->live > threshold) { | ||
80 | + break; | ||
81 | + } | ||
82 | + | ||
83 | + if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) { | ||
84 | + goto exit; | ||
85 | + } | ||
86 | + } | ||
87 | + | ||
88 | + decr = to_mix = pa->live; | ||
89 | + rpos = hw->rpos; | ||
90 | + | ||
91 | + if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { | ||
92 | + return NULL; | ||
93 | + } | ||
94 | + | ||
95 | + while (to_mix) { | ||
96 | + int error; | ||
97 | + int chunk = audio_MIN (to_mix, hw->samples - rpos); | ||
98 | + st_sample_t *src = hw->mix_buf + rpos; | ||
99 | + | ||
100 | + hw->clip (pa->pcm_buf, src, chunk); | ||
101 | + | ||
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"); | ||
105 | + return NULL; | ||
106 | + } | ||
107 | + | ||
108 | + rpos = (rpos + chunk) % hw->samples; | ||
109 | + to_mix -= chunk; | ||
110 | + } | ||
111 | + | ||
112 | + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { | ||
113 | + return NULL; | ||
114 | + } | ||
115 | + | ||
116 | + pa->rpos = rpos; | ||
117 | + pa->live -= decr; | ||
118 | + pa->decr += decr; | ||
119 | + } | ||
120 | + | ||
121 | + exit: | ||
122 | + audio_pt_unlock (&pa->pt, AUDIO_FUNC); | ||
123 | + return NULL; | ||
124 | +} | ||
125 | + | ||
126 | +static int qpa_run_out (HWVoiceOut *hw) | ||
127 | +{ | ||
128 | + int live, decr; | ||
129 | + PAVoiceOut *pa = (PAVoiceOut *) hw; | ||
130 | + | ||
131 | + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { | ||
132 | + return 0; | ||
133 | + } | ||
134 | + | ||
135 | + live = audio_pcm_hw_get_live_out (hw); | ||
136 | + decr = audio_MIN (live, pa->decr); | ||
137 | + pa->decr -= decr; | ||
138 | + pa->live = live - decr; | ||
139 | + hw->rpos = pa->rpos; | ||
140 | + if (pa->live > 0) { | ||
141 | + audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); | ||
142 | + } | ||
143 | + else { | ||
144 | + audio_pt_unlock (&pa->pt, AUDIO_FUNC); | ||
145 | + } | ||
146 | + return decr; | ||
147 | +} | ||
148 | + | ||
149 | +static int qpa_write (SWVoiceOut *sw, void *buf, int len) | ||
150 | +{ | ||
151 | + return audio_pcm_sw_write (sw, buf, len); | ||
152 | +} | ||
153 | + | ||
154 | +/* capture */ | ||
155 | +static void *qpa_thread_in (void *arg) | ||
156 | +{ | ||
157 | + PAVoiceIn *pa = arg; | ||
158 | + HWVoiceIn *hw = &pa->hw; | ||
159 | + int threshold; | ||
160 | + | ||
161 | + threshold = conf.divisor ? hw->samples / conf.divisor : 0; | ||
162 | + | ||
163 | + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { | ||
164 | + return NULL; | ||
165 | + } | ||
166 | + | ||
167 | + for (;;) { | ||
168 | + int incr, to_grab, wpos; | ||
169 | + | ||
170 | + for (;;) { | ||
171 | + if (pa->done) { | ||
172 | + goto exit; | ||
173 | + } | ||
174 | + | ||
175 | + if (pa->dead > threshold) { | ||
176 | + break; | ||
177 | + } | ||
178 | + | ||
179 | + if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) { | ||
180 | + goto exit; | ||
181 | + } | ||
182 | + } | ||
183 | + | ||
184 | + incr = to_grab = pa->dead; | ||
185 | + wpos = hw->wpos; | ||
186 | + | ||
187 | + if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { | ||
188 | + return NULL; | ||
189 | + } | ||
190 | + | ||
191 | + while (to_grab) { | ||
192 | + int error; | ||
193 | + int chunk = audio_MIN (to_grab, hw->samples - wpos); | ||
194 | + void *buf = advance (pa->pcm_buf, wpos); | ||
195 | + | ||
196 | + if (pa_simple_read (pa->s, buf, | ||
197 | + chunk << hw->info.shift, &error) < 0) { | ||
198 | + qpa_logerr (error, "pa_simple_read failed\n"); | ||
199 | + return NULL; | ||
200 | + } | ||
201 | + | ||
202 | + hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume); | ||
203 | + wpos = (wpos + chunk) % hw->samples; | ||
204 | + to_grab -= chunk; | ||
205 | + } | ||
206 | + | ||
207 | + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { | ||
208 | + return NULL; | ||
209 | + } | ||
210 | + | ||
211 | + pa->wpos = wpos; | ||
212 | + pa->dead -= incr; | ||
213 | + pa->incr += incr; | ||
214 | + } | ||
215 | + | ||
216 | + exit: | ||
217 | + audio_pt_unlock (&pa->pt, AUDIO_FUNC); | ||
218 | + return NULL; | ||
219 | +} | ||
220 | + | ||
221 | +static int qpa_run_in (HWVoiceIn *hw) | ||
222 | +{ | ||
223 | + int live, incr, dead; | ||
224 | + PAVoiceIn *pa = (PAVoiceIn *) hw; | ||
225 | + | ||
226 | + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { | ||
227 | + return 0; | ||
228 | + } | ||
229 | + | ||
230 | + live = audio_pcm_hw_get_live_in (hw); | ||
231 | + dead = hw->samples - live; | ||
232 | + incr = audio_MIN (dead, pa->incr); | ||
233 | + pa->incr -= incr; | ||
234 | + pa->dead = dead - incr; | ||
235 | + hw->wpos = pa->wpos; | ||
236 | + if (pa->dead > 0) { | ||
237 | + audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); | ||
238 | + } | ||
239 | + else { | ||
240 | + audio_pt_unlock (&pa->pt, AUDIO_FUNC); | ||
241 | + } | ||
242 | + return incr; | ||
243 | +} | ||
244 | + | ||
245 | +static int qpa_read (SWVoiceIn *sw, void *buf, int len) | ||
246 | +{ | ||
247 | + return audio_pcm_sw_read (sw, buf, len); | ||
248 | +} | ||
249 | + | ||
250 | +static pa_sample_format_t audfmt_to_pa (audfmt_e afmt, int endianness) | ||
251 | +{ | ||
252 | + int format; | ||
253 | + | ||
254 | + switch (afmt) { | ||
255 | + case AUD_FMT_S8: | ||
256 | + case AUD_FMT_U8: | ||
257 | + format = PA_SAMPLE_U8; | ||
258 | + break; | ||
259 | + case AUD_FMT_S16: | ||
260 | + case AUD_FMT_U16: | ||
261 | + format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; | ||
262 | + break; | ||
263 | + case AUD_FMT_S32: | ||
264 | + case AUD_FMT_U32: | ||
265 | + format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; | ||
266 | + break; | ||
267 | + default: | ||
268 | + dolog ("Internal logic error: Bad audio format %d\n", afmt); | ||
269 | + format = PA_SAMPLE_U8; | ||
270 | + break; | ||
271 | + } | ||
272 | + return format; | ||
273 | +} | ||
274 | + | ||
275 | +static audfmt_e pa_to_audfmt (pa_sample_format_t fmt, int *endianness) | ||
276 | +{ | ||
277 | + switch (fmt) { | ||
278 | + case PA_SAMPLE_U8: | ||
279 | + return AUD_FMT_U8; | ||
280 | + case PA_SAMPLE_S16BE: | ||
281 | + *endianness = 1; | ||
282 | + return AUD_FMT_S16; | ||
283 | + case PA_SAMPLE_S16LE: | ||
284 | + *endianness = 0; | ||
285 | + return AUD_FMT_S16; | ||
286 | + case PA_SAMPLE_S32BE: | ||
287 | + *endianness = 1; | ||
288 | + return AUD_FMT_S32; | ||
289 | + case PA_SAMPLE_S32LE: | ||
290 | + *endianness = 0; | ||
291 | + return AUD_FMT_S32; | ||
292 | + default: | ||
293 | + dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt); | ||
294 | + return AUD_FMT_U8; | ||
295 | + } | ||
296 | +} | ||
297 | + | ||
298 | +static int qpa_init_out (HWVoiceOut *hw, audsettings_t *as) | ||
299 | +{ | ||
300 | + int error; | ||
301 | + static pa_sample_spec ss; | ||
302 | + audsettings_t obt_as = *as; | ||
303 | + PAVoiceOut *pa = (PAVoiceOut *) hw; | ||
304 | + | ||
305 | + ss.format = audfmt_to_pa (as->fmt, as->endianness); | ||
306 | + ss.channels = as->nchannels; | ||
307 | + ss.rate = as->freq; | ||
308 | + | ||
309 | + obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); | ||
310 | + | ||
311 | + pa->s = pa_simple_new ( | ||
312 | + conf.server, | ||
313 | + "qemu", | ||
314 | + PA_STREAM_PLAYBACK, | ||
315 | + conf.sink, | ||
316 | + "pcm.playback", | ||
317 | + &ss, | ||
318 | + NULL, /* channel map */ | ||
319 | + NULL, /* buffering attributes */ | ||
320 | + &error | ||
321 | + ); | ||
322 | + if (!pa->s) { | ||
323 | + qpa_logerr (error, "pa_simple_new for playback failed\n"); | ||
324 | + goto fail1; | ||
325 | + } | ||
326 | + | ||
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); | ||
330 | + if (!pa->pcm_buf) { | ||
331 | + dolog ("Could not allocate buffer (%d bytes)\n", | ||
332 | + hw->samples << hw->info.shift); | ||
333 | + goto fail2; | ||
334 | + } | ||
335 | + | ||
336 | + if (audio_pt_init (&pa->pt, qpa_thread_out, hw, AUDIO_CAP, AUDIO_FUNC)) { | ||
337 | + goto fail3; | ||
338 | + } | ||
339 | + | ||
340 | + return 0; | ||
341 | + | ||
342 | + fail3: | ||
343 | + free (pa->pcm_buf); | ||
344 | + pa->pcm_buf = NULL; | ||
345 | + fail2: | ||
346 | + pa_simple_free (pa->s); | ||
347 | + pa->s = NULL; | ||
348 | + fail1: | ||
349 | + return -1; | ||
350 | +} | ||
351 | + | ||
352 | +static int qpa_init_in (HWVoiceIn *hw, audsettings_t *as) | ||
353 | +{ | ||
354 | + int error; | ||
355 | + static pa_sample_spec ss; | ||
356 | + audsettings_t obt_as = *as; | ||
357 | + PAVoiceIn *pa = (PAVoiceIn *) hw; | ||
358 | + | ||
359 | + ss.format = audfmt_to_pa (as->fmt, as->endianness); | ||
360 | + ss.channels = as->nchannels; | ||
361 | + ss.rate = as->freq; | ||
362 | + | ||
363 | + obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); | ||
364 | + | ||
365 | + pa->s = pa_simple_new ( | ||
366 | + conf.server, | ||
367 | + "qemu", | ||
368 | + PA_STREAM_RECORD, | ||
369 | + conf.source, | ||
370 | + "pcm.capture", | ||
371 | + &ss, | ||
372 | + NULL, /* channel map */ | ||
373 | + NULL, /* buffering attributes */ | ||
374 | + &error | ||
375 | + ); | ||
376 | + if (!pa->s) { | ||
377 | + qpa_logerr (error, "pa_simple_new for capture failed\n"); | ||
378 | + goto fail1; | ||
379 | + } | ||
380 | + | ||
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); | ||
384 | + if (!pa->pcm_buf) { | ||
385 | + dolog ("Could not allocate buffer (%d bytes)\n", | ||
386 | + hw->samples << hw->info.shift); | ||
387 | + goto fail2; | ||
388 | + } | ||
389 | + | ||
390 | + if (audio_pt_init (&pa->pt, qpa_thread_in, hw, AUDIO_CAP, AUDIO_FUNC)) { | ||
391 | + goto fail3; | ||
392 | + } | ||
393 | + | ||
394 | + return 0; | ||
395 | + | ||
396 | + fail3: | ||
397 | + free (pa->pcm_buf); | ||
398 | + pa->pcm_buf = NULL; | ||
399 | + fail2: | ||
400 | + pa_simple_free (pa->s); | ||
401 | + pa->s = NULL; | ||
402 | + fail1: | ||
403 | + return -1; | ||
404 | +} | ||
405 | + | ||
406 | +static void qpa_fini_out (HWVoiceOut *hw) | ||
407 | +{ | ||
408 | + void *ret; | ||
409 | + PAVoiceOut *pa = (PAVoiceOut *) hw; | ||
410 | + | ||
411 | + audio_pt_lock (&pa->pt, AUDIO_FUNC); | ||
412 | + pa->done = 1; | ||
413 | + audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); | ||
414 | + audio_pt_join (&pa->pt, &ret, AUDIO_FUNC); | ||
415 | + | ||
416 | + if (pa->s) { | ||
417 | + pa_simple_free (pa->s); | ||
418 | + pa->s = NULL; | ||
419 | + } | ||
420 | + | ||
421 | + audio_pt_fini (&pa->pt, AUDIO_FUNC); | ||
422 | + qemu_free (pa->pcm_buf); | ||
423 | + pa->pcm_buf = NULL; | ||
424 | +} | ||
425 | + | ||
426 | +static void qpa_fini_in (HWVoiceIn *hw) | ||
427 | +{ | ||
428 | + void *ret; | ||
429 | + PAVoiceIn *pa = (PAVoiceIn *) hw; | ||
430 | + | ||
431 | + audio_pt_lock (&pa->pt, AUDIO_FUNC); | ||
432 | + pa->done = 1; | ||
433 | + audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); | ||
434 | + audio_pt_join (&pa->pt, &ret, AUDIO_FUNC); | ||
435 | + | ||
436 | + if (pa->s) { | ||
437 | + pa_simple_free (pa->s); | ||
438 | + pa->s = NULL; | ||
439 | + } | ||
440 | + | ||
441 | + audio_pt_fini (&pa->pt, AUDIO_FUNC); | ||
442 | + qemu_free (pa->pcm_buf); | ||
443 | + pa->pcm_buf = NULL; | ||
444 | +} | ||
445 | + | ||
446 | +static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) | ||
447 | +{ | ||
448 | + (void) hw; | ||
449 | + (void) cmd; | ||
450 | + return 0; | ||
451 | +} | ||
452 | + | ||
453 | +static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) | ||
454 | +{ | ||
455 | + (void) hw; | ||
456 | + (void) cmd; | ||
457 | + return 0; | ||
458 | +} | ||
459 | + | ||
460 | +/* common */ | ||
461 | +static void *qpa_audio_init (void) | ||
462 | +{ | ||
463 | + return &conf; | ||
464 | +} | ||
465 | + | ||
466 | +static void qpa_audio_fini (void *opaque) | ||
467 | +{ | ||
468 | + (void) opaque; | ||
469 | +} | ||
470 | + | ||
471 | +struct audio_option qpa_options[] = { | ||
472 | + {"SAMPLES", AUD_OPT_INT, &conf.samples, | ||
473 | + "buffer size in samples", NULL, 0}, | ||
474 | + | ||
475 | + {"DIVISOR", AUD_OPT_INT, &conf.divisor, | ||
476 | + "threshold divisor", NULL, 0}, | ||
477 | + | ||
478 | + {"SERVER", AUD_OPT_STR, &conf.server, | ||
479 | + "server address", NULL, 0}, | ||
480 | + | ||
481 | + {"SINK", AUD_OPT_STR, &conf.sink, | ||
482 | + "sink device name", NULL, 0}, | ||
483 | + | ||
484 | + {"SOURCE", AUD_OPT_STR, &conf.source, | ||
485 | + "source device name", NULL, 0}, | ||
486 | + | ||
487 | + {NULL, 0, NULL, NULL, NULL, 0} | ||
488 | +}; | ||
489 | + | ||
490 | +struct audio_pcm_ops qpa_pcm_ops = { | ||
491 | + qpa_init_out, | ||
492 | + qpa_fini_out, | ||
493 | + qpa_run_out, | ||
494 | + qpa_write, | ||
495 | + qpa_ctl_out, | ||
496 | + qpa_init_in, | ||
497 | + qpa_fini_in, | ||
498 | + qpa_run_in, | ||
499 | + qpa_read, | ||
500 | + qpa_ctl_in | ||
501 | +}; | ||
502 | + | ||
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) | ||
515 | +}; |
configure
@@ -196,7 +196,7 @@ SunOS) | @@ -196,7 +196,7 @@ SunOS) | ||
196 | ;; | 196 | ;; |
197 | *) | 197 | *) |
198 | audio_drv_list="oss" | 198 | audio_drv_list="oss" |
199 | -audio_possible_drivers="oss alsa sdl esd" | 199 | +audio_possible_drivers="oss alsa sdl esd pa" |
200 | linux="yes" | 200 | linux="yes" |
201 | linux_user="yes" | 201 | linux_user="yes" |
202 | if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then | 202 | if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then |
@@ -767,6 +767,12 @@ for drv in $audio_drv_list; do | @@ -767,6 +767,12 @@ for drv in $audio_drv_list; do | ||
767 | esd) | 767 | esd) |
768 | audio_drv_probe $drv esd.h -lesd 'return esd_play_stream(0, 0, "", 0);' | 768 | audio_drv_probe $drv esd.h -lesd 'return esd_play_stream(0, 0, "", 0);' |
769 | ;; | 769 | ;; |
770 | + | ||
771 | + pa) | ||
772 | + audio_drv_probe $drv pulse/simple.h -lpulse-simple \ | ||
773 | + "pa_simple *s = NULL; pa_simple_free(s); return 0;" | ||
774 | + ;; | ||
775 | + | ||
770 | esac | 776 | esac |
771 | done | 777 | done |
772 | 778 |