VirtualBox

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

最後變更 在這個檔案從5922是 5754,由 vboxsync 提交於 17 年 前

Solaris audio driver, work in progress.

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

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