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