|
1 /* |
|
2 * QEMU Audio subsystem |
|
3 * |
|
4 * Copyright (c) 2003-2005 Vassili Karpov (malc) |
|
5 * |
|
6 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 * of this software and associated documentation files (the "Software"), to deal |
|
8 * in the Software without restriction, including without limitation the rights |
|
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 * copies of the Software, and to permit persons to whom the Software is |
|
11 * furnished to do so, subject to the following conditions: |
|
12 * |
|
13 * The above copyright notice and this permission notice shall be included in |
|
14 * all copies or substantial portions of the Software. |
|
15 * |
|
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 * THE SOFTWARE. |
|
23 */ |
|
24 #include "hw/hw.h" |
|
25 #include "audio.h" |
|
26 #include "console.h" |
|
27 #include "qemu-timer.h" |
|
28 #include "sysemu.h" |
|
29 |
|
30 #define AUDIO_CAP "audio" |
|
31 #include "audio_int.h" |
|
32 |
|
33 /* #define DEBUG_PLIVE */ |
|
34 /* #define DEBUG_LIVE */ |
|
35 /* #define DEBUG_OUT */ |
|
36 /* #define DEBUG_CAPTURE */ |
|
37 |
|
38 #define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown" |
|
39 |
|
40 static struct audio_driver *drvtab[] = { |
|
41 AUDIO_DRIVERS |
|
42 &no_audio_driver, |
|
43 &wav_audio_driver |
|
44 }; |
|
45 |
|
46 struct fixed_settings { |
|
47 int enabled; |
|
48 int nb_voices; |
|
49 int greedy; |
|
50 struct audsettings settings; |
|
51 }; |
|
52 |
|
53 static struct { |
|
54 struct fixed_settings fixed_out; |
|
55 struct fixed_settings fixed_in; |
|
56 union { |
|
57 int hertz; |
|
58 int64_t ticks; |
|
59 } period; |
|
60 int plive; |
|
61 int log_to_monitor; |
|
62 } conf = { |
|
63 { /* DAC fixed settings */ |
|
64 1, /* enabled */ |
|
65 1, /* nb_voices */ |
|
66 1, /* greedy */ |
|
67 { |
|
68 44100, /* freq */ |
|
69 2, /* nchannels */ |
|
70 AUD_FMT_S16, /* fmt */ |
|
71 AUDIO_HOST_ENDIANNESS |
|
72 } |
|
73 }, |
|
74 |
|
75 { /* ADC fixed settings */ |
|
76 1, /* enabled */ |
|
77 1, /* nb_voices */ |
|
78 1, /* greedy */ |
|
79 { |
|
80 44100, /* freq */ |
|
81 2, /* nchannels */ |
|
82 AUD_FMT_S16, /* fmt */ |
|
83 AUDIO_HOST_ENDIANNESS |
|
84 } |
|
85 }, |
|
86 |
|
87 { 250 }, /* period */ |
|
88 0, /* plive */ |
|
89 0 /* log_to_monitor */ |
|
90 }; |
|
91 |
|
92 static AudioState glob_audio_state; |
|
93 |
|
94 struct mixeng_volume nominal_volume = { |
|
95 0, |
|
96 #ifdef FLOAT_MIXENG |
|
97 1.0, |
|
98 1.0 |
|
99 #else |
|
100 1ULL << 32, |
|
101 1ULL << 32 |
|
102 #endif |
|
103 }; |
|
104 |
|
105 /* http://www.df.lth.se/~john_e/gems/gem002d.html */ |
|
106 /* http://www.multi-platforms.com/Tips/PopCount.htm */ |
|
107 uint32_t popcount (uint32_t u) |
|
108 { |
|
109 u = ((u&0x55555555) + ((u>>1)&0x55555555)); |
|
110 u = ((u&0x33333333) + ((u>>2)&0x33333333)); |
|
111 u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f)); |
|
112 u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff)); |
|
113 u = ( u&0x0000ffff) + (u>>16); |
|
114 return u; |
|
115 } |
|
116 |
|
117 inline uint32_t lsbindex (uint32_t u) |
|
118 { |
|
119 return popcount ((u&-u)-1); |
|
120 } |
|
121 |
|
122 #ifdef AUDIO_IS_FLAWLESS_AND_NO_CHECKS_ARE_REQURIED |
|
123 #error No its not |
|
124 #else |
|
125 int audio_bug (const char *funcname, int cond) |
|
126 { |
|
127 if (cond) { |
|
128 static int shown; |
|
129 |
|
130 AUD_log (NULL, "A bug was just triggered in %s\n", funcname); |
|
131 if (!shown) { |
|
132 shown = 1; |
|
133 AUD_log (NULL, "Save all your work and restart without audio\n"); |
|
134 AUD_log (NULL, "Please send bug report to malc@pulsesoft.com\n"); |
|
135 AUD_log (NULL, "I am sorry\n"); |
|
136 } |
|
137 AUD_log (NULL, "Context:\n"); |
|
138 |
|
139 #if defined AUDIO_BREAKPOINT_ON_BUG |
|
140 # if defined HOST_I386 |
|
141 # if defined __GNUC__ |
|
142 __asm__ ("int3"); |
|
143 # elif defined _MSC_VER |
|
144 _asm _emit 0xcc; |
|
145 # else |
|
146 abort (); |
|
147 # endif |
|
148 # else |
|
149 abort (); |
|
150 # endif |
|
151 #endif |
|
152 } |
|
153 |
|
154 return cond; |
|
155 } |
|
156 #endif |
|
157 |
|
158 static inline int audio_bits_to_index (int bits) |
|
159 { |
|
160 switch (bits) { |
|
161 case 8: |
|
162 return 0; |
|
163 |
|
164 case 16: |
|
165 return 1; |
|
166 |
|
167 case 32: |
|
168 return 2; |
|
169 |
|
170 default: |
|
171 audio_bug ("bits_to_index", 1); |
|
172 AUD_log (NULL, "invalid bits %d\n", bits); |
|
173 return 0; |
|
174 } |
|
175 } |
|
176 |
|
177 void *audio_calloc (const char *funcname, int nmemb, size_t size) |
|
178 { |
|
179 int cond; |
|
180 size_t len; |
|
181 |
|
182 len = nmemb * size; |
|
183 cond = !nmemb || !size; |
|
184 cond |= nmemb < 0; |
|
185 cond |= len < size; |
|
186 |
|
187 if (audio_bug ("audio_calloc", cond)) { |
|
188 AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n", |
|
189 funcname); |
|
190 AUD_log (NULL, "nmemb=%d size=%zu (len=%zu)\n", nmemb, size, len); |
|
191 return NULL; |
|
192 } |
|
193 |
|
194 return qemu_mallocz (len); |
|
195 } |
|
196 |
|
197 static char *audio_alloc_prefix (const char *s) |
|
198 { |
|
199 const char qemu_prefix[] = "QEMU_"; |
|
200 size_t len; |
|
201 char *r; |
|
202 |
|
203 if (!s) { |
|
204 return NULL; |
|
205 } |
|
206 |
|
207 len = strlen (s); |
|
208 r = qemu_malloc (len + sizeof (qemu_prefix)); |
|
209 |
|
210 if (r) { |
|
211 size_t i; |
|
212 char *u = r + sizeof (qemu_prefix) - 1; |
|
213 |
|
214 pstrcpy (r, len + sizeof (qemu_prefix), qemu_prefix); |
|
215 pstrcat (r, len + sizeof (qemu_prefix), s); |
|
216 |
|
217 for (i = 0; i < len; ++i) { |
|
218 u[i] = qemu_toupper(u[i]); |
|
219 } |
|
220 } |
|
221 return r; |
|
222 } |
|
223 |
|
224 static const char *audio_audfmt_to_string (audfmt_e fmt) |
|
225 { |
|
226 switch (fmt) { |
|
227 case AUD_FMT_U8: |
|
228 return "U8"; |
|
229 |
|
230 case AUD_FMT_U16: |
|
231 return "U16"; |
|
232 |
|
233 case AUD_FMT_S8: |
|
234 return "S8"; |
|
235 |
|
236 case AUD_FMT_S16: |
|
237 return "S16"; |
|
238 |
|
239 case AUD_FMT_U32: |
|
240 return "U32"; |
|
241 |
|
242 case AUD_FMT_S32: |
|
243 return "S32"; |
|
244 } |
|
245 |
|
246 dolog ("Bogus audfmt %d returning S16\n", fmt); |
|
247 return "S16"; |
|
248 } |
|
249 |
|
250 static audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, |
|
251 int *defaultp) |
|
252 { |
|
253 if (!strcasecmp (s, "u8")) { |
|
254 *defaultp = 0; |
|
255 return AUD_FMT_U8; |
|
256 } |
|
257 else if (!strcasecmp (s, "u16")) { |
|
258 *defaultp = 0; |
|
259 return AUD_FMT_U16; |
|
260 } |
|
261 else if (!strcasecmp (s, "u32")) { |
|
262 *defaultp = 0; |
|
263 return AUD_FMT_U32; |
|
264 } |
|
265 else if (!strcasecmp (s, "s8")) { |
|
266 *defaultp = 0; |
|
267 return AUD_FMT_S8; |
|
268 } |
|
269 else if (!strcasecmp (s, "s16")) { |
|
270 *defaultp = 0; |
|
271 return AUD_FMT_S16; |
|
272 } |
|
273 else if (!strcasecmp (s, "s32")) { |
|
274 *defaultp = 0; |
|
275 return AUD_FMT_S32; |
|
276 } |
|
277 else { |
|
278 dolog ("Bogus audio format `%s' using %s\n", |
|
279 s, audio_audfmt_to_string (defval)); |
|
280 *defaultp = 1; |
|
281 return defval; |
|
282 } |
|
283 } |
|
284 |
|
285 static audfmt_e audio_get_conf_fmt (const char *envname, |
|
286 audfmt_e defval, |
|
287 int *defaultp) |
|
288 { |
|
289 const char *var = getenv (envname); |
|
290 if (!var) { |
|
291 *defaultp = 1; |
|
292 return defval; |
|
293 } |
|
294 return audio_string_to_audfmt (var, defval, defaultp); |
|
295 } |
|
296 |
|
297 static int audio_get_conf_int (const char *key, int defval, int *defaultp) |
|
298 { |
|
299 int val; |
|
300 char *strval; |
|
301 |
|
302 strval = getenv (key); |
|
303 if (strval) { |
|
304 *defaultp = 0; |
|
305 val = atoi (strval); |
|
306 return val; |
|
307 } |
|
308 else { |
|
309 *defaultp = 1; |
|
310 return defval; |
|
311 } |
|
312 } |
|
313 |
|
314 static const char *audio_get_conf_str (const char *key, |
|
315 const char *defval, |
|
316 int *defaultp) |
|
317 { |
|
318 const char *val = getenv (key); |
|
319 if (!val) { |
|
320 *defaultp = 1; |
|
321 return defval; |
|
322 } |
|
323 else { |
|
324 *defaultp = 0; |
|
325 return val; |
|
326 } |
|
327 } |
|
328 |
|
329 void AUD_vlog (const char *cap, const char *fmt, va_list ap) |
|
330 { |
|
331 if (conf.log_to_monitor) { |
|
332 if (cap) { |
|
333 term_printf ("%s: ", cap); |
|
334 } |
|
335 |
|
336 term_vprintf (fmt, ap); |
|
337 } |
|
338 else { |
|
339 if (cap) { |
|
340 fprintf (stderr, "%s: ", cap); |
|
341 } |
|
342 |
|
343 vfprintf (stderr, fmt, ap); |
|
344 } |
|
345 } |
|
346 |
|
347 void AUD_log (const char *cap, const char *fmt, ...) |
|
348 { |
|
349 va_list ap; |
|
350 |
|
351 va_start (ap, fmt); |
|
352 AUD_vlog (cap, fmt, ap); |
|
353 va_end (ap); |
|
354 } |
|
355 |
|
356 static void audio_print_options (const char *prefix, |
|
357 struct audio_option *opt) |
|
358 { |
|
359 char *uprefix; |
|
360 |
|
361 if (!prefix) { |
|
362 dolog ("No prefix specified\n"); |
|
363 return; |
|
364 } |
|
365 |
|
366 if (!opt) { |
|
367 dolog ("No options\n"); |
|
368 return; |
|
369 } |
|
370 |
|
371 uprefix = audio_alloc_prefix (prefix); |
|
372 |
|
373 for (; opt->name; opt++) { |
|
374 const char *state = "default"; |
|
375 printf (" %s_%s: ", uprefix, opt->name); |
|
376 |
|
377 if (opt->overriddenp && *opt->overriddenp) { |
|
378 state = "current"; |
|
379 } |
|
380 |
|
381 switch (opt->tag) { |
|
382 case AUD_OPT_BOOL: |
|
383 { |
|
384 int *intp = opt->valp; |
|
385 printf ("boolean, %s = %d\n", state, *intp ? 1 : 0); |
|
386 } |
|
387 break; |
|
388 |
|
389 case AUD_OPT_INT: |
|
390 { |
|
391 int *intp = opt->valp; |
|
392 printf ("integer, %s = %d\n", state, *intp); |
|
393 } |
|
394 break; |
|
395 |
|
396 case AUD_OPT_FMT: |
|
397 { |
|
398 audfmt_e *fmtp = opt->valp; |
|
399 printf ( |
|
400 "format, %s = %s, (one of: U8 S8 U16 S16 U32 S32)\n", |
|
401 state, |
|
402 audio_audfmt_to_string (*fmtp) |
|
403 ); |
|
404 } |
|
405 break; |
|
406 |
|
407 case AUD_OPT_STR: |
|
408 { |
|
409 const char **strp = opt->valp; |
|
410 printf ("string, %s = %s\n", |
|
411 state, |
|
412 *strp ? *strp : "(not set)"); |
|
413 } |
|
414 break; |
|
415 |
|
416 default: |
|
417 printf ("???\n"); |
|
418 dolog ("Bad value tag for option %s_%s %d\n", |
|
419 uprefix, opt->name, opt->tag); |
|
420 break; |
|
421 } |
|
422 printf (" %s\n", opt->descr); |
|
423 } |
|
424 |
|
425 qemu_free (uprefix); |
|
426 } |
|
427 |
|
428 static void audio_process_options (const char *prefix, |
|
429 struct audio_option *opt) |
|
430 { |
|
431 char *optname; |
|
432 const char qemu_prefix[] = "QEMU_"; |
|
433 size_t preflen, optlen; |
|
434 |
|
435 if (audio_bug (AUDIO_FUNC, !prefix)) { |
|
436 dolog ("prefix = NULL\n"); |
|
437 return; |
|
438 } |
|
439 |
|
440 if (audio_bug (AUDIO_FUNC, !opt)) { |
|
441 dolog ("opt = NULL\n"); |
|
442 return; |
|
443 } |
|
444 |
|
445 preflen = strlen (prefix); |
|
446 |
|
447 for (; opt->name; opt++) { |
|
448 size_t len, i; |
|
449 int def; |
|
450 |
|
451 if (!opt->valp) { |
|
452 dolog ("Option value pointer for `%s' is not set\n", |
|
453 opt->name); |
|
454 continue; |
|
455 } |
|
456 |
|
457 len = strlen (opt->name); |
|
458 /* len of opt->name + len of prefix + size of qemu_prefix |
|
459 * (includes trailing zero) + zero + underscore (on behalf of |
|
460 * sizeof) */ |
|
461 optlen = len + preflen + sizeof (qemu_prefix) + 1; |
|
462 optname = qemu_malloc (optlen); |
|
463 if (!optname) { |
|
464 dolog ("Could not allocate memory for option name `%s'\n", |
|
465 opt->name); |
|
466 continue; |
|
467 } |
|
468 |
|
469 pstrcpy (optname, optlen, qemu_prefix); |
|
470 |
|
471 /* copy while upper-casing, including trailing zero */ |
|
472 for (i = 0; i <= preflen; ++i) { |
|
473 optname[i + sizeof (qemu_prefix) - 1] = qemu_toupper(prefix[i]); |
|
474 } |
|
475 pstrcat (optname, optlen, "_"); |
|
476 pstrcat (optname, optlen, opt->name); |
|
477 |
|
478 def = 1; |
|
479 switch (opt->tag) { |
|
480 case AUD_OPT_BOOL: |
|
481 case AUD_OPT_INT: |
|
482 { |
|
483 int *intp = opt->valp; |
|
484 *intp = audio_get_conf_int (optname, *intp, &def); |
|
485 } |
|
486 break; |
|
487 |
|
488 case AUD_OPT_FMT: |
|
489 { |
|
490 audfmt_e *fmtp = opt->valp; |
|
491 *fmtp = audio_get_conf_fmt (optname, *fmtp, &def); |
|
492 } |
|
493 break; |
|
494 |
|
495 case AUD_OPT_STR: |
|
496 { |
|
497 const char **strp = opt->valp; |
|
498 *strp = audio_get_conf_str (optname, *strp, &def); |
|
499 } |
|
500 break; |
|
501 |
|
502 default: |
|
503 dolog ("Bad value tag for option `%s' - %d\n", |
|
504 optname, opt->tag); |
|
505 break; |
|
506 } |
|
507 |
|
508 if (!opt->overriddenp) { |
|
509 opt->overriddenp = &opt->overridden; |
|
510 } |
|
511 *opt->overriddenp = !def; |
|
512 qemu_free (optname); |
|
513 } |
|
514 } |
|
515 |
|
516 static void audio_print_settings (struct audsettings *as) |
|
517 { |
|
518 dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels); |
|
519 |
|
520 switch (as->fmt) { |
|
521 case AUD_FMT_S8: |
|
522 AUD_log (NULL, "S8"); |
|
523 break; |
|
524 case AUD_FMT_U8: |
|
525 AUD_log (NULL, "U8"); |
|
526 break; |
|
527 case AUD_FMT_S16: |
|
528 AUD_log (NULL, "S16"); |
|
529 break; |
|
530 case AUD_FMT_U16: |
|
531 AUD_log (NULL, "U16"); |
|
532 break; |
|
533 case AUD_FMT_S32: |
|
534 AUD_log (NULL, "S32"); |
|
535 break; |
|
536 case AUD_FMT_U32: |
|
537 AUD_log (NULL, "U32"); |
|
538 break; |
|
539 default: |
|
540 AUD_log (NULL, "invalid(%d)", as->fmt); |
|
541 break; |
|
542 } |
|
543 |
|
544 AUD_log (NULL, " endianness="); |
|
545 switch (as->endianness) { |
|
546 case 0: |
|
547 AUD_log (NULL, "little"); |
|
548 break; |
|
549 case 1: |
|
550 AUD_log (NULL, "big"); |
|
551 break; |
|
552 default: |
|
553 AUD_log (NULL, "invalid"); |
|
554 break; |
|
555 } |
|
556 AUD_log (NULL, "\n"); |
|
557 } |
|
558 |
|
559 static int audio_validate_settings (struct audsettings *as) |
|
560 { |
|
561 int invalid; |
|
562 |
|
563 invalid = as->nchannels != 1 && as->nchannels != 2; |
|
564 invalid |= as->endianness != 0 && as->endianness != 1; |
|
565 |
|
566 switch (as->fmt) { |
|
567 case AUD_FMT_S8: |
|
568 case AUD_FMT_U8: |
|
569 case AUD_FMT_S16: |
|
570 case AUD_FMT_U16: |
|
571 case AUD_FMT_S32: |
|
572 case AUD_FMT_U32: |
|
573 break; |
|
574 default: |
|
575 invalid = 1; |
|
576 break; |
|
577 } |
|
578 |
|
579 invalid |= as->freq <= 0; |
|
580 return invalid ? -1 : 0; |
|
581 } |
|
582 |
|
583 static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *as) |
|
584 { |
|
585 int bits = 8, sign = 0; |
|
586 |
|
587 switch (as->fmt) { |
|
588 case AUD_FMT_S8: |
|
589 sign = 1; |
|
590 case AUD_FMT_U8: |
|
591 break; |
|
592 |
|
593 case AUD_FMT_S16: |
|
594 sign = 1; |
|
595 case AUD_FMT_U16: |
|
596 bits = 16; |
|
597 break; |
|
598 |
|
599 case AUD_FMT_S32: |
|
600 sign = 1; |
|
601 case AUD_FMT_U32: |
|
602 bits = 32; |
|
603 break; |
|
604 } |
|
605 return info->freq == as->freq |
|
606 && info->nchannels == as->nchannels |
|
607 && info->sign == sign |
|
608 && info->bits == bits |
|
609 && info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS); |
|
610 } |
|
611 |
|
612 void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as) |
|
613 { |
|
614 int bits = 8, sign = 0, shift = 0; |
|
615 |
|
616 switch (as->fmt) { |
|
617 case AUD_FMT_S8: |
|
618 sign = 1; |
|
619 case AUD_FMT_U8: |
|
620 break; |
|
621 |
|
622 case AUD_FMT_S16: |
|
623 sign = 1; |
|
624 case AUD_FMT_U16: |
|
625 bits = 16; |
|
626 shift = 1; |
|
627 break; |
|
628 |
|
629 case AUD_FMT_S32: |
|
630 sign = 1; |
|
631 case AUD_FMT_U32: |
|
632 bits = 32; |
|
633 shift = 2; |
|
634 break; |
|
635 } |
|
636 |
|
637 info->freq = as->freq; |
|
638 info->bits = bits; |
|
639 info->sign = sign; |
|
640 info->nchannels = as->nchannels; |
|
641 info->shift = (as->nchannels == 2) + shift; |
|
642 info->align = (1 << info->shift) - 1; |
|
643 info->bytes_per_second = info->freq << info->shift; |
|
644 info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS); |
|
645 } |
|
646 |
|
647 void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len) |
|
648 { |
|
649 if (!len) { |
|
650 return; |
|
651 } |
|
652 |
|
653 if (info->sign) { |
|
654 memset (buf, 0x00, len << info->shift); |
|
655 } |
|
656 else { |
|
657 switch (info->bits) { |
|
658 case 8: |
|
659 memset (buf, 0x80, len << info->shift); |
|
660 break; |
|
661 |
|
662 case 16: |
|
663 { |
|
664 int i; |
|
665 uint16_t *p = buf; |
|
666 int shift = info->nchannels - 1; |
|
667 short s = INT16_MAX; |
|
668 |
|
669 if (info->swap_endianness) { |
|
670 s = bswap16 (s); |
|
671 } |
|
672 |
|
673 for (i = 0; i < len << shift; i++) { |
|
674 p[i] = s; |
|
675 } |
|
676 } |
|
677 break; |
|
678 |
|
679 case 32: |
|
680 { |
|
681 int i; |
|
682 uint32_t *p = buf; |
|
683 int shift = info->nchannels - 1; |
|
684 int32_t s = INT32_MAX; |
|
685 |
|
686 if (info->swap_endianness) { |
|
687 s = bswap32 (s); |
|
688 } |
|
689 |
|
690 for (i = 0; i < len << shift; i++) { |
|
691 p[i] = s; |
|
692 } |
|
693 } |
|
694 break; |
|
695 |
|
696 default: |
|
697 AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n", |
|
698 info->bits); |
|
699 break; |
|
700 } |
|
701 } |
|
702 } |
|
703 |
|
704 /* |
|
705 * Capture |
|
706 */ |
|
707 static void noop_conv (struct st_sample *dst, const void *src, |
|
708 int samples, struct mixeng_volume *vol) |
|
709 { |
|
710 (void) src; |
|
711 (void) dst; |
|
712 (void) samples; |
|
713 (void) vol; |
|
714 } |
|
715 |
|
716 static CaptureVoiceOut *audio_pcm_capture_find_specific ( |
|
717 AudioState *s, |
|
718 struct audsettings *as |
|
719 ) |
|
720 { |
|
721 CaptureVoiceOut *cap; |
|
722 |
|
723 for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) { |
|
724 if (audio_pcm_info_eq (&cap->hw.info, as)) { |
|
725 return cap; |
|
726 } |
|
727 } |
|
728 return NULL; |
|
729 } |
|
730 |
|
731 static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd) |
|
732 { |
|
733 struct capture_callback *cb; |
|
734 |
|
735 #ifdef DEBUG_CAPTURE |
|
736 dolog ("notification %d sent\n", cmd); |
|
737 #endif |
|
738 for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { |
|
739 cb->ops.notify (cb->opaque, cmd); |
|
740 } |
|
741 } |
|
742 |
|
743 static void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled) |
|
744 { |
|
745 if (cap->hw.enabled != enabled) { |
|
746 audcnotification_e cmd; |
|
747 cap->hw.enabled = enabled; |
|
748 cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE; |
|
749 audio_notify_capture (cap, cmd); |
|
750 } |
|
751 } |
|
752 |
|
753 static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap) |
|
754 { |
|
755 HWVoiceOut *hw = &cap->hw; |
|
756 SWVoiceOut *sw; |
|
757 int enabled = 0; |
|
758 |
|
759 for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { |
|
760 if (sw->active) { |
|
761 enabled = 1; |
|
762 break; |
|
763 } |
|
764 } |
|
765 audio_capture_maybe_changed (cap, enabled); |
|
766 } |
|
767 |
|
768 static void audio_detach_capture (HWVoiceOut *hw) |
|
769 { |
|
770 SWVoiceCap *sc = hw->cap_head.lh_first; |
|
771 |
|
772 while (sc) { |
|
773 SWVoiceCap *sc1 = sc->entries.le_next; |
|
774 SWVoiceOut *sw = &sc->sw; |
|
775 CaptureVoiceOut *cap = sc->cap; |
|
776 int was_active = sw->active; |
|
777 |
|
778 if (sw->rate) { |
|
779 st_rate_stop (sw->rate); |
|
780 sw->rate = NULL; |
|
781 } |
|
782 |
|
783 LIST_REMOVE (sw, entries); |
|
784 LIST_REMOVE (sc, entries); |
|
785 qemu_free (sc); |
|
786 if (was_active) { |
|
787 /* We have removed soft voice from the capture: |
|
788 this might have changed the overall status of the capture |
|
789 since this might have been the only active voice */ |
|
790 audio_recalc_and_notify_capture (cap); |
|
791 } |
|
792 sc = sc1; |
|
793 } |
|
794 } |
|
795 |
|
796 static int audio_attach_capture (AudioState *s, HWVoiceOut *hw) |
|
797 { |
|
798 CaptureVoiceOut *cap; |
|
799 |
|
800 audio_detach_capture (hw); |
|
801 for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) { |
|
802 SWVoiceCap *sc; |
|
803 SWVoiceOut *sw; |
|
804 HWVoiceOut *hw_cap = &cap->hw; |
|
805 |
|
806 sc = audio_calloc (AUDIO_FUNC, 1, sizeof (*sc)); |
|
807 if (!sc) { |
|
808 dolog ("Could not allocate soft capture voice (%zu bytes)\n", |
|
809 sizeof (*sc)); |
|
810 return -1; |
|
811 } |
|
812 |
|
813 sc->cap = cap; |
|
814 sw = &sc->sw; |
|
815 sw->hw = hw_cap; |
|
816 sw->info = hw->info; |
|
817 sw->empty = 1; |
|
818 sw->active = hw->enabled; |
|
819 sw->conv = noop_conv; |
|
820 sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq; |
|
821 sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq); |
|
822 if (!sw->rate) { |
|
823 dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw)); |
|
824 qemu_free (sw); |
|
825 return -1; |
|
826 } |
|
827 LIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries); |
|
828 LIST_INSERT_HEAD (&hw->cap_head, sc, entries); |
|
829 #ifdef DEBUG_CAPTURE |
|
830 asprintf (&sw->name, "for %p %d,%d,%d", |
|
831 hw, sw->info.freq, sw->info.bits, sw->info.nchannels); |
|
832 dolog ("Added %s active = %d\n", sw->name, sw->active); |
|
833 #endif |
|
834 if (sw->active) { |
|
835 audio_capture_maybe_changed (cap, 1); |
|
836 } |
|
837 } |
|
838 return 0; |
|
839 } |
|
840 |
|
841 /* |
|
842 * Hard voice (capture) |
|
843 */ |
|
844 static int audio_pcm_hw_find_min_in (HWVoiceIn *hw) |
|
845 { |
|
846 SWVoiceIn *sw; |
|
847 int m = hw->total_samples_captured; |
|
848 |
|
849 for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { |
|
850 if (sw->active) { |
|
851 m = audio_MIN (m, sw->total_hw_samples_acquired); |
|
852 } |
|
853 } |
|
854 return m; |
|
855 } |
|
856 |
|
857 int audio_pcm_hw_get_live_in (HWVoiceIn *hw) |
|
858 { |
|
859 int live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); |
|
860 if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { |
|
861 dolog ("live=%d hw->samples=%d\n", live, hw->samples); |
|
862 return 0; |
|
863 } |
|
864 return live; |
|
865 } |
|
866 |
|
867 /* |
|
868 * Soft voice (capture) |
|
869 */ |
|
870 static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw) |
|
871 { |
|
872 HWVoiceIn *hw = sw->hw; |
|
873 int live = hw->total_samples_captured - sw->total_hw_samples_acquired; |
|
874 int rpos; |
|
875 |
|
876 if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { |
|
877 dolog ("live=%d hw->samples=%d\n", live, hw->samples); |
|
878 return 0; |
|
879 } |
|
880 |
|
881 rpos = hw->wpos - live; |
|
882 if (rpos >= 0) { |
|
883 return rpos; |
|
884 } |
|
885 else { |
|
886 return hw->samples + rpos; |
|
887 } |
|
888 } |
|
889 |
|
890 int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size) |
|
891 { |
|
892 HWVoiceIn *hw = sw->hw; |
|
893 int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; |
|
894 struct st_sample *src, *dst = sw->buf; |
|
895 |
|
896 rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples; |
|
897 |
|
898 live = hw->total_samples_captured - sw->total_hw_samples_acquired; |
|
899 if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { |
|
900 dolog ("live_in=%d hw->samples=%d\n", live, hw->samples); |
|
901 return 0; |
|
902 } |
|
903 |
|
904 samples = size >> sw->info.shift; |
|
905 if (!live) { |
|
906 return 0; |
|
907 } |
|
908 |
|
909 swlim = (live * sw->ratio) >> 32; |
|
910 swlim = audio_MIN (swlim, samples); |
|
911 |
|
912 while (swlim) { |
|
913 src = hw->conv_buf + rpos; |
|
914 isamp = hw->wpos - rpos; |
|
915 /* XXX: <= ? */ |
|
916 if (isamp <= 0) { |
|
917 isamp = hw->samples - rpos; |
|
918 } |
|
919 |
|
920 if (!isamp) { |
|
921 break; |
|
922 } |
|
923 osamp = swlim; |
|
924 |
|
925 if (audio_bug (AUDIO_FUNC, osamp < 0)) { |
|
926 dolog ("osamp=%d\n", osamp); |
|
927 return 0; |
|
928 } |
|
929 |
|
930 st_rate_flow (sw->rate, src, dst, &isamp, &osamp); |
|
931 swlim -= osamp; |
|
932 rpos = (rpos + isamp) % hw->samples; |
|
933 dst += osamp; |
|
934 ret += osamp; |
|
935 total += isamp; |
|
936 } |
|
937 |
|
938 sw->clip (buf, sw->buf, ret); |
|
939 sw->total_hw_samples_acquired += total; |
|
940 return ret << sw->info.shift; |
|
941 } |
|
942 |
|
943 /* |
|
944 * Hard voice (playback) |
|
945 */ |
|
946 static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep) |
|
947 { |
|
948 SWVoiceOut *sw; |
|
949 int m = INT_MAX; |
|
950 int nb_live = 0; |
|
951 |
|
952 for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { |
|
953 if (sw->active || !sw->empty) { |
|
954 m = audio_MIN (m, sw->total_hw_samples_mixed); |
|
955 nb_live += 1; |
|
956 } |
|
957 } |
|
958 |
|
959 *nb_livep = nb_live; |
|
960 return m; |
|
961 } |
|
962 |
|
963 int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live) |
|
964 { |
|
965 int smin; |
|
966 |
|
967 smin = audio_pcm_hw_find_min_out (hw, nb_live); |
|
968 |
|
969 if (!*nb_live) { |
|
970 return 0; |
|
971 } |
|
972 else { |
|
973 int live = smin; |
|
974 |
|
975 if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { |
|
976 dolog ("live=%d hw->samples=%d\n", live, hw->samples); |
|
977 return 0; |
|
978 } |
|
979 return live; |
|
980 } |
|
981 } |
|
982 |
|
983 int audio_pcm_hw_get_live_out (HWVoiceOut *hw) |
|
984 { |
|
985 int nb_live; |
|
986 int live; |
|
987 |
|
988 live = audio_pcm_hw_get_live_out2 (hw, &nb_live); |
|
989 if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { |
|
990 dolog ("live=%d hw->samples=%d\n", live, hw->samples); |
|
991 return 0; |
|
992 } |
|
993 return live; |
|
994 } |
|
995 |
|
996 /* |
|
997 * Soft voice (playback) |
|
998 */ |
|
999 int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size) |
|
1000 { |
|
1001 int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck; |
|
1002 int ret = 0, pos = 0, total = 0; |
|
1003 |
|
1004 if (!sw) { |
|
1005 return size; |
|
1006 } |
|
1007 |
|
1008 hwsamples = sw->hw->samples; |
|
1009 |
|
1010 live = sw->total_hw_samples_mixed; |
|
1011 if (audio_bug (AUDIO_FUNC, live < 0 || live > hwsamples)){ |
|
1012 dolog ("live=%d hw->samples=%d\n", live, hwsamples); |
|
1013 return 0; |
|
1014 } |
|
1015 |
|
1016 if (live == hwsamples) { |
|
1017 #ifdef DEBUG_OUT |
|
1018 dolog ("%s is full %d\n", sw->name, live); |
|
1019 #endif |
|
1020 return 0; |
|
1021 } |
|
1022 |
|
1023 wpos = (sw->hw->rpos + live) % hwsamples; |
|
1024 samples = size >> sw->info.shift; |
|
1025 |
|
1026 dead = hwsamples - live; |
|
1027 swlim = ((int64_t) dead << 32) / sw->ratio; |
|
1028 swlim = audio_MIN (swlim, samples); |
|
1029 if (swlim) { |
|
1030 sw->conv (sw->buf, buf, swlim, &sw->vol); |
|
1031 } |
|
1032 |
|
1033 while (swlim) { |
|
1034 dead = hwsamples - live; |
|
1035 left = hwsamples - wpos; |
|
1036 blck = audio_MIN (dead, left); |
|
1037 if (!blck) { |
|
1038 break; |
|
1039 } |
|
1040 isamp = swlim; |
|
1041 osamp = blck; |
|
1042 st_rate_flow_mix ( |
|
1043 sw->rate, |
|
1044 sw->buf + pos, |
|
1045 sw->hw->mix_buf + wpos, |
|
1046 &isamp, |
|
1047 &osamp |
|
1048 ); |
|
1049 ret += isamp; |
|
1050 swlim -= isamp; |
|
1051 pos += isamp; |
|
1052 live += osamp; |
|
1053 wpos = (wpos + osamp) % hwsamples; |
|
1054 total += osamp; |
|
1055 } |
|
1056 |
|
1057 sw->total_hw_samples_mixed += total; |
|
1058 sw->empty = sw->total_hw_samples_mixed == 0; |
|
1059 |
|
1060 #ifdef DEBUG_OUT |
|
1061 dolog ( |
|
1062 "%s: write size %d ret %d total sw %d\n", |
|
1063 SW_NAME (sw), |
|
1064 size >> sw->info.shift, |
|
1065 ret, |
|
1066 sw->total_hw_samples_mixed |
|
1067 ); |
|
1068 #endif |
|
1069 |
|
1070 return ret << sw->info.shift; |
|
1071 } |
|
1072 |
|
1073 #ifdef DEBUG_AUDIO |
|
1074 static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info) |
|
1075 { |
|
1076 dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n", |
|
1077 cap, info->bits, info->sign, info->freq, info->nchannels); |
|
1078 } |
|
1079 #endif |
|
1080 |
|
1081 #define DAC |
|
1082 #include "audio_template.h" |
|
1083 #undef DAC |
|
1084 #include "audio_template.h" |
|
1085 |
|
1086 int AUD_write (SWVoiceOut *sw, void *buf, int size) |
|
1087 { |
|
1088 int bytes; |
|
1089 |
|
1090 if (!sw) { |
|
1091 /* XXX: Consider options */ |
|
1092 return size; |
|
1093 } |
|
1094 |
|
1095 if (!sw->hw->enabled) { |
|
1096 dolog ("Writing to disabled voice %s\n", SW_NAME (sw)); |
|
1097 return 0; |
|
1098 } |
|
1099 |
|
1100 bytes = sw->hw->pcm_ops->write (sw, buf, size); |
|
1101 return bytes; |
|
1102 } |
|
1103 |
|
1104 int AUD_read (SWVoiceIn *sw, void *buf, int size) |
|
1105 { |
|
1106 int bytes; |
|
1107 |
|
1108 if (!sw) { |
|
1109 /* XXX: Consider options */ |
|
1110 return size; |
|
1111 } |
|
1112 |
|
1113 if (!sw->hw->enabled) { |
|
1114 dolog ("Reading from disabled voice %s\n", SW_NAME (sw)); |
|
1115 return 0; |
|
1116 } |
|
1117 |
|
1118 bytes = sw->hw->pcm_ops->read (sw, buf, size); |
|
1119 return bytes; |
|
1120 } |
|
1121 |
|
1122 int AUD_get_buffer_size_out (SWVoiceOut *sw) |
|
1123 { |
|
1124 return sw->hw->samples << sw->hw->info.shift; |
|
1125 } |
|
1126 |
|
1127 void AUD_set_active_out (SWVoiceOut *sw, int on) |
|
1128 { |
|
1129 HWVoiceOut *hw; |
|
1130 |
|
1131 if (!sw) { |
|
1132 return; |
|
1133 } |
|
1134 |
|
1135 hw = sw->hw; |
|
1136 if (sw->active != on) { |
|
1137 SWVoiceOut *temp_sw; |
|
1138 SWVoiceCap *sc; |
|
1139 |
|
1140 if (on) { |
|
1141 hw->pending_disable = 0; |
|
1142 if (!hw->enabled) { |
|
1143 hw->enabled = 1; |
|
1144 hw->pcm_ops->ctl_out (hw, VOICE_ENABLE); |
|
1145 } |
|
1146 } |
|
1147 else { |
|
1148 if (hw->enabled) { |
|
1149 int nb_active = 0; |
|
1150 |
|
1151 for (temp_sw = hw->sw_head.lh_first; temp_sw; |
|
1152 temp_sw = temp_sw->entries.le_next) { |
|
1153 nb_active += temp_sw->active != 0; |
|
1154 } |
|
1155 |
|
1156 hw->pending_disable = nb_active == 1; |
|
1157 } |
|
1158 } |
|
1159 |
|
1160 for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { |
|
1161 sc->sw.active = hw->enabled; |
|
1162 if (hw->enabled) { |
|
1163 audio_capture_maybe_changed (sc->cap, 1); |
|
1164 } |
|
1165 } |
|
1166 sw->active = on; |
|
1167 } |
|
1168 } |
|
1169 |
|
1170 void AUD_set_active_in (SWVoiceIn *sw, int on) |
|
1171 { |
|
1172 HWVoiceIn *hw; |
|
1173 |
|
1174 if (!sw) { |
|
1175 return; |
|
1176 } |
|
1177 |
|
1178 hw = sw->hw; |
|
1179 if (sw->active != on) { |
|
1180 SWVoiceIn *temp_sw; |
|
1181 |
|
1182 if (on) { |
|
1183 if (!hw->enabled) { |
|
1184 hw->enabled = 1; |
|
1185 hw->pcm_ops->ctl_in (hw, VOICE_ENABLE); |
|
1186 } |
|
1187 sw->total_hw_samples_acquired = hw->total_samples_captured; |
|
1188 } |
|
1189 else { |
|
1190 if (hw->enabled) { |
|
1191 int nb_active = 0; |
|
1192 |
|
1193 for (temp_sw = hw->sw_head.lh_first; temp_sw; |
|
1194 temp_sw = temp_sw->entries.le_next) { |
|
1195 nb_active += temp_sw->active != 0; |
|
1196 } |
|
1197 |
|
1198 if (nb_active == 1) { |
|
1199 hw->enabled = 0; |
|
1200 hw->pcm_ops->ctl_in (hw, VOICE_DISABLE); |
|
1201 } |
|
1202 } |
|
1203 } |
|
1204 sw->active = on; |
|
1205 } |
|
1206 } |
|
1207 |
|
1208 static int audio_get_avail (SWVoiceIn *sw) |
|
1209 { |
|
1210 int live; |
|
1211 |
|
1212 if (!sw) { |
|
1213 return 0; |
|
1214 } |
|
1215 |
|
1216 live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired; |
|
1217 if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) { |
|
1218 dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples); |
|
1219 return 0; |
|
1220 } |
|
1221 |
|
1222 ldebug ( |
|
1223 "%s: get_avail live %d ret %" PRId64 "\n", |
|
1224 SW_NAME (sw), |
|
1225 live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift |
|
1226 ); |
|
1227 |
|
1228 return (((int64_t) live << 32) / sw->ratio) << sw->info.shift; |
|
1229 } |
|
1230 |
|
1231 static int audio_get_free (SWVoiceOut *sw) |
|
1232 { |
|
1233 int live, dead; |
|
1234 |
|
1235 if (!sw) { |
|
1236 return 0; |
|
1237 } |
|
1238 |
|
1239 live = sw->total_hw_samples_mixed; |
|
1240 |
|
1241 if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) { |
|
1242 dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples); |
|
1243 return 0; |
|
1244 } |
|
1245 |
|
1246 dead = sw->hw->samples - live; |
|
1247 |
|
1248 #ifdef DEBUG_OUT |
|
1249 dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n", |
|
1250 SW_NAME (sw), |
|
1251 live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift); |
|
1252 #endif |
|
1253 |
|
1254 return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift; |
|
1255 } |
|
1256 |
|
1257 static void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples) |
|
1258 { |
|
1259 int n; |
|
1260 |
|
1261 if (hw->enabled) { |
|
1262 SWVoiceCap *sc; |
|
1263 |
|
1264 for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { |
|
1265 SWVoiceOut *sw = &sc->sw; |
|
1266 int rpos2 = rpos; |
|
1267 |
|
1268 n = samples; |
|
1269 while (n) { |
|
1270 int till_end_of_hw = hw->samples - rpos2; |
|
1271 int to_write = audio_MIN (till_end_of_hw, n); |
|
1272 int bytes = to_write << hw->info.shift; |
|
1273 int written; |
|
1274 |
|
1275 sw->buf = hw->mix_buf + rpos2; |
|
1276 written = audio_pcm_sw_write (sw, NULL, bytes); |
|
1277 if (written - bytes) { |
|
1278 dolog ("Could not mix %d bytes into a capture " |
|
1279 "buffer, mixed %d\n", |
|
1280 bytes, written); |
|
1281 break; |
|
1282 } |
|
1283 n -= to_write; |
|
1284 rpos2 = (rpos2 + to_write) % hw->samples; |
|
1285 } |
|
1286 } |
|
1287 } |
|
1288 |
|
1289 n = audio_MIN (samples, hw->samples - rpos); |
|
1290 mixeng_clear (hw->mix_buf + rpos, n); |
|
1291 mixeng_clear (hw->mix_buf, samples - n); |
|
1292 } |
|
1293 |
|
1294 static void audio_run_out (AudioState *s) |
|
1295 { |
|
1296 HWVoiceOut *hw = NULL; |
|
1297 SWVoiceOut *sw; |
|
1298 |
|
1299 while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) { |
|
1300 int played; |
|
1301 int live, free, nb_live, cleanup_required, prev_rpos; |
|
1302 |
|
1303 live = audio_pcm_hw_get_live_out2 (hw, &nb_live); |
|
1304 if (!nb_live) { |
|
1305 live = 0; |
|
1306 } |
|
1307 |
|
1308 if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { |
|
1309 dolog ("live=%d hw->samples=%d\n", live, hw->samples); |
|
1310 continue; |
|
1311 } |
|
1312 |
|
1313 if (hw->pending_disable && !nb_live) { |
|
1314 SWVoiceCap *sc; |
|
1315 #ifdef DEBUG_OUT |
|
1316 dolog ("Disabling voice\n"); |
|
1317 #endif |
|
1318 hw->enabled = 0; |
|
1319 hw->pending_disable = 0; |
|
1320 hw->pcm_ops->ctl_out (hw, VOICE_DISABLE); |
|
1321 for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { |
|
1322 sc->sw.active = 0; |
|
1323 audio_recalc_and_notify_capture (sc->cap); |
|
1324 } |
|
1325 continue; |
|
1326 } |
|
1327 |
|
1328 if (!live) { |
|
1329 for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { |
|
1330 if (sw->active) { |
|
1331 free = audio_get_free (sw); |
|
1332 if (free > 0) { |
|
1333 sw->callback.fn (sw->callback.opaque, free); |
|
1334 } |
|
1335 } |
|
1336 } |
|
1337 continue; |
|
1338 } |
|
1339 |
|
1340 prev_rpos = hw->rpos; |
|
1341 played = hw->pcm_ops->run_out (hw); |
|
1342 if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) { |
|
1343 dolog ("hw->rpos=%d hw->samples=%d played=%d\n", |
|
1344 hw->rpos, hw->samples, played); |
|
1345 hw->rpos = 0; |
|
1346 } |
|
1347 |
|
1348 #ifdef DEBUG_OUT |
|
1349 dolog ("played=%d\n", played); |
|
1350 #endif |
|
1351 |
|
1352 if (played) { |
|
1353 hw->ts_helper += played; |
|
1354 audio_capture_mix_and_clear (hw, prev_rpos, played); |
|
1355 } |
|
1356 |
|
1357 cleanup_required = 0; |
|
1358 for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { |
|
1359 if (!sw->active && sw->empty) { |
|
1360 continue; |
|
1361 } |
|
1362 |
|
1363 if (audio_bug (AUDIO_FUNC, played > sw->total_hw_samples_mixed)) { |
|
1364 dolog ("played=%d sw->total_hw_samples_mixed=%d\n", |
|
1365 played, sw->total_hw_samples_mixed); |
|
1366 played = sw->total_hw_samples_mixed; |
|
1367 } |
|
1368 |
|
1369 sw->total_hw_samples_mixed -= played; |
|
1370 |
|
1371 if (!sw->total_hw_samples_mixed) { |
|
1372 sw->empty = 1; |
|
1373 cleanup_required |= !sw->active && !sw->callback.fn; |
|
1374 } |
|
1375 |
|
1376 if (sw->active) { |
|
1377 free = audio_get_free (sw); |
|
1378 if (free > 0) { |
|
1379 sw->callback.fn (sw->callback.opaque, free); |
|
1380 } |
|
1381 } |
|
1382 } |
|
1383 |
|
1384 if (cleanup_required) { |
|
1385 SWVoiceOut *sw1; |
|
1386 |
|
1387 sw = hw->sw_head.lh_first; |
|
1388 while (sw) { |
|
1389 sw1 = sw->entries.le_next; |
|
1390 if (!sw->active && !sw->callback.fn) { |
|
1391 #ifdef DEBUG_PLIVE |
|
1392 dolog ("Finishing with old voice\n"); |
|
1393 #endif |
|
1394 audio_close_out (s, sw); |
|
1395 } |
|
1396 sw = sw1; |
|
1397 } |
|
1398 } |
|
1399 } |
|
1400 } |
|
1401 |
|
1402 static void audio_run_in (AudioState *s) |
|
1403 { |
|
1404 HWVoiceIn *hw = NULL; |
|
1405 |
|
1406 while ((hw = audio_pcm_hw_find_any_enabled_in (s, hw))) { |
|
1407 SWVoiceIn *sw; |
|
1408 int captured, min; |
|
1409 |
|
1410 captured = hw->pcm_ops->run_in (hw); |
|
1411 |
|
1412 min = audio_pcm_hw_find_min_in (hw); |
|
1413 hw->total_samples_captured += captured - min; |
|
1414 hw->ts_helper += captured; |
|
1415 |
|
1416 for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { |
|
1417 sw->total_hw_samples_acquired -= min; |
|
1418 |
|
1419 if (sw->active) { |
|
1420 int avail; |
|
1421 |
|
1422 avail = audio_get_avail (sw); |
|
1423 if (avail > 0) { |
|
1424 sw->callback.fn (sw->callback.opaque, avail); |
|
1425 } |
|
1426 } |
|
1427 } |
|
1428 } |
|
1429 } |
|
1430 |
|
1431 static void audio_run_capture (AudioState *s) |
|
1432 { |
|
1433 CaptureVoiceOut *cap; |
|
1434 |
|
1435 for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) { |
|
1436 int live, rpos, captured; |
|
1437 HWVoiceOut *hw = &cap->hw; |
|
1438 SWVoiceOut *sw; |
|
1439 |
|
1440 captured = live = audio_pcm_hw_get_live_out (hw); |
|
1441 rpos = hw->rpos; |
|
1442 while (live) { |
|
1443 int left = hw->samples - rpos; |
|
1444 int to_capture = audio_MIN (live, left); |
|
1445 struct st_sample *src; |
|
1446 struct capture_callback *cb; |
|
1447 |
|
1448 src = hw->mix_buf + rpos; |
|
1449 hw->clip (cap->buf, src, to_capture); |
|
1450 mixeng_clear (src, to_capture); |
|
1451 |
|
1452 for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { |
|
1453 cb->ops.capture (cb->opaque, cap->buf, |
|
1454 to_capture << hw->info.shift); |
|
1455 } |
|
1456 rpos = (rpos + to_capture) % hw->samples; |
|
1457 live -= to_capture; |
|
1458 } |
|
1459 hw->rpos = rpos; |
|
1460 |
|
1461 for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { |
|
1462 if (!sw->active && sw->empty) { |
|
1463 continue; |
|
1464 } |
|
1465 |
|
1466 if (audio_bug (AUDIO_FUNC, captured > sw->total_hw_samples_mixed)) { |
|
1467 dolog ("captured=%d sw->total_hw_samples_mixed=%d\n", |
|
1468 captured, sw->total_hw_samples_mixed); |
|
1469 captured = sw->total_hw_samples_mixed; |
|
1470 } |
|
1471 |
|
1472 sw->total_hw_samples_mixed -= captured; |
|
1473 sw->empty = sw->total_hw_samples_mixed == 0; |
|
1474 } |
|
1475 } |
|
1476 } |
|
1477 |
|
1478 static void audio_timer (void *opaque) |
|
1479 { |
|
1480 AudioState *s = opaque; |
|
1481 |
|
1482 audio_run_out (s); |
|
1483 audio_run_in (s); |
|
1484 audio_run_capture (s); |
|
1485 |
|
1486 qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks); |
|
1487 } |
|
1488 |
|
1489 static struct audio_option audio_options[] = { |
|
1490 /* DAC */ |
|
1491 {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled, |
|
1492 "Use fixed settings for host DAC", NULL, 0}, |
|
1493 |
|
1494 {"DAC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_out.settings.freq, |
|
1495 "Frequency for fixed host DAC", NULL, 0}, |
|
1496 |
|
1497 {"DAC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_out.settings.fmt, |
|
1498 "Format for fixed host DAC", NULL, 0}, |
|
1499 |
|
1500 {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_out.settings.nchannels, |
|
1501 "Number of channels for fixed DAC (1 - mono, 2 - stereo)", NULL, 0}, |
|
1502 |
|
1503 {"DAC_VOICES", AUD_OPT_INT, &conf.fixed_out.nb_voices, |
|
1504 "Number of voices for DAC", NULL, 0}, |
|
1505 |
|
1506 /* ADC */ |
|
1507 {"ADC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_in.enabled, |
|
1508 "Use fixed settings for host ADC", NULL, 0}, |
|
1509 |
|
1510 {"ADC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_in.settings.freq, |
|
1511 "Frequency for fixed host ADC", NULL, 0}, |
|
1512 |
|
1513 {"ADC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_in.settings.fmt, |
|
1514 "Format for fixed host ADC", NULL, 0}, |
|
1515 |
|
1516 {"ADC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_in.settings.nchannels, |
|
1517 "Number of channels for fixed ADC (1 - mono, 2 - stereo)", NULL, 0}, |
|
1518 |
|
1519 {"ADC_VOICES", AUD_OPT_INT, &conf.fixed_in.nb_voices, |
|
1520 "Number of voices for ADC", NULL, 0}, |
|
1521 |
|
1522 /* Misc */ |
|
1523 {"TIMER_PERIOD", AUD_OPT_INT, &conf.period.hertz, |
|
1524 "Timer period in HZ (0 - use lowest possible)", NULL, 0}, |
|
1525 |
|
1526 {"PLIVE", AUD_OPT_BOOL, &conf.plive, |
|
1527 "(undocumented)", NULL, 0}, |
|
1528 |
|
1529 {"LOG_TO_MONITOR", AUD_OPT_BOOL, &conf.log_to_monitor, |
|
1530 "print logging messages to monitor instead of stderr", NULL, 0}, |
|
1531 |
|
1532 {NULL, 0, NULL, NULL, NULL, 0} |
|
1533 }; |
|
1534 |
|
1535 static void audio_pp_nb_voices (const char *typ, int nb) |
|
1536 { |
|
1537 switch (nb) { |
|
1538 case 0: |
|
1539 printf ("Does not support %s\n", typ); |
|
1540 break; |
|
1541 case 1: |
|
1542 printf ("One %s voice\n", typ); |
|
1543 break; |
|
1544 case INT_MAX: |
|
1545 printf ("Theoretically supports many %s voices\n", typ); |
|
1546 break; |
|
1547 default: |
|
1548 printf ("Theoretically supports upto %d %s voices\n", nb, typ); |
|
1549 break; |
|
1550 } |
|
1551 |
|
1552 } |
|
1553 |
|
1554 void AUD_help (void) |
|
1555 { |
|
1556 size_t i; |
|
1557 |
|
1558 audio_process_options ("AUDIO", audio_options); |
|
1559 for (i = 0; i < ARRAY_SIZE (drvtab); i++) { |
|
1560 struct audio_driver *d = drvtab[i]; |
|
1561 if (d->options) { |
|
1562 audio_process_options (d->name, d->options); |
|
1563 } |
|
1564 } |
|
1565 |
|
1566 printf ("Audio options:\n"); |
|
1567 audio_print_options ("AUDIO", audio_options); |
|
1568 printf ("\n"); |
|
1569 |
|
1570 printf ("Available drivers:\n"); |
|
1571 |
|
1572 for (i = 0; i < ARRAY_SIZE (drvtab); i++) { |
|
1573 struct audio_driver *d = drvtab[i]; |
|
1574 |
|
1575 printf ("Name: %s\n", d->name); |
|
1576 printf ("Description: %s\n", d->descr); |
|
1577 |
|
1578 audio_pp_nb_voices ("playback", d->max_voices_out); |
|
1579 audio_pp_nb_voices ("capture", d->max_voices_in); |
|
1580 |
|
1581 if (d->options) { |
|
1582 printf ("Options:\n"); |
|
1583 audio_print_options (d->name, d->options); |
|
1584 } |
|
1585 else { |
|
1586 printf ("No options\n"); |
|
1587 } |
|
1588 printf ("\n"); |
|
1589 } |
|
1590 |
|
1591 printf ( |
|
1592 "Options are settable through environment variables.\n" |
|
1593 "Example:\n" |
|
1594 #ifdef _WIN32 |
|
1595 " set QEMU_AUDIO_DRV=wav\n" |
|
1596 " set QEMU_WAV_PATH=c:\\tune.wav\n" |
|
1597 #else |
|
1598 " export QEMU_AUDIO_DRV=wav\n" |
|
1599 " export QEMU_WAV_PATH=$HOME/tune.wav\n" |
|
1600 "(for csh replace export with setenv in the above)\n" |
|
1601 #endif |
|
1602 " qemu ...\n\n" |
|
1603 ); |
|
1604 } |
|
1605 |
|
1606 static int audio_driver_init (AudioState *s, struct audio_driver *drv) |
|
1607 { |
|
1608 if (drv->options) { |
|
1609 audio_process_options (drv->name, drv->options); |
|
1610 } |
|
1611 s->drv_opaque = drv->init (); |
|
1612 |
|
1613 if (s->drv_opaque) { |
|
1614 audio_init_nb_voices_out (s, drv); |
|
1615 audio_init_nb_voices_in (s, drv); |
|
1616 s->drv = drv; |
|
1617 return 0; |
|
1618 } |
|
1619 else { |
|
1620 dolog ("Could not init `%s' audio driver\n", drv->name); |
|
1621 return -1; |
|
1622 } |
|
1623 } |
|
1624 |
|
1625 static void audio_vm_change_state_handler (void *opaque, int running) |
|
1626 { |
|
1627 AudioState *s = opaque; |
|
1628 HWVoiceOut *hwo = NULL; |
|
1629 HWVoiceIn *hwi = NULL; |
|
1630 int op = running ? VOICE_ENABLE : VOICE_DISABLE; |
|
1631 |
|
1632 while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) { |
|
1633 hwo->pcm_ops->ctl_out (hwo, op); |
|
1634 } |
|
1635 |
|
1636 while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) { |
|
1637 hwi->pcm_ops->ctl_in (hwi, op); |
|
1638 } |
|
1639 } |
|
1640 |
|
1641 static void audio_atexit (void) |
|
1642 { |
|
1643 AudioState *s = &glob_audio_state; |
|
1644 HWVoiceOut *hwo = NULL; |
|
1645 HWVoiceIn *hwi = NULL; |
|
1646 |
|
1647 while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) { |
|
1648 SWVoiceCap *sc; |
|
1649 |
|
1650 hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); |
|
1651 hwo->pcm_ops->fini_out (hwo); |
|
1652 |
|
1653 for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) { |
|
1654 CaptureVoiceOut *cap = sc->cap; |
|
1655 struct capture_callback *cb; |
|
1656 |
|
1657 for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { |
|
1658 cb->ops.destroy (cb->opaque); |
|
1659 } |
|
1660 } |
|
1661 } |
|
1662 |
|
1663 while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) { |
|
1664 hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); |
|
1665 hwi->pcm_ops->fini_in (hwi); |
|
1666 } |
|
1667 |
|
1668 if (s->drv) { |
|
1669 s->drv->fini (s->drv_opaque); |
|
1670 } |
|
1671 } |
|
1672 |
|
1673 static void audio_save (QEMUFile *f, void *opaque) |
|
1674 { |
|
1675 (void) f; |
|
1676 (void) opaque; |
|
1677 } |
|
1678 |
|
1679 static int audio_load (QEMUFile *f, void *opaque, int version_id) |
|
1680 { |
|
1681 (void) f; |
|
1682 (void) opaque; |
|
1683 |
|
1684 if (version_id != 1) { |
|
1685 return -EINVAL; |
|
1686 } |
|
1687 |
|
1688 return 0; |
|
1689 } |
|
1690 |
|
1691 void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card) |
|
1692 { |
|
1693 card->audio = s; |
|
1694 card->name = qemu_strdup (name); |
|
1695 memset (&card->entries, 0, sizeof (card->entries)); |
|
1696 LIST_INSERT_HEAD (&s->card_head, card, entries); |
|
1697 } |
|
1698 |
|
1699 void AUD_remove_card (QEMUSoundCard *card) |
|
1700 { |
|
1701 LIST_REMOVE (card, entries); |
|
1702 card->audio = NULL; |
|
1703 qemu_free (card->name); |
|
1704 } |
|
1705 |
|
1706 AudioState *AUD_init (void) |
|
1707 { |
|
1708 size_t i; |
|
1709 int done = 0; |
|
1710 const char *drvname; |
|
1711 AudioState *s = &glob_audio_state; |
|
1712 |
|
1713 LIST_INIT (&s->hw_head_out); |
|
1714 LIST_INIT (&s->hw_head_in); |
|
1715 LIST_INIT (&s->cap_head); |
|
1716 atexit (audio_atexit); |
|
1717 |
|
1718 s->ts = qemu_new_timer (vm_clock, audio_timer, s); |
|
1719 if (!s->ts) { |
|
1720 dolog ("Could not create audio timer\n"); |
|
1721 return NULL; |
|
1722 } |
|
1723 |
|
1724 audio_process_options ("AUDIO", audio_options); |
|
1725 |
|
1726 s->nb_hw_voices_out = conf.fixed_out.nb_voices; |
|
1727 s->nb_hw_voices_in = conf.fixed_in.nb_voices; |
|
1728 |
|
1729 if (s->nb_hw_voices_out <= 0) { |
|
1730 dolog ("Bogus number of playback voices %d, setting to 1\n", |
|
1731 s->nb_hw_voices_out); |
|
1732 s->nb_hw_voices_out = 1; |
|
1733 } |
|
1734 |
|
1735 if (s->nb_hw_voices_in <= 0) { |
|
1736 dolog ("Bogus number of capture voices %d, setting to 0\n", |
|
1737 s->nb_hw_voices_in); |
|
1738 s->nb_hw_voices_in = 0; |
|
1739 } |
|
1740 |
|
1741 { |
|
1742 int def; |
|
1743 drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def); |
|
1744 } |
|
1745 |
|
1746 if (drvname) { |
|
1747 int found = 0; |
|
1748 |
|
1749 for (i = 0; i < ARRAY_SIZE (drvtab); i++) { |
|
1750 if (!strcmp (drvname, drvtab[i]->name)) { |
|
1751 done = !audio_driver_init (s, drvtab[i]); |
|
1752 found = 1; |
|
1753 break; |
|
1754 } |
|
1755 } |
|
1756 |
|
1757 if (!found) { |
|
1758 dolog ("Unknown audio driver `%s'\n", drvname); |
|
1759 dolog ("Run with -audio-help to list available drivers\n"); |
|
1760 } |
|
1761 } |
|
1762 |
|
1763 if (!done) { |
|
1764 for (i = 0; !done && i < ARRAY_SIZE (drvtab); i++) { |
|
1765 if (drvtab[i]->can_be_default) { |
|
1766 done = !audio_driver_init (s, drvtab[i]); |
|
1767 } |
|
1768 } |
|
1769 } |
|
1770 |
|
1771 if (!done) { |
|
1772 done = !audio_driver_init (s, &no_audio_driver); |
|
1773 if (!done) { |
|
1774 dolog ("Could not initialize audio subsystem\n"); |
|
1775 } |
|
1776 else { |
|
1777 dolog ("warning: Using timer based audio emulation\n"); |
|
1778 } |
|
1779 } |
|
1780 |
|
1781 if (done) { |
|
1782 VMChangeStateEntry *e; |
|
1783 |
|
1784 if (conf.period.hertz <= 0) { |
|
1785 if (conf.period.hertz < 0) { |
|
1786 dolog ("warning: Timer period is negative - %d " |
|
1787 "treating as zero\n", |
|
1788 conf.period.hertz); |
|
1789 } |
|
1790 conf.period.ticks = 1; |
|
1791 } |
|
1792 else { |
|
1793 conf.period.ticks = ticks_per_sec / conf.period.hertz; |
|
1794 } |
|
1795 |
|
1796 e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s); |
|
1797 if (!e) { |
|
1798 dolog ("warning: Could not register change state handler\n" |
|
1799 "(Audio can continue looping even after stopping the VM)\n"); |
|
1800 } |
|
1801 } |
|
1802 else { |
|
1803 qemu_del_timer (s->ts); |
|
1804 return NULL; |
|
1805 } |
|
1806 |
|
1807 LIST_INIT (&s->card_head); |
|
1808 register_savevm ("audio", 0, 1, audio_save, audio_load, s); |
|
1809 qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks); |
|
1810 return s; |
|
1811 } |
|
1812 |
|
1813 CaptureVoiceOut *AUD_add_capture ( |
|
1814 AudioState *s, |
|
1815 struct audsettings *as, |
|
1816 struct audio_capture_ops *ops, |
|
1817 void *cb_opaque |
|
1818 ) |
|
1819 { |
|
1820 CaptureVoiceOut *cap; |
|
1821 struct capture_callback *cb; |
|
1822 |
|
1823 if (!s) { |
|
1824 /* XXX suppress */ |
|
1825 s = &glob_audio_state; |
|
1826 } |
|
1827 |
|
1828 if (audio_validate_settings (as)) { |
|
1829 dolog ("Invalid settings were passed when trying to add capture\n"); |
|
1830 audio_print_settings (as); |
|
1831 goto err0; |
|
1832 } |
|
1833 |
|
1834 cb = audio_calloc (AUDIO_FUNC, 1, sizeof (*cb)); |
|
1835 if (!cb) { |
|
1836 dolog ("Could not allocate capture callback information, size %zu\n", |
|
1837 sizeof (*cb)); |
|
1838 goto err0; |
|
1839 } |
|
1840 cb->ops = *ops; |
|
1841 cb->opaque = cb_opaque; |
|
1842 |
|
1843 cap = audio_pcm_capture_find_specific (s, as); |
|
1844 if (cap) { |
|
1845 LIST_INSERT_HEAD (&cap->cb_head, cb, entries); |
|
1846 return cap; |
|
1847 } |
|
1848 else { |
|
1849 HWVoiceOut *hw; |
|
1850 CaptureVoiceOut *cap; |
|
1851 |
|
1852 cap = audio_calloc (AUDIO_FUNC, 1, sizeof (*cap)); |
|
1853 if (!cap) { |
|
1854 dolog ("Could not allocate capture voice, size %zu\n", |
|
1855 sizeof (*cap)); |
|
1856 goto err1; |
|
1857 } |
|
1858 |
|
1859 hw = &cap->hw; |
|
1860 LIST_INIT (&hw->sw_head); |
|
1861 LIST_INIT (&cap->cb_head); |
|
1862 |
|
1863 /* XXX find a more elegant way */ |
|
1864 hw->samples = 4096 * 4; |
|
1865 hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples, |
|
1866 sizeof (struct st_sample)); |
|
1867 if (!hw->mix_buf) { |
|
1868 dolog ("Could not allocate capture mix buffer (%d samples)\n", |
|
1869 hw->samples); |
|
1870 goto err2; |
|
1871 } |
|
1872 |
|
1873 audio_pcm_init_info (&hw->info, as); |
|
1874 |
|
1875 cap->buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); |
|
1876 if (!cap->buf) { |
|
1877 dolog ("Could not allocate capture buffer " |
|
1878 "(%d samples, each %d bytes)\n", |
|
1879 hw->samples, 1 << hw->info.shift); |
|
1880 goto err3; |
|
1881 } |
|
1882 |
|
1883 hw->clip = mixeng_clip |
|
1884 [hw->info.nchannels == 2] |
|
1885 [hw->info.sign] |
|
1886 [hw->info.swap_endianness] |
|
1887 [audio_bits_to_index (hw->info.bits)]; |
|
1888 |
|
1889 LIST_INSERT_HEAD (&s->cap_head, cap, entries); |
|
1890 LIST_INSERT_HEAD (&cap->cb_head, cb, entries); |
|
1891 |
|
1892 hw = NULL; |
|
1893 while ((hw = audio_pcm_hw_find_any_out (s, hw))) { |
|
1894 audio_attach_capture (s, hw); |
|
1895 } |
|
1896 return cap; |
|
1897 |
|
1898 err3: |
|
1899 qemu_free (cap->hw.mix_buf); |
|
1900 err2: |
|
1901 qemu_free (cap); |
|
1902 err1: |
|
1903 qemu_free (cb); |
|
1904 err0: |
|
1905 return NULL; |
|
1906 } |
|
1907 } |
|
1908 |
|
1909 void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque) |
|
1910 { |
|
1911 struct capture_callback *cb; |
|
1912 |
|
1913 for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { |
|
1914 if (cb->opaque == cb_opaque) { |
|
1915 cb->ops.destroy (cb_opaque); |
|
1916 LIST_REMOVE (cb, entries); |
|
1917 qemu_free (cb); |
|
1918 |
|
1919 if (!cap->cb_head.lh_first) { |
|
1920 SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1; |
|
1921 |
|
1922 while (sw) { |
|
1923 SWVoiceCap *sc = (SWVoiceCap *) sw; |
|
1924 #ifdef DEBUG_CAPTURE |
|
1925 dolog ("freeing %s\n", sw->name); |
|
1926 #endif |
|
1927 |
|
1928 sw1 = sw->entries.le_next; |
|
1929 if (sw->rate) { |
|
1930 st_rate_stop (sw->rate); |
|
1931 sw->rate = NULL; |
|
1932 } |
|
1933 LIST_REMOVE (sw, entries); |
|
1934 LIST_REMOVE (sc, entries); |
|
1935 qemu_free (sc); |
|
1936 sw = sw1; |
|
1937 } |
|
1938 LIST_REMOVE (cap, entries); |
|
1939 qemu_free (cap); |
|
1940 } |
|
1941 return; |
|
1942 } |
|
1943 } |
|
1944 } |
|
1945 |
|
1946 void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol) |
|
1947 { |
|
1948 if (sw) { |
|
1949 sw->vol.mute = mute; |
|
1950 sw->vol.l = nominal_volume.l * lvol / 255; |
|
1951 sw->vol.r = nominal_volume.r * rvol / 255; |
|
1952 } |
|
1953 } |
|
1954 |
|
1955 void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol) |
|
1956 { |
|
1957 if (sw) { |
|
1958 sw->vol.mute = mute; |
|
1959 sw->vol.l = nominal_volume.l * lvol / 255; |
|
1960 sw->vol.r = nominal_volume.r * rvol / 255; |
|
1961 } |
|
1962 } |