VirtualBox

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

Last change on this file since 35533 was 35533, checked in by vboxsync, 14 years ago

Audio: missed part of clean up.

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