VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/audio.c@ 355

Last change on this file since 355 was 355, checked in by vboxsync, 18 years ago

activated soft volume mixing

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette