VirtualBox

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

Last change on this file since 217 was 1, checked in by vboxsync, 55 years ago

import

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

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