summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-06-15 16:15:32 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-06-15 16:15:32 +0100
commitb500e4db8e3e0b5f41a2dd14e2001200e5fc7d6b (patch)
tree02cafbbc6317e821ff89dc1976fc79a30247f306
parent46bca5404b08201bb9df1ac32bc88fc7e6db1f74 (diff)
parentd95d7d802c33f6277c9fb967c14ae0cc99aeb072 (diff)
downloadqemu-b500e4db8e3e0b5f41a2dd14e2001200e5fc7d6b.tar.gz
Merge remote-tracking branch 'remotes/kraxel/tags/pull-audio-20150615-1' into staging
audio: remove obsolete backends (esd, fmod, winwave). audio: stop using global variables, small fixes. audio: remove some obsolte and unused code. # gpg: Signature made Mon Jun 15 13:24:44 2015 BST using RSA key ID D3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" * remotes/kraxel/tags/pull-audio-20150615-1: ossaudio: use trace events instead of debug config flag alsaaudio: use trace events instead of verbose dsoundaudio: remove primary buffer dsoundaudio: remove *_retries kludges audio: remove plive audio: remove LOG_TO_MONITOR along with default_mon MAINTAINERS: remove malc from audio sdlaudio: do not allow multiple instances coreaudio: do not use global variables where possible dsoundaudio: do not use global variables paaudio: fix possible resource leak wavaudio: do not use global variables ossaudio: do not use global variables alsaaudio: do not use global variables paaudio: do not use global variables audio: expose drv_opaque to init_out and init_in only enable dsound in case the header file is present audio: remove winwave audio driver audio: remove fmod backend audio: remove esd backend Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS1
-rw-r--r--audio/Makefile.objs4
-rw-r--r--audio/alsaaudio.c179
-rw-r--r--audio/audio.c35
-rw-r--r--audio/audio_int.h7
-rw-r--r--audio/audio_template.h43
-rw-r--r--audio/coreaudio.c46
-rw-r--r--audio/dsound_template.h51
-rw-r--r--audio/dsoundaudio.c238
-rw-r--r--audio/esdaudio.c557
-rw-r--r--audio/fmodaudio.c685
-rw-r--r--audio/noaudio.c4
-rw-r--r--audio/ossaudio.c126
-rw-r--r--audio/paaudio.c105
-rw-r--r--audio/sdlaudio.c10
-rw-r--r--audio/spiceaudio.c5
-rw-r--r--audio/wavaudio.c42
-rw-r--r--audio/winwaveaudio.c717
-rwxr-xr-xconfigure68
-rw-r--r--include/monitor/monitor.h1
-rw-r--r--monitor.c4
-rw-r--r--trace-events16
22 files changed, 382 insertions, 2562 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index e728d3a1d2..7ba2079c35 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -770,7 +770,6 @@ F: hw/net/rocker/
Subsystems
----------
Audio
-M: Vassili Karpov (malc) <av1474@comtv.ru>
M: Gerd Hoffmann <kraxel@redhat.com>
S: Maintained
F: audio/
diff --git a/audio/Makefile.objs b/audio/Makefile.objs
index 26a0ac9507..481d1aa30e 100644
--- a/audio/Makefile.objs
+++ b/audio/Makefile.objs
@@ -5,13 +5,9 @@ common-obj-$(CONFIG_SPICE) += spiceaudio.o
common-obj-$(CONFIG_COREAUDIO) += coreaudio.o
common-obj-$(CONFIG_ALSA) += alsaaudio.o
common-obj-$(CONFIG_DSOUND) += dsoundaudio.o
-common-obj-$(CONFIG_FMOD) += fmodaudio.o
-common-obj-$(CONFIG_ESD) += esdaudio.o
common-obj-$(CONFIG_PA) += paaudio.o
-common-obj-$(CONFIG_WINWAVE) += winwaveaudio.o
common-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o
common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
common-obj-y += wavcapture.o
-$(obj)/audio.o $(obj)/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
sdlaudio.o-cflags := $(SDL_CFLAGS)
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index ed7655de86..6315b2d746 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -25,6 +25,7 @@
#include "qemu-common.h"
#include "qemu/main-loop.h"
#include "audio.h"
+#include "trace.h"
#if QEMU_GNUC_PREREQ(4, 3)
#pragma GCC diagnostic ignored "-Waddress"
@@ -33,9 +34,28 @@
#define AUDIO_CAP "alsa"
#include "audio_int.h"
+typedef struct ALSAConf {
+ int size_in_usec_in;
+ int size_in_usec_out;
+ const char *pcm_name_in;
+ const char *pcm_name_out;
+ unsigned int buffer_size_in;
+ unsigned int period_size_in;
+ unsigned int buffer_size_out;
+ unsigned int period_size_out;
+ unsigned int threshold;
+
+ int buffer_size_in_overridden;
+ int period_size_in_overridden;
+
+ int buffer_size_out_overridden;
+ int period_size_out_overridden;
+} ALSAConf;
+
struct pollhlp {
snd_pcm_t *handle;
struct pollfd *pfds;
+ ALSAConf *conf;
int count;
int mask;
};
@@ -56,30 +76,6 @@ typedef struct ALSAVoiceIn {
struct pollhlp pollhlp;
} ALSAVoiceIn;
-static struct {
- int size_in_usec_in;
- int size_in_usec_out;
- const char *pcm_name_in;
- const char *pcm_name_out;
- unsigned int buffer_size_in;
- unsigned int period_size_in;
- unsigned int buffer_size_out;
- unsigned int period_size_out;
- unsigned int threshold;
-
- int buffer_size_in_overridden;
- int period_size_in_overridden;
-
- int buffer_size_out_overridden;
- int period_size_out_overridden;
- int verbose;
-} conf = {
- .buffer_size_out = 4096,
- .period_size_out = 1024,
- .pcm_name_out = "default",
- .pcm_name_in = "default",
-};
-
struct alsa_params_req {
int freq;
snd_pcm_format_t fmt;
@@ -205,9 +201,7 @@ static void alsa_poll_handler (void *opaque)
}
if (!(revents & hlp->mask)) {
- if (conf.verbose) {
- dolog ("revents = %d\n", revents);
- }
+ trace_alsa_revents(revents);
return;
}
@@ -269,15 +263,10 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask)
qemu_set_fd_handler (pfds[i].fd, alsa_poll_handler, NULL, hlp);
}
if (pfds[i].events & POLLOUT) {
- if (conf.verbose) {
- dolog ("POLLOUT %d %d\n", i, pfds[i].fd);
- }
+ trace_alsa_pollout(i, pfds[i].fd);
qemu_set_fd_handler (pfds[i].fd, NULL, alsa_poll_handler, hlp);
}
- if (conf.verbose) {
- dolog ("Set handler events=%#x index=%d fd=%d err=%d\n",
- pfds[i].events, i, pfds[i].fd, err);
- }
+ trace_alsa_set_handler(pfds[i].events, i, pfds[i].fd, err);
}
hlp->pfds = pfds;
@@ -464,14 +453,15 @@ static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
}
static int alsa_open (int in, struct alsa_params_req *req,
- struct alsa_params_obt *obt, snd_pcm_t **handlep)
+ struct alsa_params_obt *obt, snd_pcm_t **handlep,
+ ALSAConf *conf)
{
snd_pcm_t *handle;
snd_pcm_hw_params_t *hw_params;
int err;
int size_in_usec;
unsigned int freq, nchannels;
- const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
+ const char *pcm_name = in ? conf->pcm_name_in : conf->pcm_name_out;
snd_pcm_uframes_t obt_buffer_size;
const char *typ = in ? "ADC" : "DAC";
snd_pcm_format_t obtfmt;
@@ -510,7 +500,7 @@ static int alsa_open (int in, struct alsa_params_req *req,
}
err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
- if (err < 0 && conf.verbose) {
+ if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
}
@@ -642,7 +632,7 @@ static int alsa_open (int in, struct alsa_params_req *req,
goto err;
}
- if (!in && conf.threshold) {
+ if (!in && conf->threshold) {
snd_pcm_uframes_t threshold;
int bytes_per_sec;
@@ -664,7 +654,7 @@ static int alsa_open (int in, struct alsa_params_req *req,
break;
}
- threshold = (conf.threshold * bytes_per_sec) / 1000;
+ threshold = (conf->threshold * bytes_per_sec) / 1000;
alsa_set_threshold (handle, threshold);
}
@@ -674,10 +664,9 @@ static int alsa_open (int in, struct alsa_params_req *req,
*handlep = handle;
- if (conf.verbose &&
- (obtfmt != req->fmt ||
+ if (obtfmt != req->fmt ||
obt->nchannels != req->nchannels ||
- obt->freq != req->freq)) {
+ obt->freq != req->freq) {
dolog ("Audio parameters for %s\n", typ);
alsa_dump_info (req, obt, obtfmt);
}
@@ -731,9 +720,7 @@ static void alsa_write_pending (ALSAVoiceOut *alsa)
if (written <= 0) {
switch (written) {
case 0:
- if (conf.verbose) {
- dolog ("Failed to write %d frames (wrote zero)\n", len);
- }
+ trace_alsa_wrote_zero(len);
return;
case -EPIPE:
@@ -742,9 +729,7 @@ static void alsa_write_pending (ALSAVoiceOut *alsa)
len);
return;
}
- if (conf.verbose) {
- dolog ("Recovering from playback xrun\n");
- }
+ trace_alsa_xrun_out();
continue;
case -ESTRPIPE:
@@ -755,9 +740,7 @@ static void alsa_write_pending (ALSAVoiceOut *alsa)
len);
return;
}
- if (conf.verbose) {
- dolog ("Resuming suspended output stream\n");
- }
+ trace_alsa_resume_out();
continue;
case -EAGAIN:
@@ -807,25 +790,27 @@ static void alsa_fini_out (HWVoiceOut *hw)
alsa->pcm_buf = NULL;
}
-static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
{
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
struct alsa_params_req req;
struct alsa_params_obt obt;
snd_pcm_t *handle;
struct audsettings obt_as;
+ ALSAConf *conf = drv_opaque;
req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
- req.period_size = conf.period_size_out;
- req.buffer_size = conf.buffer_size_out;
- req.size_in_usec = conf.size_in_usec_out;
+ req.period_size = conf->period_size_out;
+ req.buffer_size = conf->buffer_size_out;
+ req.size_in_usec = conf->size_in_usec_out;
req.override_mask =
- (conf.period_size_out_overridden ? 1 : 0) |
- (conf.buffer_size_out_overridden ? 2 : 0);
+ (conf->period_size_out_overridden ? 1 : 0) |
+ (conf->buffer_size_out_overridden ? 2 : 0);
- if (alsa_open (0, &req, &obt, &handle)) {
+ if (alsa_open (0, &req, &obt, &handle, conf)) {
return -1;
}
@@ -846,6 +831,7 @@ static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
}
alsa->handle = handle;
+ alsa->pollhlp.conf = conf;
return 0;
}
@@ -916,25 +902,26 @@ static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
return -1;
}
-static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
{
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
struct alsa_params_req req;
struct alsa_params_obt obt;
snd_pcm_t *handle;
struct audsettings obt_as;
+ ALSAConf *conf = drv_opaque;
req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
- req.period_size = conf.period_size_in;
- req.buffer_size = conf.buffer_size_in;
- req.size_in_usec = conf.size_in_usec_in;
+ req.period_size = conf->period_size_in;
+ req.buffer_size = conf->buffer_size_in;
+ req.size_in_usec = conf->size_in_usec_in;
req.override_mask =
- (conf.period_size_in_overridden ? 1 : 0) |
- (conf.buffer_size_in_overridden ? 2 : 0);
+ (conf->period_size_in_overridden ? 1 : 0) |
+ (conf->buffer_size_in_overridden ? 2 : 0);
- if (alsa_open (1, &req, &obt, &handle)) {
+ if (alsa_open (1, &req, &obt, &handle, conf)) {
return -1;
}
@@ -955,6 +942,7 @@ static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
}
alsa->handle = handle;
+ alsa->pollhlp.conf = conf;
return 0;
}
@@ -1010,14 +998,10 @@ static int alsa_run_in (HWVoiceIn *hw)
dolog ("Failed to resume suspended input stream\n");
return 0;
}
- if (conf.verbose) {
- dolog ("Resuming suspended input stream\n");
- }
+ trace_alsa_resume_in();
break;
default:
- if (conf.verbose) {
- dolog ("No frames available and ALSA state is %d\n", state);
- }
+ trace_alsa_no_frames(state);
return 0;
}
}
@@ -1052,9 +1036,7 @@ static int alsa_run_in (HWVoiceIn *hw)
if (nread <= 0) {
switch (nread) {
case 0:
- if (conf.verbose) {
- dolog ("Failed to read %ld frames (read zero)\n", len);
- }
+ trace_alsa_read_zero(len);
goto exit;
case -EPIPE:
@@ -1062,9 +1044,7 @@ static int alsa_run_in (HWVoiceIn *hw)
alsa_logerr (nread, "Failed to read %ld frames\n", len);
goto exit;
}
- if (conf.verbose) {
- dolog ("Recovering from capture xrun\n");
- }
+ trace_alsa_xrun_in();
continue;
case -EAGAIN:
@@ -1136,82 +1116,85 @@ static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
return -1;
}
+static ALSAConf glob_conf = {
+ .buffer_size_out = 4096,
+ .period_size_out = 1024,
+ .pcm_name_out = "default",
+ .pcm_name_in = "default",
+};
+
static void *alsa_audio_init (void)
{
- return &conf;
+ ALSAConf *conf = g_malloc(sizeof(ALSAConf));
+ *conf = glob_conf;
+ return conf;
}
static void alsa_audio_fini (void *opaque)
{
- (void) opaque;
+ g_free(opaque);
}
static struct audio_option alsa_options[] = {
{
.name = "DAC_SIZE_IN_USEC",
.tag = AUD_OPT_BOOL,
- .valp = &conf.size_in_usec_out,
+ .valp = &glob_conf.size_in_usec_out,
.descr = "DAC period/buffer size in microseconds (otherwise in frames)"
},
{
.name = "DAC_PERIOD_SIZE",
.tag = AUD_OPT_INT,
- .valp = &conf.period_size_out,
+ .valp = &glob_conf.period_size_out,
.descr = "DAC period size (0 to go with system default)",
- .overriddenp = &conf.period_size_out_overridden
+ .overriddenp = &glob_conf.period_size_out_overridden
},
{
.name = "DAC_BUFFER_SIZE",
.tag = AUD_OPT_INT,
- .valp = &conf.buffer_size_out,
+ .valp = &glob_conf.buffer_size_out,
.descr = "DAC buffer size (0 to go with system default)",
- .overriddenp = &conf.buffer_size_out_overridden
+ .overriddenp = &glob_conf.buffer_size_out_overridden
},
{
.name = "ADC_SIZE_IN_USEC",
.tag = AUD_OPT_BOOL,
- .valp = &conf.size_in_usec_in,
+ .valp = &glob_conf.size_in_usec_in,
.descr =
"ADC period/buffer size in microseconds (otherwise in frames)"
},
{
.name = "ADC_PERIOD_SIZE",
.tag = AUD_OPT_INT,
- .valp = &conf.period_size_in,
+ .valp = &glob_conf.period_size_in,
.descr = "ADC period size (0 to go with system default)",
- .overriddenp = &conf.period_size_in_overridden
+ .overriddenp = &glob_conf.period_size_in_overridden
},
{
.name = "ADC_BUFFER_SIZE",
.tag = AUD_OPT_INT,
- .valp = &conf.buffer_size_in,
+ .valp = &glob_conf.buffer_size_in,
.descr = "ADC buffer size (0 to go with system default)",
- .overriddenp = &conf.buffer_size_in_overridden
+ .overriddenp = &glob_conf.buffer_size_in_overridden
},
{
.name = "THRESHOLD",
.tag = AUD_OPT_INT,
- .valp = &conf.threshold,
+ .valp = &glob_conf.threshold,
.descr = "(undocumented)"
},
{
.name = "DAC_DEV",
.tag = AUD_OPT_STR,
- .valp = &conf.pcm_name_out,
+ .valp = &glob_conf.pcm_name_out,
.descr = "DAC device name (for instance dmix)"
},
{
.name = "ADC_DEV",
.tag = AUD_OPT_STR,
- .valp = &conf.pcm_name_in,
+ .valp = &glob_conf.pcm_name_in,
.descr = "ADC device name"
},
- {
- .name = "VERBOSE",
- .tag = AUD_OPT_BOOL,
- .valp = &conf.verbose,
- .descr = "Behave in a more verbose way"
- },
{ /* End of list */ }
};
diff --git a/audio/audio.c b/audio/audio.c
index 9d018e9ded..5be4b15fcf 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -30,7 +30,6 @@
#define AUDIO_CAP "audio"
#include "audio_int.h"
-/* #define DEBUG_PLIVE */
/* #define DEBUG_LIVE */
/* #define DEBUG_OUT */
/* #define DEBUG_CAPTURE */
@@ -66,8 +65,6 @@ static struct {
int hertz;
int64_t ticks;
} period;
- int plive;
- int log_to_monitor;
int try_poll_in;
int try_poll_out;
} conf = {
@@ -96,8 +93,6 @@ static struct {
},
.period = { .hertz = 100 },
- .plive = 0,
- .log_to_monitor = 0,
.try_poll_in = 1,
.try_poll_out = 1,
};
@@ -331,20 +326,11 @@ static const char *audio_get_conf_str (const char *key,
void AUD_vlog (const char *cap, const char *fmt, va_list ap)
{
- if (conf.log_to_monitor) {
- if (cap) {
- monitor_printf(default_mon, "%s: ", cap);
- }
-
- monitor_vprintf(default_mon, fmt, ap);
+ if (cap) {
+ fprintf(stderr, "%s: ", cap);
}
- else {
- if (cap) {
- fprintf (stderr, "%s: ", cap);
- }
- vfprintf (stderr, fmt, ap);
- }
+ vfprintf(stderr, fmt, ap);
}
void AUD_log (const char *cap, const char *fmt, ...)
@@ -1454,9 +1440,6 @@ static void audio_run_out (AudioState *s)
while (sw) {
sw1 = sw->entries.le_next;
if (!sw->active && !sw->callback.fn) {
-#ifdef DEBUG_PLIVE
- dolog ("Finishing with old voice\n");
-#endif
audio_close_out (sw);
}
sw = sw1;
@@ -1648,18 +1631,6 @@ static struct audio_option audio_options[] = {
.valp = &conf.period.hertz,
.descr = "Timer period in HZ (0 - use lowest possible)"
},
- {
- .name = "PLIVE",
- .tag = AUD_OPT_BOOL,
- .valp = &conf.plive,
- .descr = "(undocumented)"
- },
- {
- .name = "LOG_TO_MONITOR",
- .tag = AUD_OPT_BOOL,
- .valp = &conf.log_to_monitor,
- .descr = "Print logging messages to monitor instead of stderr"
- },
{ /* End of list */ }
};
diff --git a/audio/audio_int.h b/audio/audio_int.h
index fd019a0fc3..566df5edf4 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -156,13 +156,13 @@ struct audio_driver {
};
struct audio_pcm_ops {
- int (*init_out)(HWVoiceOut *hw, struct audsettings *as);
+ int (*init_out)(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque);
void (*fini_out)(HWVoiceOut *hw);
int (*run_out) (HWVoiceOut *hw, int live);
int (*write) (SWVoiceOut *sw, void *buf, int size);
int (*ctl_out) (HWVoiceOut *hw, int cmd, ...);
- int (*init_in) (HWVoiceIn *hw, struct audsettings *as);
+ int (*init_in) (HWVoiceIn *hw, struct audsettings *as, void *drv_opaque);
void (*fini_in) (HWVoiceIn *hw);
int (*run_in) (HWVoiceIn *hw);
int (*read) (SWVoiceIn *sw, void *buf, int size);
@@ -206,14 +206,11 @@ extern struct audio_driver no_audio_driver;
extern struct audio_driver oss_audio_driver;
extern struct audio_driver sdl_audio_driver;
extern struct audio_driver wav_audio_driver;
-extern struct audio_driver fmod_audio_driver;
extern struct audio_driver alsa_audio_driver;
extern struct audio_driver coreaudio_audio_driver;
extern struct audio_driver dsound_audio_driver;
-extern struct audio_driver esd_audio_driver;
extern struct audio_driver pa_audio_driver;
extern struct audio_driver spice_audio_driver;
-extern struct audio_driver winwave_audio_driver;
extern const struct mixeng_volume nominal_volume;
void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 584e536fac..99b27b285e 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -262,7 +262,7 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)
#ifdef DAC
QLIST_INIT (&hw->cap_head);
#endif
- if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
+ if (glue (hw->pcm_ops->init_, TYPE) (hw, as, s->drv_opaque)) {
goto err0;
}
@@ -398,10 +398,6 @@ SW *glue (AUD_open_, TYPE) (
)
{
AudioState *s = &glob_audio_state;
-#ifdef DAC
- int live = 0;
- SW *old_sw = NULL;
-#endif
if (audio_bug (AUDIO_FUNC, !card || !name || !callback_fn || !as)) {
dolog ("card=%p name=%p callback_fn=%p as=%p\n",
@@ -426,29 +422,6 @@ SW *glue (AUD_open_, TYPE) (
return sw;
}
-#ifdef DAC
- if (conf.plive && sw && (!sw->active && !sw->empty)) {
- live = sw->total_hw_samples_mixed;
-
-#ifdef DEBUG_PLIVE
- dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live);
- dolog ("Old %s freq %d, bits %d, channels %d\n",
- SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels);
- dolog ("New %s freq %d, bits %d, channels %d\n",
- name,
- as->freq,
- (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) ? 16 : 8,
- as->nchannels);
-#endif
-
- if (live) {
- old_sw = sw;
- old_sw->callback.fn = NULL;
- sw = NULL;
- }
- }
-#endif
-
if (!glue (conf.fixed_, TYPE).enabled && sw) {
glue (AUD_close_, TYPE) (card, sw);
sw = NULL;
@@ -481,20 +454,6 @@ SW *glue (AUD_open_, TYPE) (
sw->callback.fn = callback_fn;
sw->callback.opaque = callback_opaque;
-#ifdef DAC
- if (live) {
- int mixed =
- (live << old_sw->info.shift)
- * old_sw->info.bytes_per_second
- / sw->info.bytes_per_second;
-
-#ifdef DEBUG_PLIVE
- dolog ("Silence will be mixed %d\n", mixed);
-#endif
- sw->total_hw_samples_mixed += mixed;
- }
-#endif
-
#ifdef DEBUG_AUDIO
dolog ("%s\n", name);
audio_pcm_print_info ("hw", &sw->hw->info);
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 5964c62eaf..6dfd63eb42 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -32,20 +32,16 @@
#define AUDIO_CAP "coreaudio"
#include "audio_int.h"
-struct {
+static int isAtexit;
+
+typedef struct {
int buffer_frames;
int nbuffers;
- int isAtexit;
-} conf = {
- .buffer_frames = 512,
- .nbuffers = 4,
- .isAtexit = 0
-};
+} CoreaudioConf;
typedef struct coreaudioVoiceOut {
HWVoiceOut hw;
pthread_mutex_t mutex;
- int isAtexit;
AudioDeviceID outputDeviceID;
UInt32 audioDevicePropertyBufferFrameSize;
AudioStreamBasicDescription outputStreamBasicDescription;
@@ -161,7 +157,7 @@ static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
static void coreaudio_atexit (void)
{
- conf.isAtexit = 1;
+ isAtexit = 1;
}
static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
@@ -287,7 +283,8 @@ static int coreaudio_write (SWVoiceOut *sw, void *buf, int len)
return audio_pcm_sw_write (sw, buf, len);
}
-static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
{
OSStatus status;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
@@ -295,6 +292,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
int err;
const char *typ = "playback";
AudioValueRange frameRange;
+ CoreaudioConf *conf = drv_opaque;
/* create mutex */
err = pthread_mutex_init(&core->mutex, NULL);
@@ -336,16 +334,16 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
return -1;
}
- if (frameRange.mMinimum > conf.buffer_frames) {
+ if (frameRange.mMinimum > conf->buffer_frames) {
core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
}
- else if (frameRange.mMaximum < conf.buffer_frames) {
+ else if (frameRange.mMaximum < conf->buffer_frames) {
core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
}
else {
- core->audioDevicePropertyBufferFrameSize = conf.buffer_frames;
+ core->audioDevicePropertyBufferFrameSize = conf->buffer_frames;
}
/* set Buffer Frame Size */
@@ -379,7 +377,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
"Could not get device buffer frame size\n");
return -1;
}
- hw->samples = conf.nbuffers * core->audioDevicePropertyBufferFrameSize;
+ hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize;
/* get StreamFormat */
propertySize = sizeof(core->outputStreamBasicDescription);
@@ -443,7 +441,7 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
int err;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
- if (!conf.isAtexit) {
+ if (!isAtexit) {
/* stop playback */
if (isPlaying(core->outputDeviceID)) {
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
@@ -486,7 +484,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
case VOICE_DISABLE:
/* stop playback */
- if (!conf.isAtexit) {
+ if (!isAtexit) {
if (isPlaying(core->outputDeviceID)) {
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
if (status != kAudioHardwareNoError) {
@@ -499,28 +497,36 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
return 0;
}
+static CoreaudioConf glob_conf = {
+ .buffer_frames = 512,
+ .nbuffers = 4,
+};
+
static void *coreaudio_audio_init (void)
{
+ CoreaudioConf *conf = g_malloc(sizeof(CoreaudioConf));
+ *conf = glob_conf;
+
atexit(coreaudio_atexit);
- return &coreaudio_audio_init;
+ return conf;
}
static void coreaudio_audio_fini (void *opaque)
{
- (void) opaque;
+ g_free(opaque);
}
static struct audio_option coreaudio_options[] = {
{
.name = "BUFFER_SIZE",
.tag = AUD_OPT_INT,
- .valp = &conf.buffer_frames,
+ .valp = &glob_conf.buffer_frames,
.descr = "Size of the buffer in frames"
},
{
.name = "BUFFER_COUNT",
.tag = AUD_OPT_INT,
- .valp = &conf.nbuffers,
+ .valp = &glob_conf.nbuffers,
.descr = "Number of buffers"
},
{ /* End of list */ }
diff --git a/audio/dsound_template.h b/audio/dsound_template.h
index 8b37d16a8c..b439f33f58 100644
--- a/audio/dsound_template.h
+++ b/audio/dsound_template.h
@@ -67,11 +67,11 @@ static int glue (dsound_lock_, TYPE) (
LPVOID *p2p,
DWORD *blen1p,
DWORD *blen2p,
- int entire
+ int entire,
+ dsound *s
)
{
HRESULT hr;
- int i;
LPVOID p1 = NULL, p2 = NULL;
DWORD blen1 = 0, blen2 = 0;
DWORD flag;
@@ -81,37 +81,18 @@ static int glue (dsound_lock_, TYPE) (
#else
flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
#endif
- for (i = 0; i < conf.lock_retries; ++i) {
- hr = glue (IFACE, _Lock) (
- buf,
- pos,
- len,
- &p1,
- &blen1,
- &p2,
- &blen2,
- flag
- );
+ hr = glue(IFACE, _Lock)(buf, pos, len, &p1, &blen1, &p2, &blen2, flag);
- if (FAILED (hr)) {
+ if (FAILED (hr)) {
#ifndef DSBTYPE_IN
- if (hr == DSERR_BUFFERLOST) {
- if (glue (dsound_restore_, TYPE) (buf)) {
- dsound_logerr (hr, "Could not lock " NAME "\n");
- goto fail;
- }
- continue;
+ if (hr == DSERR_BUFFERLOST) {
+ if (glue (dsound_restore_, TYPE) (buf, s)) {
+ dsound_logerr (hr, "Could not lock " NAME "\n");
}
-#endif
- dsound_logerr (hr, "Could not lock " NAME "\n");
goto fail;
}
-
- break;
- }
-
- if (i == conf.lock_retries) {
- dolog ("%d attempts to lock " NAME " failed\n", i);
+#endif
+ dsound_logerr (hr, "Could not lock " NAME "\n");
goto fail;
}
@@ -174,16 +155,19 @@ static void dsound_fini_out (HWVoiceOut *hw)
}
#ifdef DSBTYPE_IN
-static int dsound_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
+ void *drv_opaque)
#else
-static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
#endif
{
int err;
HRESULT hr;
- dsound *s = &glob_dsound;
+ dsound *s = drv_opaque;
WAVEFORMATEX wfx;
struct audsettings obt_as;
+ DSoundConf *conf = &s->conf;
#ifdef DSBTYPE_IN
const char *typ = "ADC";
DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
@@ -210,7 +194,7 @@ static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
bd.dwSize = sizeof (bd);
bd.lpwfxFormat = &wfx;
#ifdef DSBTYPE_IN
- bd.dwBufferBytes = conf.bufsize_in;
+ bd.dwBufferBytes = conf->bufsize_in;
hr = IDirectSoundCapture_CreateCaptureBuffer (
s->dsound_capture,
&bd,
@@ -219,7 +203,7 @@ static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
);
#else
bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
- bd.dwBufferBytes = conf.bufsize_out;
+ bd.dwBufferBytes = conf->bufsize_out;
hr = IDirectSound_CreateSoundBuffer (
s->dsound,
&bd,
@@ -269,6 +253,7 @@ static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
);
}
hw->samples = bc.dwBufferBytes >> hw->info.shift;
+ ds->s = s;
#ifdef DEBUG_DSOUND
dolog ("caps %ld, desc %ld\n",
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index e2d89fd5d5..e9472c105c 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -41,42 +41,25 @@
/* #define DEBUG_DSOUND */
-static struct {
- int lock_retries;
- int restore_retries;
- int getstatus_retries;
- int set_primary;
+typedef struct {
int bufsize_in;
int bufsize_out;
- struct audsettings settings;
int latency_millis;
-} conf = {
- .lock_retries = 1,
- .restore_retries = 1,
- .getstatus_retries = 1,
- .set_primary = 0,
- .bufsize_in = 16384,
- .bufsize_out = 16384,
- .settings.freq = 44100,
- .settings.nchannels = 2,
- .settings.fmt = AUD_FMT_S16,
- .latency_millis = 10
-};
+} DSoundConf;
typedef struct {
LPDIRECTSOUND dsound;
LPDIRECTSOUNDCAPTURE dsound_capture;
- LPDIRECTSOUNDBUFFER dsound_primary_buffer;
struct audsettings settings;
+ DSoundConf conf;
} dsound;
-static dsound glob_dsound;
-
typedef struct {
HWVoiceOut hw;
LPDIRECTSOUNDBUFFER dsound_buffer;
DWORD old_pos;
int first_time;
+ dsound *s;
#ifdef DEBUG_DSOUND
DWORD old_ppos;
DWORD played;
@@ -88,6 +71,7 @@ typedef struct {
HWVoiceIn hw;
int first_time;
LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
+ dsound *s;
} DSoundVoiceIn;
static void dsound_log_hresult (HRESULT hr)
@@ -281,29 +265,17 @@ static void print_wave_format (WAVEFORMATEX *wfx)
}
#endif
-static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb)
+static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb, dsound *s)
{
HRESULT hr;
- int i;
-
- for (i = 0; i < conf.restore_retries; ++i) {
- hr = IDirectSoundBuffer_Restore (dsb);
-
- switch (hr) {
- case DS_OK:
- return 0;
- case DSERR_BUFFERLOST:
- continue;
+ hr = IDirectSoundBuffer_Restore (dsb);
- default:
- dsound_logerr (hr, "Could not restore playback buffer\n");
- return -1;
- }
+ if (hr != DS_OK) {
+ dsound_logerr (hr, "Could not restore playback buffer\n");
+ return -1;
}
-
- dolog ("%d attempts to restore playback buffer failed\n", i);
- return -1;
+ return 0;
}
#include "dsound_template.h"
@@ -311,25 +283,20 @@ static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb)
#include "dsound_template.h"
#undef DSBTYPE_IN
-static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp)
+static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp,
+ dsound *s)
{
HRESULT hr;
- int i;
- for (i = 0; i < conf.getstatus_retries; ++i) {
- hr = IDirectSoundBuffer_GetStatus (dsb, statusp);
- if (FAILED (hr)) {
- dsound_logerr (hr, "Could not get playback buffer status\n");
- return -1;
- }
+ hr = IDirectSoundBuffer_GetStatus (dsb, statusp);
+ if (FAILED (hr)) {
+ dsound_logerr (hr, "Could not get playback buffer status\n");
+ return -1;
+ }
- if (*statusp & DSERR_BUFFERLOST) {
- if (dsound_restore_out (dsb)) {
- return -1;
- }
- continue;
- }
- break;
+ if (*statusp & DSERR_BUFFERLOST) {
+ dsound_restore_out(dsb, s);
+ return -1;
}
return 0;
@@ -376,7 +343,8 @@ static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
hw->rpos = pos % hw->samples;
}
-static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb)
+static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb,
+ dsound *s)
{
int err;
LPVOID p1, p2;
@@ -389,7 +357,8 @@ static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb)
hw->samples << hw->info.shift,
&p1, &p2,
&blen1, &blen2,
- 1
+ 1,
+ s
);
if (err) {
return;
@@ -415,25 +384,9 @@ static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb)
dsound_unlock_out (dsb, p1, p2, blen1, blen2);
}
-static void dsound_close (dsound *s)
-{
- HRESULT hr;
-
- if (s->dsound_primary_buffer) {
- hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer);
- if (FAILED (hr)) {
- dsound_logerr (hr, "Could not release primary buffer\n");
- }
- s->dsound_primary_buffer = NULL;
- }
-}
-
static int dsound_open (dsound *s)
{
- int err;
HRESULT hr;
- WAVEFORMATEX wfx;
- DSBUFFERDESC dsbd;
HWND hwnd;
hwnd = GetForegroundWindow ();
@@ -449,63 +402,7 @@ static int dsound_open (dsound *s)
return -1;
}
- if (!conf.set_primary) {
- return 0;
- }
-
- err = waveformat_from_audio_settings (&wfx, &conf.settings);
- if (err) {
- return -1;
- }
-
- memset (&dsbd, 0, sizeof (dsbd));
- dsbd.dwSize = sizeof (dsbd);
- dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
- dsbd.dwBufferBytes = 0;
- dsbd.lpwfxFormat = NULL;
-
- hr = IDirectSound_CreateSoundBuffer (
- s->dsound,
- &dsbd,
- &s->dsound_primary_buffer,
- NULL
- );
- if (FAILED (hr)) {
- dsound_logerr (hr, "Could not create primary playback buffer\n");
- return -1;
- }
-
- hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx);
- if (FAILED (hr)) {
- dsound_logerr (hr, "Could not set primary playback buffer format\n");
- }
-
- hr = IDirectSoundBuffer_GetFormat (
- s->dsound_primary_buffer,
- &wfx,
- sizeof (wfx),
- NULL
- );
- if (FAILED (hr)) {
- dsound_logerr (hr, "Could not get primary playback buffer format\n");
- goto fail0;
- }
-
-#ifdef DEBUG_DSOUND
- dolog ("Primary\n");
- print_wave_format (&wfx);
-#endif
-
- err = waveformat_to_audio_settings (&wfx, &s->settings);
- if (err) {
- goto fail0;
- }
-
return 0;
-
- fail0:
- dsound_close (s);
- return -1;
}
static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
@@ -514,6 +411,7 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
DWORD status;
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
+ dsound *s = ds->s;
if (!dsb) {
dolog ("Attempt to control voice without a buffer\n");
@@ -522,7 +420,7 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
switch (cmd) {
case VOICE_ENABLE:
- if (dsound_get_status_out (dsb, &status)) {
+ if (dsound_get_status_out (dsb, &status, s)) {
return -1;
}
@@ -531,7 +429,7 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
return 0;
}
- dsound_clear_sample (hw, dsb);
+ dsound_clear_sample (hw, dsb, s);
hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING);
if (FAILED (hr)) {
@@ -541,7 +439,7 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
break;
case VOICE_DISABLE:
- if (dsound_get_status_out (dsb, &status)) {
+ if (dsound_get_status_out (dsb, &status, s)) {
return -1;
}
@@ -578,6 +476,8 @@ static int dsound_run_out (HWVoiceOut *hw, int live)
DWORD wpos, ppos, old_pos;
LPVOID p1, p2;
int bufsize;
+ dsound *s = ds->s;
+ DSoundConf *conf = &s->conf;
if (!dsb) {
dolog ("Attempt to run empty with playback buffer\n");
@@ -600,14 +500,14 @@ static int dsound_run_out (HWVoiceOut *hw, int live)
len = live << hwshift;
if (ds->first_time) {
- if (conf.latency_millis) {
+ if (conf->latency_millis) {
DWORD cur_blat;
cur_blat = audio_ring_dist (wpos, ppos, bufsize);
ds->first_time = 0;
old_pos = wpos;
old_pos +=
- millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat;
+ millis_to_bytes (&hw->info, conf->latency_millis) - cur_blat;
old_pos %= bufsize;
old_pos &= ~hw->info.align;
}
@@ -663,7 +563,8 @@ static int dsound_run_out (HWVoiceOut *hw, int live)
len,
&p1, &p2,
&blen1, &blen2,
- 0
+ 0,
+ s
);
if (err) {
return 0;
@@ -766,6 +667,7 @@ static int dsound_run_in (HWVoiceIn *hw)
DWORD cpos, rpos;
LPVOID p1, p2;
int hwshift;
+ dsound *s = ds->s;
if (!dscb) {
dolog ("Attempt to run without capture buffer\n");
@@ -820,7 +722,8 @@ static int dsound_run_in (HWVoiceIn *hw)
&p2,
&blen1,
&blen2,
- 0
+ 0,
+ s
);
if (err) {
return 0;
@@ -843,12 +746,19 @@ static int dsound_run_in (HWVoiceIn *hw)
return decr;
}
+static DSoundConf glob_conf = {
+ .bufsize_in = 16384,
+ .bufsize_out = 16384,
+ .latency_millis = 10
+};
+
static void dsound_audio_fini (void *opaque)
{
HRESULT hr;
dsound *s = opaque;
if (!s->dsound) {
+ g_free(s);
return;
}
@@ -859,6 +769,7 @@ static void dsound_audio_fini (void *opaque)
s->dsound = NULL;
if (!s->dsound_capture) {
+ g_free(s);
return;
}
@@ -867,17 +778,21 @@ static void dsound_audio_fini (void *opaque)
dsound_logerr (hr, "Could not release DirectSoundCapture\n");
}
s->dsound_capture = NULL;
+
+ g_free(s);
}
static void *dsound_audio_init (void)
{
int err;
HRESULT hr;
- dsound *s = &glob_dsound;
+ dsound *s = g_malloc0(sizeof(dsound));
+ s->conf = glob_conf;
hr = CoInitialize (NULL);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not initialize COM\n");
+ g_free(s);
return NULL;
}
@@ -890,6 +805,7 @@ static void *dsound_audio_init (void)
);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not create DirectSound instance\n");
+ g_free(s);
return NULL;
}
@@ -901,7 +817,7 @@ static void *dsound_audio_init (void)
if (FAILED (hr)) {
dsound_logerr (hr, "Could not release DirectSound\n");
}
- s->dsound = NULL;
+ g_free(s);
return NULL;
}
@@ -939,63 +855,21 @@ static void *dsound_audio_init (void)
static struct audio_option dsound_options[] = {
{
- .name = "LOCK_RETRIES",
- .tag = AUD_OPT_INT,
- .valp = &conf.lock_retries,
- .descr = "Number of times to attempt locking the buffer"
- },
- {
- .name = "RESTOURE_RETRIES",
- .tag = AUD_OPT_INT,
- .valp = &conf.restore_retries,
- .descr = "Number of times to attempt restoring the buffer"
- },
- {
- .name = "GETSTATUS_RETRIES",
- .tag = AUD_OPT_INT,
- .valp = &conf.getstatus_retries,
- .descr = "Number of times to attempt getting status of the buffer"
- },
- {
- .name = "SET_PRIMARY",
- .tag = AUD_OPT_BOOL,
- .valp = &conf.set_primary,
- .descr = "Set the parameters of primary buffer"
- },
- {
.name = "LATENCY_MILLIS",
.tag = AUD_OPT_INT,
- .valp = &conf.latency_millis,
+ .valp = &glob_conf.latency_millis,
.descr = "(undocumented)"
},
{
- .name = "PRIMARY_FREQ",
- .tag = AUD_OPT_INT,
- .valp = &conf.settings.freq,
- .descr = "Primary buffer frequency"
- },
- {
- .name = "PRIMARY_CHANNELS",
- .tag = AUD_OPT_INT,
- .valp = &conf.settings.nchannels,
- .descr = "Primary buffer number of channels (1 - mono, 2 - stereo)"
- },
- {
- .name = "PRIMARY_FMT",
- .tag = AUD_OPT_FMT,
- .valp = &conf.settings.fmt,
- .descr = "Primary buffer format"
- },
- {
.name = "BUFSIZE_OUT",
.tag = AUD_OPT_INT,
- .valp = &conf.bufsize_out,
+ .valp = &glob_conf.bufsize_out,
.descr = "(undocumented)"
},
{
.name = "BUFSIZE_IN",
.tag = AUD_OPT_INT,
- .valp = &conf.bufsize_in,
+ .valp = &glob_conf.bufsize_in,
.descr = "(undocumented)"
},
{ /* End of list */ }
diff --git a/audio/esdaudio.c b/audio/esdaudio.c
deleted file mode 100644
index eea9ccec0b..0000000000
--- a/audio/esdaudio.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * QEMU ESD audio driver
- *
- * Copyright (c) 2006 Frederick Reeve (brushed up by malc)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include <esd.h>
-#include "qemu-common.h"
-#include "audio.h"
-
-#define AUDIO_CAP "esd"
-#include "audio_int.h"
-#include "audio_pt_int.h"
-
-typedef struct {
- HWVoiceOut hw;
- int done;
- int live;
- int decr;
- int rpos;
- void *pcm_buf;
- int fd;
- struct audio_pt pt;
-} ESDVoiceOut;
-
-typedef struct {
- HWVoiceIn hw;
- int done;
- int dead;
- int incr;
- int wpos;
- void *pcm_buf;
- int fd;
- struct audio_pt pt;
-} ESDVoiceIn;
-
-static struct {
- int samples;
- int divisor;
- char *dac_host;
- char *adc_host;
-} conf = {
- .samples = 1024,
- .divisor = 2,
-};
-
-static void GCC_FMT_ATTR (2, 3) qesd_logerr (int err, const char *fmt, ...)
-{
- va_list ap;
-
- va_start (ap, fmt);
- AUD_vlog (AUDIO_CAP, fmt, ap);
- va_end (ap);
-
- AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
-}
-
-/* playback */
-static void *qesd_thread_out (void *arg)
-{
- ESDVoiceOut *esd = arg;
- HWVoiceOut *hw = &esd->hw;
- int threshold;
-
- threshold = conf.divisor ? hw->samples / conf.divisor : 0;
-
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
-
- for (;;) {
- int decr, to_mix, rpos;
-
- for (;;) {
- if (esd->done) {
- goto exit;
- }
-
- if (esd->live > threshold) {
- break;
- }
-
- if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
- goto exit;
- }
- }
-
- decr = to_mix = esd->live;
- rpos = hw->rpos;
-
- if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
-
- while (to_mix) {
- ssize_t written;
- int chunk = audio_MIN (to_mix, hw->samples - rpos);
- struct st_sample *src = hw->mix_buf + rpos;
-
- hw->clip (esd->pcm_buf, src, chunk);
-
- again:
- written = write (esd->fd, esd->pcm_buf, chunk << hw->info.shift);
- if (written == -1) {
- if (errno == EINTR || errno == EAGAIN) {
- goto again;
- }
- qesd_logerr (errno, "write failed\n");
- return NULL;
- }
-
- if (written != chunk << hw->info.shift) {
- int wsamples = written >> hw->info.shift;
- int wbytes = wsamples << hw->info.shift;
- if (wbytes != written) {
- dolog ("warning: Misaligned write %d (requested %zd), "
- "alignment %d\n",
- wbytes, written, hw->info.align + 1);
- }
- to_mix -= wsamples;
- rpos = (rpos + wsamples) % hw->samples;
- break;
- }
-
- rpos = (rpos + chunk) % hw->samples;
- to_mix -= chunk;
- }
-
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
-
- esd->rpos = rpos;
- esd->live -= decr;
- esd->decr += decr;
- }
-
- exit:
- audio_pt_unlock (&esd->pt, AUDIO_FUNC);
- return NULL;
-}
-
-static int qesd_run_out (HWVoiceOut *hw, int live)
-{
- int decr;
- ESDVoiceOut *esd = (ESDVoiceOut *) hw;
-
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return 0;
- }
-
- decr = audio_MIN (live, esd->decr);
- esd->decr -= decr;
- esd->live = live - decr;
- hw->rpos = esd->rpos;
- if (esd->live > 0) {
- audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
- }
- else {
- audio_pt_unlock (&esd->pt, AUDIO_FUNC);
- }
- return decr;
-}
-
-static int qesd_write (SWVoiceOut *sw, void *buf, int len)
-{
- return audio_pcm_sw_write (sw, buf, len);
-}
-
-static int qesd_init_out (HWVoiceOut *hw, struct audsettings *as)
-{
- ESDVoiceOut *esd = (ESDVoiceOut *) hw;
- struct audsettings obt_as = *as;
- int esdfmt = ESD_STREAM | ESD_PLAY;
-
- esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
- switch (as->fmt) {
- case AUD_FMT_S8:
- case AUD_FMT_U8:
- esdfmt |= ESD_BITS8;
- obt_as.fmt = AUD_FMT_U8;
- break;
-
- case AUD_FMT_S32:
- case AUD_FMT_U32:
- dolog ("Will use 16 instead of 32 bit samples\n");
- /* fall through */
- case AUD_FMT_S16:
- case AUD_FMT_U16:
- deffmt:
- esdfmt |= ESD_BITS16;
- obt_as.fmt = AUD_FMT_S16;
- break;
-
- default:
- dolog ("Internal logic error: Bad audio format %d\n", as->fmt);
- goto deffmt;
-
- }
- obt_as.endianness = AUDIO_HOST_ENDIANNESS;
-
- audio_pcm_init_info (&hw->info, &obt_as);
-
- hw->samples = conf.samples;
- esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
- if (!esd->pcm_buf) {
- dolog ("Could not allocate buffer (%d bytes)\n",
- hw->samples << hw->info.shift);
- return -1;
- }
-
- esd->fd = esd_play_stream (esdfmt, as->freq, conf.dac_host, NULL);
- if (esd->fd < 0) {
- qesd_logerr (errno, "esd_play_stream failed\n");
- goto fail1;
- }
-
- if (audio_pt_init (&esd->pt, qesd_thread_out, esd, AUDIO_CAP, AUDIO_FUNC)) {
- goto fail2;
- }
-
- return 0;
-
- fail2:
- if (close (esd->fd)) {
- qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
- AUDIO_FUNC, esd->fd);
- }
- esd->fd = -1;
-
- fail1:
- g_free (esd->pcm_buf);
- esd->pcm_buf = NULL;
- return -1;
-}
-
-static void qesd_fini_out (HWVoiceOut *hw)
-{
- void *ret;
- ESDVoiceOut *esd = (ESDVoiceOut *) hw;
-
- audio_pt_lock (&esd->pt, AUDIO_FUNC);
- esd->done = 1;
- audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
- audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
-
- if (esd->fd >= 0) {
- if (close (esd->fd)) {
- qesd_logerr (errno, "failed to close esd socket\n");
- }
- esd->fd = -1;
- }
-
- audio_pt_fini (&esd->pt, AUDIO_FUNC);
-
- g_free (esd->pcm_buf);
- esd->pcm_buf = NULL;
-}
-
-static int qesd_ctl_out (HWVoiceOut *hw, int cmd, ...)
-{
- (void) hw;
- (void) cmd;
- return 0;
-}
-
-/* capture */
-static void *qesd_thread_in (void *arg)
-{
- ESDVoiceIn *esd = arg;
- HWVoiceIn *hw = &esd->hw;
- int threshold;
-
- threshold = conf.divisor ? hw->samples / conf.divisor : 0;
-
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
-
- for (;;) {
- int incr, to_grab, wpos;
-
- for (;;) {
- if (esd->done) {
- goto exit;
- }
-
- if (esd->dead > threshold) {
- break;
- }
-
- if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
- goto exit;
- }
- }
-
- incr = to_grab = esd->dead;
- wpos = hw->wpos;
-
- if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
-
- while (to_grab) {
- ssize_t nread;
- int chunk = audio_MIN (to_grab, hw->samples - wpos);
- void *buf = advance (esd->pcm_buf, wpos);
-
- again:
- nread = read (esd->fd, buf, chunk << hw->info.shift);
- if (nread == -1) {
- if (errno == EINTR || errno == EAGAIN) {
- goto again;
- }
- qesd_logerr (errno, "read failed\n");
- return NULL;
- }
-
- if (nread != chunk << hw->info.shift) {
- int rsamples = nread >> hw->info.shift;
- int rbytes = rsamples << hw->info.shift;
- if (rbytes != nread) {
- dolog ("warning: Misaligned write %d (requested %zd), "
- "alignment %d\n",
- rbytes, nread, hw->info.align + 1);
- }
- to_grab -= rsamples;
- wpos = (wpos + rsamples) % hw->samples;
- break;
- }
-
- hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift);
- wpos = (wpos + chunk) % hw->samples;
- to_grab -= chunk;
- }
-
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
-
- esd->wpos = wpos;
- esd->dead -= incr;
- esd->incr += incr;
- }
-
- exit:
- audio_pt_unlock (&esd->pt, AUDIO_FUNC);
- return NULL;
-}
-
-static int qesd_run_in (HWVoiceIn *hw)
-{
- int live, incr, dead;
- ESDVoiceIn *esd = (ESDVoiceIn *) hw;
-
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return 0;
- }
-
- live = audio_pcm_hw_get_live_in (hw);
- dead = hw->samples - live;
- incr = audio_MIN (dead, esd->incr);
- esd->incr -= incr;
- esd->dead = dead - incr;
- hw->wpos = esd->wpos;
- if (esd->dead > 0) {
- audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
- }
- else {
- audio_pt_unlock (&esd->pt, AUDIO_FUNC);
- }
- return incr;
-}
-
-static int qesd_read (SWVoiceIn *sw, void *buf, int len)
-{
- return audio_pcm_sw_read (sw, buf, len);
-}
-
-static int qesd_init_in (HWVoiceIn *hw, struct audsettings *as)
-{
- ESDVoiceIn *esd = (ESDVoiceIn *) hw;
- struct audsettings obt_as = *as;
- int esdfmt = ESD_STREAM | ESD_RECORD;
-
- esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
- switch (as->fmt) {
- case AUD_FMT_S8:
- case AUD_FMT_U8:
- esdfmt |= ESD_BITS8;
- obt_as.fmt = AUD_FMT_U8;
- break;
-
- case AUD_FMT_S16:
- case AUD_FMT_U16:
- esdfmt |= ESD_BITS16;
- obt_as.fmt = AUD_FMT_S16;
- break;
-
- case AUD_FMT_S32:
- case AUD_FMT_U32:
- dolog ("Will use 16 instead of 32 bit samples\n");
- esdfmt |= ESD_BITS16;
- obt_as.fmt = AUD_FMT_S16;
- break;
- }
- obt_as.endianness = AUDIO_HOST_ENDIANNESS;
-
- audio_pcm_init_info (&hw->info, &obt_as);
-
- hw->samples = conf.samples;
- esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
- if (!esd->pcm_buf) {
- dolog ("Could not allocate buffer (%d bytes)\n",
- hw->samples << hw->info.shift);
- return -1;
- }
-
- esd->fd = esd_record_stream (esdfmt, as->freq, conf.adc_host, NULL);
- if (esd->fd < 0) {
- qesd_logerr (errno, "esd_record_stream failed\n");
- goto fail1;
- }
-
- if (audio_pt_init (&esd->pt, qesd_thread_in, esd, AUDIO_CAP, AUDIO_FUNC)) {
- goto fail2;
- }
-
- return 0;
-
- fail2:
- if (close (esd->fd)) {
- qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
- AUDIO_FUNC, esd->fd);
- }
- esd->fd = -1;
-
- fail1:
- g_free (esd->pcm_buf);
- esd->pcm_buf = NULL;
- return -1;
-}
-
-static void qesd_fini_in (HWVoiceIn *hw)
-{
- void *ret;
- ESDVoiceIn *esd = (ESDVoiceIn *) hw;
-
- audio_pt_lock (&esd->pt, AUDIO_FUNC);
- esd->done = 1;
- audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
- audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
-
- if (esd->fd >= 0) {
- if (close (esd->fd)) {
- qesd_logerr (errno, "failed to close esd socket\n");
- }
- esd->fd = -1;
- }
-
- audio_pt_fini (&esd->pt, AUDIO_FUNC);
-
- g_free (esd->pcm_buf);
- esd->pcm_buf = NULL;
-}
-
-static int qesd_ctl_in (HWVoiceIn *hw, int cmd, ...)
-{
- (void) hw;
- (void) cmd;
- return 0;
-}
-
-/* common */
-static void *qesd_audio_init (void)
-{
- return &conf;
-}
-
-static void qesd_audio_fini (void *opaque)
-{
- (void) opaque;
- ldebug ("esd_fini");
-}
-
-struct audio_option qesd_options[] = {
- {
- .name = "SAMPLES",
- .tag = AUD_OPT_INT,
- .valp = &conf.samples,
- .descr = "buffer size in samples"
- },
- {
- .name = "DIVISOR",
- .tag = AUD_OPT_INT,
- .valp = &conf.divisor,
- .descr = "threshold divisor"
- },
- {
- .name = "DAC_HOST",
- .tag = AUD_OPT_STR,
- .valp = &conf.dac_host,
- .descr = "playback host"
- },
- {
- .name = "ADC_HOST",
- .tag = AUD_OPT_STR,
- .valp = &conf.adc_host,
- .descr = "capture host"
- },
- { /* End of list */ }
-};
-
-static struct audio_pcm_ops qesd_pcm_ops = {
- .init_out = qesd_init_out,
- .fini_out = qesd_fini_out,
- .run_out = qesd_run_out,
- .write = qesd_write,
- .ctl_out = qesd_ctl_out,
-
- .init_in = qesd_init_in,
- .fini_in = qesd_fini_in,
- .run_in = qesd_run_in,
- .read = qesd_read,
- .ctl_in = qesd_ctl_in,
-};
-
-struct audio_driver esd_audio_driver = {
- .name = "esd",
- .descr = "http://en.wikipedia.org/wiki/Esound",
- .options = qesd_options,
- .init = qesd_audio_init,
- .fini = qesd_audio_fini,
- .pcm_ops = &qesd_pcm_ops,
- .can_be_default = 0,
- .max_voices_out = INT_MAX,
- .max_voices_in = INT_MAX,
- .voice_size_out = sizeof (ESDVoiceOut),
- .voice_size_in = sizeof (ESDVoiceIn)
-};
diff --git a/audio/fmodaudio.c b/audio/fmodaudio.c
deleted file mode 100644
index fabf84dd3b..0000000000
--- a/audio/fmodaudio.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- * QEMU FMOD audio driver
- *
- * Copyright (c) 2004-2005 Vassili Karpov (malc)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include <fmod.h>
-#include <fmod_errors.h>
-#include "qemu-common.h"
-#include "audio.h"
-
-#define AUDIO_CAP "fmod"
-#include "audio_int.h"
-
-typedef struct FMODVoiceOut {
- HWVoiceOut hw;
- unsigned int old_pos;
- FSOUND_SAMPLE *fmod_sample;
- int channel;
-} FMODVoiceOut;
-
-typedef struct FMODVoiceIn {
- HWVoiceIn hw;
- FSOUND_SAMPLE *fmod_sample;
-} FMODVoiceIn;
-
-static struct {
- const char *drvname;
- int nb_samples;
- int freq;
- int nb_channels;
- int bufsize;
- int broken_adc;
-} conf = {
- .nb_samples = 2048 * 2,
- .freq = 44100,
- .nb_channels = 2,
-};
-
-static void GCC_FMT_ATTR (1, 2) fmod_logerr (const char *fmt, ...)
-{
- va_list ap;
-
- va_start (ap, fmt);
- AUD_vlog (AUDIO_CAP, fmt, ap);
- va_end (ap);
-
- AUD_log (AUDIO_CAP, "Reason: %s\n",
- FMOD_ErrorString (FSOUND_GetError ()));
-}
-
-static void GCC_FMT_ATTR (2, 3) fmod_logerr2 (
- const char *typ,
- const char *fmt,
- ...
- )
-{
- va_list ap;
-
- AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
-
- va_start (ap, fmt);
- AUD_vlog (AUDIO_CAP, fmt, ap);
- va_end (ap);
-
- AUD_log (AUDIO_CAP, "Reason: %s\n",
- FMOD_ErrorString (FSOUND_GetError ()));
-}
-
-static int fmod_write (SWVoiceOut *sw, void *buf, int len)
-{
- return audio_pcm_sw_write (sw, buf, len);
-}
-
-static void fmod_clear_sample (FMODVoiceOut *fmd)
-{
- HWVoiceOut *hw = &fmd->hw;
- int status;
- void *p1 = 0, *p2 = 0;
- unsigned int len1 = 0, len2 = 0;
-
- status = FSOUND_Sample_Lock (
- fmd->fmod_sample,
- 0,
- hw->samples << hw->info.shift,
- &p1,
- &p2,
- &len1,
- &len2
- );
-
- if (!status) {
- fmod_logerr ("Failed to lock sample\n");
- return;
- }
-
- if ((len1 & hw->info.align) || (len2 & hw->info.align)) {
- dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
- len1, len2, hw->info.align + 1);
- goto fail;
- }
-
- if ((len1 + len2) - (hw->samples << hw->info.shift)) {
- dolog ("Lock returned incomplete length %d, %d\n",
- len1 + len2, hw->samples << hw->info.shift);
- goto fail;
- }
-
- audio_pcm_info_clear_buf (&hw->info, p1, hw->samples);
-
- fail:
- status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2);
- if (!status) {
- fmod_logerr ("Failed to unlock sample\n");
- }
-}
-
-static void fmod_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
-{
- int src_len1 = dst_len;
- int src_len2 = 0;
- int pos = hw->rpos + dst_len;
- struct st_sample *src1 = hw->mix_buf + hw->rpos;
- struct st_sample *src2 = NULL;
-
- if (pos > hw->samples) {
- src_len1 = hw->samples - hw->rpos;
- src2 = hw->mix_buf;
- src_len2 = dst_len - src_len1;
- pos = src_len2;
- }
-
- if (src_len1) {
- hw->clip (dst, src1, src_len1);
- }
-
- if (src_len2) {
- dst = advance (dst, src_len1 << hw->info.shift);
- hw->clip (dst, src2, src_len2);
- }
-
- hw->rpos = pos % hw->samples;
-}
-
-static int fmod_unlock_sample (FSOUND_SAMPLE *sample, void *p1, void *p2,
- unsigned int blen1, unsigned int blen2)
-{
- int status = FSOUND_Sample_Unlock (sample, p1, p2, blen1, blen2);
- if (!status) {
- fmod_logerr ("Failed to unlock sample\n");
- return -1;
- }
- return 0;
-}
-
-static int fmod_lock_sample (
- FSOUND_SAMPLE *sample,
- struct audio_pcm_info *info,
- int pos,
- int len,
- void **p1,
- void **p2,
- unsigned int *blen1,
- unsigned int *blen2
- )
-{
- int status;
-
- status = FSOUND_Sample_Lock (
- sample,
- pos << info->shift,
- len << info->shift,
- p1,
- p2,
- blen1,
- blen2
- );
-
- if (!status) {
- fmod_logerr ("Failed to lock sample\n");
- return -1;
- }
-
- if ((*blen1 & info->align) || (*blen2 & info->align)) {
- dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
- *blen1, *blen2, info->align + 1);
-
- fmod_unlock_sample (sample, *p1, *p2, *blen1, *blen2);
-
- *p1 = NULL - 1;
- *p2 = NULL - 1;
- *blen1 = ~0U;
- *blen2 = ~0U;
- return -1;
- }
-
- if (!*p1 && *blen1) {
- dolog ("warning: !p1 && blen1=%d\n", *blen1);
- *blen1 = 0;
- }
-
- if (!p2 && *blen2) {
- dolog ("warning: !p2 && blen2=%d\n", *blen2);
- *blen2 = 0;
- }
-
- return 0;
-}
-
-static int fmod_run_out (HWVoiceOut *hw, int live)
-{
- FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
- int decr;
- void *p1 = 0, *p2 = 0;
- unsigned int blen1 = 0, blen2 = 0;
- unsigned int len1 = 0, len2 = 0;
-
- if (!hw->pending_disable) {
- return 0;
- }
-
- decr = live;
-
- if (fmd->channel >= 0) {
- int len = decr;
- int old_pos = fmd->old_pos;
- int ppos = FSOUND_GetCurrentPosition (fmd->channel);
-
- if (ppos == old_pos || !ppos) {
- return 0;
- }
-
- if ((old_pos < ppos) && ((old_pos + len) > ppos)) {
- len = ppos - old_pos;
- }
- else {
- if ((old_pos > ppos) && ((old_pos + len) > (ppos + hw->samples))) {
- len = hw->samples - old_pos + ppos;
- }
- }
- decr = len;
-
- if (audio_bug (AUDIO_FUNC, decr < 0)) {
- dolog ("decr=%d live=%d ppos=%d old_pos=%d len=%d\n",
- decr, live, ppos, old_pos, len);
- return 0;
- }
- }
-
-
- if (!decr) {
- return 0;
- }
-
- if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
- fmd->old_pos, decr,
- &p1, &p2,
- &blen1, &blen2)) {
- return 0;
- }
-
- len1 = blen1 >> hw->info.shift;
- len2 = blen2 >> hw->info.shift;
- ldebug ("%p %p %d %d %d %d\n", p1, p2, len1, len2, blen1, blen2);
- decr = len1 + len2;
-
- if (p1 && len1) {
- fmod_write_sample (hw, p1, len1);
- }
-
- if (p2 && len2) {
- fmod_write_sample (hw, p2, len2);
- }
-
- fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
-
- fmd->old_pos = (fmd->old_pos + decr) % hw->samples;
- return decr;
-}
-
-static int aud_to_fmodfmt (audfmt_e fmt, int stereo)
-{
- int mode = FSOUND_LOOP_NORMAL;
-
- switch (fmt) {
- case AUD_FMT_S8:
- mode |= FSOUND_SIGNED | FSOUND_8BITS;
- break;
-
- case AUD_FMT_U8:
- mode |= FSOUND_UNSIGNED | FSOUND_8BITS;
- break;
-
- case AUD_FMT_S16:
- mode |= FSOUND_SIGNED | FSOUND_16BITS;
- break;
-
- case AUD_FMT_U16:
- mode |= FSOUND_UNSIGNED | FSOUND_16BITS;
- break;
-
- default:
- dolog ("Internal logic error: Bad audio format %d\n", fmt);
-#ifdef DEBUG_FMOD
- abort ();
-#endif
- mode |= FSOUND_8BITS;
- }
- mode |= stereo ? FSOUND_STEREO : FSOUND_MONO;
- return mode;
-}
-
-static void fmod_fini_out (HWVoiceOut *hw)
-{
- FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
-
- if (fmd->fmod_sample) {
- FSOUND_Sample_Free (fmd->fmod_sample);
- fmd->fmod_sample = 0;
-
- if (fmd->channel >= 0) {
- FSOUND_StopSound (fmd->channel);
- }
- }
-}
-
-static int fmod_init_out (HWVoiceOut *hw, struct audsettings *as)
-{
- int mode, channel;
- FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
- struct audsettings obt_as = *as;
-
- mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
- fmd->fmod_sample = FSOUND_Sample_Alloc (
- FSOUND_FREE, /* index */
- conf.nb_samples, /* length */
- mode, /* mode */
- as->freq, /* freq */
- 255, /* volume */
- 128, /* pan */
- 255 /* priority */
- );
-
- if (!fmd->fmod_sample) {
- fmod_logerr2 ("DAC", "Failed to allocate FMOD sample\n");
- return -1;
- }
-
- channel = FSOUND_PlaySoundEx (FSOUND_FREE, fmd->fmod_sample, 0, 1);
- if (channel < 0) {
- fmod_logerr2 ("DAC", "Failed to start playing sound\n");
- FSOUND_Sample_Free (fmd->fmod_sample);
- return -1;
- }
- fmd->channel = channel;
-
- /* FMOD always operates on little endian frames? */
- obt_as.endianness = 0;
- audio_pcm_init_info (&hw->info, &obt_as);
- hw->samples = conf.nb_samples;
- return 0;
-}
-
-static int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...)
-{
- int status;
- FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
-
- switch (cmd) {
- case VOICE_ENABLE:
- fmod_clear_sample (fmd);
- status = FSOUND_SetPaused (fmd->channel, 0);
- if (!status) {
- fmod_logerr ("Failed to resume channel %d\n", fmd->channel);
- }
- break;
-
- case VOICE_DISABLE:
- status = FSOUND_SetPaused (fmd->channel, 1);
- if (!status) {
- fmod_logerr ("Failed to pause channel %d\n", fmd->channel);
- }
- break;
- }
- return 0;
-}
-
-static int fmod_init_in (HWVoiceIn *hw, struct audsettings *as)
-{
- int mode;
- FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
- struct audsettings obt_as = *as;
-
- if (conf.broken_adc) {
- return -1;
- }
-
- mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
- fmd->fmod_sample = FSOUND_Sample_Alloc (
- FSOUND_FREE, /* index */
- conf.nb_samples, /* length */
- mode, /* mode */
- as->freq, /* freq */
- 255, /* volume */
- 128, /* pan */
- 255 /* priority */
- );
-
- if (!fmd->fmod_sample) {
- fmod_logerr2 ("ADC", "Failed to allocate FMOD sample\n");
- return -1;
- }
-
- /* FMOD always operates on little endian frames? */
- obt_as.endianness = 0;
- audio_pcm_init_info (&hw->info, &obt_as);
- hw->samples = conf.nb_samples;
- return 0;
-}
-
-static void fmod_fini_in (HWVoiceIn *hw)
-{
- FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
-
- if (fmd->fmod_sample) {
- FSOUND_Record_Stop ();
- FSOUND_Sample_Free (fmd->fmod_sample);
- fmd->fmod_sample = 0;
- }
-}
-
-static int fmod_run_in (HWVoiceIn *hw)
-{
- FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
- int hwshift = hw->info.shift;
- int live, dead, new_pos, len;
- unsigned int blen1 = 0, blen2 = 0;
- unsigned int len1, len2;
- unsigned int decr;
- void *p1, *p2;
-
- live = audio_pcm_hw_get_live_in (hw);
- dead = hw->samples - live;
- if (!dead) {
- return 0;
- }
-
- new_pos = FSOUND_Record_GetPosition ();
- if (new_pos < 0) {
- fmod_logerr ("Could not get recording position\n");
- return 0;
- }
-
- len = audio_ring_dist (new_pos, hw->wpos, hw->samples);
- if (!len) {
- return 0;
- }
- len = audio_MIN (len, dead);
-
- if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
- hw->wpos, len,
- &p1, &p2,
- &blen1, &blen2)) {
- return 0;
- }
-
- len1 = blen1 >> hwshift;
- len2 = blen2 >> hwshift;
- decr = len1 + len2;
-
- if (p1 && blen1) {
- hw->conv (hw->conv_buf + hw->wpos, p1, len1);
- }
- if (p2 && len2) {
- hw->conv (hw->conv_buf, p2, len2);
- }
-
- fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
- hw->wpos = (hw->wpos + decr) % hw->samples;
- return decr;
-}
-
-static struct {
- const char *name;
- int type;
-} drvtab[] = {
- { .name = "none", .type = FSOUND_OUTPUT_NOSOUND },
-#ifdef _WIN32
- { .name = "winmm", .type = FSOUND_OUTPUT_WINMM },
- { .name = "dsound", .type = FSOUND_OUTPUT_DSOUND },
- { .name = "a3d", .type = FSOUND_OUTPUT_A3D },
- { .name = "asio", .type = FSOUND_OUTPUT_ASIO },
-#endif
-#ifdef __linux__
- { .name = "oss", .type = FSOUND_OUTPUT_OSS },
- { .name = "alsa", .type = FSOUND_OUTPUT_ALSA },
- { .name = "esd", .type = FSOUND_OUTPUT_ESD },
-#endif
-#ifdef __APPLE__
- { .name = "mac", .type = FSOUND_OUTPUT_MAC },
-#endif
-#if 0
- { .name = "xbox", .type = FSOUND_OUTPUT_XBOX },
- { .name = "ps2", .type = FSOUND_OUTPUT_PS2 },
- { .name = "gcube", .type = FSOUND_OUTPUT_GC },
-#endif
- { .name = "none-realtime", .type = FSOUND_OUTPUT_NOSOUND_NONREALTIME }
-};
-
-static void *fmod_audio_init (void)
-{
- size_t i;
- double ver;
- int status;
- int output_type = -1;
- const char *drv = conf.drvname;
-
- ver = FSOUND_GetVersion ();
- if (ver < FMOD_VERSION) {
- dolog ("Wrong FMOD version %f, need at least %f\n", ver, FMOD_VERSION);
- return NULL;
- }
-
-#ifdef __linux__
- if (ver < 3.75) {
- dolog ("FMOD before 3.75 has bug preventing ADC from working\n"
- "ADC will be disabled.\n");
- conf.broken_adc = 1;
- }
-#endif
-
- if (drv) {
- int found = 0;
- for (i = 0; i < ARRAY_SIZE (drvtab); i++) {
- if (!strcmp (drv, drvtab[i].name)) {
- output_type = drvtab[i].type;
- found = 1;
- break;
- }
- }
- if (!found) {
- dolog ("Unknown FMOD driver `%s'\n", drv);
- dolog ("Valid drivers:\n");
- for (i = 0; i < ARRAY_SIZE (drvtab); i++) {
- dolog (" %s\n", drvtab[i].name);
- }
- }
- }
-
- if (output_type != -1) {
- status = FSOUND_SetOutput (output_type);
- if (!status) {
- fmod_logerr ("FSOUND_SetOutput(%d) failed\n", output_type);
- return NULL;
- }
- }
-
- if (conf.bufsize) {
- status = FSOUND_SetBufferSize (conf.bufsize);
- if (!status) {
- fmod_logerr ("FSOUND_SetBufferSize (%d) failed\n", conf.bufsize);
- }
- }
-
- status = FSOUND_Init (conf.freq, conf.nb_channels, 0);
- if (!status) {
- fmod_logerr ("FSOUND_Init failed\n");
- return NULL;
- }
-
- return &conf;
-}
-
-static int fmod_read (SWVoiceIn *sw, void *buf, int size)
-{
- return audio_pcm_sw_read (sw, buf, size);
-}
-
-static int fmod_ctl_in (HWVoiceIn *hw, int cmd, ...)
-{
- int status;
- FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
-
- switch (cmd) {
- case VOICE_ENABLE:
- status = FSOUND_Record_StartSample (fmd->fmod_sample, 1);
- if (!status) {
- fmod_logerr ("Failed to start recording\n");
- }
- break;
-
- case VOICE_DISABLE:
- status = FSOUND_Record_Stop ();
- if (!status) {
- fmod_logerr ("Failed to stop recording\n");
- }
- break;
- }
- return 0;
-}
-
-static void fmod_audio_fini (void *opaque)
-{
- (void) opaque;
- FSOUND_Close ();
-}
-
-static struct audio_option fmod_options[] = {
- {
- .name = "DRV",
- .tag = AUD_OPT_STR,
- .valp = &conf.drvname,
- .descr = "FMOD driver"
- },
- {
- .name = "FREQ",
- .tag = AUD_OPT_INT,
- .valp = &conf.freq,
- .descr = "Default frequency"
- },
- {
- .name = "SAMPLES",
- .tag = AUD_OPT_INT,
- .valp = &conf.nb_samples,
- .descr = "Buffer size in samples"
- },
- {
- .name = "CHANNELS",
- .tag = AUD_OPT_INT,
- .valp = &conf.nb_channels,
- .descr = "Number of default channels (1 - mono, 2 - stereo)"
- },
- {
- .name = "BUFSIZE",
- .tag = AUD_OPT_INT,
- .valp = &conf.bufsize,
- .descr = "(undocumented)"
- },
- { /* End of list */ }
-};
-
-static struct audio_pcm_ops fmod_pcm_ops = {
- .init_out = fmod_init_out,
- .fini_out = fmod_fini_out,
- .run_out = fmod_run_out,
- .write = fmod_write,
- .ctl_out = fmod_ctl_out,
-
- .init_in = fmod_init_in,
- .fini_in = fmod_fini_in,
- .run_in = fmod_run_in,
- .read = fmod_read,
- .ctl_in = fmod_ctl_in
-};
-
-struct audio_driver fmod_audio_driver = {
- .name = "fmod",
- .descr = "FMOD 3.xx http://www.fmod.org",
- .options = fmod_options,
- .init = fmod_audio_init,
- .fini = fmod_audio_fini,
- .pcm_ops = &fmod_pcm_ops,
- .can_be_default = 1,
- .max_voices_out = INT_MAX,
- .max_voices_in = INT_MAX,
- .voice_size_out = sizeof (FMODVoiceOut),
- .voice_size_in = sizeof (FMODVoiceIn)
-};
diff --git a/audio/noaudio.c b/audio/noaudio.c
index cb386620ae..50db1f344b 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -63,7 +63,7 @@ static int no_write (SWVoiceOut *sw, void *buf, int len)
return audio_pcm_sw_write (sw, buf, len);
}
-static int no_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
{
audio_pcm_init_info (&hw->info, as);
hw->samples = 1024;
@@ -82,7 +82,7 @@ static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
return 0;
}
-static int no_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
{
audio_pcm_init_info (&hw->info, as);
hw->samples = 1024;
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index b9c6b30ca1..11e76a15a2 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -30,6 +30,7 @@
#include "qemu/main-loop.h"
#include "qemu/host-utils.h"
#include "audio.h"
+#include "trace.h"
#define AUDIO_CAP "oss"
#include "audio_int.h"
@@ -38,6 +39,16 @@
#define USE_DSP_POLICY
#endif
+typedef struct OSSConf {
+ int try_mmap;
+ int nfrags;
+ int fragsize;
+ const char *devpath_out;
+ const char *devpath_in;
+ int exclusive;
+ int policy;
+} OSSConf;
+
typedef struct OSSVoiceOut {
HWVoiceOut hw;
void *pcm_buf;
@@ -47,6 +58,7 @@ typedef struct OSSVoiceOut {
int fragsize;
int mmapped;
int pending;
+ OSSConf *conf;
} OSSVoiceOut;
typedef struct OSSVoiceIn {
@@ -55,28 +67,9 @@ typedef struct OSSVoiceIn {
int fd;
int nfrags;
int fragsize;
+ OSSConf *conf;
} OSSVoiceIn;
-static struct {
- int try_mmap;
- int nfrags;
- int fragsize;
- const char *devpath_out;
- const char *devpath_in;
- int debug;
- int exclusive;
- int policy;
-} conf = {
- .try_mmap = 0,
- .nfrags = 4,
- .fragsize = 4096,
- .devpath_out = "/dev/dsp",
- .devpath_in = "/dev/dsp",
- .debug = 0,
- .exclusive = 0,
- .policy = 5
-};
-
struct oss_params {
int freq;
audfmt_e fmt;
@@ -272,18 +265,18 @@ static int oss_get_version (int fd, int *version, const char *typ)
#endif
static int oss_open (int in, struct oss_params *req,
- struct oss_params *obt, int *pfd)
+ struct oss_params *obt, int *pfd, OSSConf* conf)
{
int fd;
- int oflags = conf.exclusive ? O_EXCL : 0;
+ int oflags = conf->exclusive ? O_EXCL : 0;
audio_buf_info abinfo;
int fmt, freq, nchannels;
int setfragment = 1;
- const char *dspname = in ? conf.devpath_in : conf.devpath_out;
+ const char *dspname = in ? conf->devpath_in : conf->devpath_out;
const char *typ = in ? "ADC" : "DAC";
/* Kludge needed to have working mmap on Linux */
- oflags |= conf.try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY);
+ oflags |= conf->try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY);
fd = open (dspname, oflags | O_NONBLOCK);
if (-1 == fd) {
@@ -317,20 +310,18 @@ static int oss_open (int in, struct oss_params *req,
}
#ifdef USE_DSP_POLICY
- if (conf.policy >= 0) {
+ if (conf->policy >= 0) {
int version;
if (!oss_get_version (fd, &version, typ)) {
- if (conf.debug) {
- dolog ("OSS version = %#x\n", version);
- }
+ trace_oss_version(version);
if (version >= 0x040000) {
- int policy = conf.policy;
+ int policy = conf->policy;
if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) {
oss_logerr2 (errno, typ,
"Failed to set timing policy to %d\n",
- conf.policy);
+ conf->policy);
goto err;
}
setfragment = 0;
@@ -458,19 +449,12 @@ static int oss_run_out (HWVoiceOut *hw, int live)
}
if (abinfo.bytes > bufsize) {
- if (conf.debug) {
- dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
- "please report your OS/audio hw to av1474@comtv.ru\n",
- abinfo.bytes, bufsize);
- }
+ trace_oss_invalid_available_size(abinfo.bytes, bufsize);
abinfo.bytes = bufsize;
}
if (abinfo.bytes < 0) {
- if (conf.debug) {
- dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
- abinfo.bytes, bufsize);
- }
+ trace_oss_invalid_available_size(abinfo.bytes, bufsize);
return 0;
}
@@ -510,7 +494,8 @@ static void oss_fini_out (HWVoiceOut *hw)
}
}
-static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
{
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
struct oss_params req, obt;
@@ -519,16 +504,17 @@ static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
int fd;
audfmt_e effective_fmt;
struct audsettings obt_as;
+ OSSConf *conf = drv_opaque;
oss->fd = -1;
req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
- req.fragsize = conf.fragsize;
- req.nfrags = conf.nfrags;
+ req.fragsize = conf->fragsize;
+ req.nfrags = conf->nfrags;
- if (oss_open (0, &req, &obt, &fd)) {
+ if (oss_open (0, &req, &obt, &fd, conf)) {
return -1;
}
@@ -555,7 +541,7 @@ static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
oss->mmapped = 0;
- if (conf.try_mmap) {
+ if (conf->try_mmap) {
oss->pcm_buf = mmap (
NULL,
hw->samples << hw->info.shift,
@@ -615,6 +601,7 @@ static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
}
oss->fd = fd;
+ oss->conf = conf;
return 0;
}
@@ -677,7 +664,7 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
return 0;
}
-static int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
{
OSSVoiceIn *oss = (OSSVoiceIn *) hw;
struct oss_params req, obt;
@@ -686,15 +673,16 @@ static int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
int fd;
audfmt_e effective_fmt;
struct audsettings obt_as;
+ OSSConf *conf = drv_opaque;
oss->fd = -1;
req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
- req.fragsize = conf.fragsize;
- req.nfrags = conf.nfrags;
- if (oss_open (1, &req, &obt, &fd)) {
+ req.fragsize = conf->fragsize;
+ req.nfrags = conf->nfrags;
+ if (oss_open (1, &req, &obt, &fd, conf)) {
return -1;
}
@@ -728,6 +716,7 @@ static int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
}
oss->fd = fd;
+ oss->conf = conf;
return 0;
}
@@ -847,71 +836,78 @@ static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
return 0;
}
+static OSSConf glob_conf = {
+ .try_mmap = 0,
+ .nfrags = 4,
+ .fragsize = 4096,
+ .devpath_out = "/dev/dsp",
+ .devpath_in = "/dev/dsp",
+ .exclusive = 0,
+ .policy = 5
+};
+
static void *oss_audio_init (void)
{
- if (access(conf.devpath_in, R_OK | W_OK) < 0 ||
- access(conf.devpath_out, R_OK | W_OK) < 0) {
+ OSSConf *conf = g_malloc(sizeof(OSSConf));
+ *conf = glob_conf;
+
+ if (access(conf->devpath_in, R_OK | W_OK) < 0 ||
+ access(conf->devpath_out, R_OK | W_OK) < 0) {
return NULL;
}
- return &conf;
+ return conf;
}
static void oss_audio_fini (void *opaque)
{
- (void) opaque;
+ g_free(opaque);
}
static struct audio_option oss_options[] = {
{
.name = "FRAGSIZE",
.tag = AUD_OPT_INT,
- .valp = &conf.fragsize,
+ .valp = &glob_conf.fragsize,
.descr = "Fragment size in bytes"
},
{
.name = "NFRAGS",
.tag = AUD_OPT_INT,
- .valp = &conf.nfrags,
+ .valp = &glob_conf.nfrags,
.descr = "Number of fragments"
},
{
.name = "MMAP",
.tag = AUD_OPT_BOOL,
- .valp = &conf.try_mmap,
+ .valp = &glob_conf.try_mmap,
.descr = "Try using memory mapped access"
},
{
.name = "DAC_DEV",
.tag = AUD_OPT_STR,
- .valp = &conf.devpath_out,
+ .valp = &glob_conf.devpath_out,
.descr = "Path to DAC device"
},
{
.name = "ADC_DEV",
.tag = AUD_OPT_STR,
- .valp = &conf.devpath_in,
+ .valp = &glob_conf.devpath_in,
.descr = "Path to ADC device"
},
{
.name = "EXCLUSIVE",
.tag = AUD_OPT_BOOL,
- .valp = &conf.exclusive,
+ .valp = &glob_conf.exclusive,
.descr = "Open device in exclusive mode (vmix wont work)"
},
#ifdef USE_DSP_POLICY
{
.name = "POLICY",
.tag = AUD_OPT_INT,
- .valp = &conf.policy,
+ .valp = &glob_conf.policy,
.descr = "Set the timing policy of the device, -1 to use fragment mode",
},
#endif
- {
- .name = "DEBUG",
- .tag = AUD_OPT_BOOL,
- .valp = &conf.debug,
- .descr = "Turn on some debugging messages"
- },
{ /* End of list */ }
};
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 90ff24500b..fea607166f 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -9,6 +9,19 @@
#include "audio_pt_int.h"
typedef struct {
+ int samples;
+ char *server;
+ char *sink;
+ char *source;
+} PAConf;
+
+typedef struct {
+ PAConf conf;
+ pa_threaded_mainloop *mainloop;
+ pa_context *context;
+} paaudio;
+
+typedef struct {
HWVoiceOut hw;
int done;
int live;
@@ -17,6 +30,7 @@ typedef struct {
pa_stream *stream;
void *pcm_buf;
struct audio_pt pt;
+ paaudio *g;
} PAVoiceOut;
typedef struct {
@@ -30,20 +44,10 @@ typedef struct {
struct audio_pt pt;
const void *read_data;
size_t read_index, read_length;
+ paaudio *g;
} PAVoiceIn;
-typedef struct {
- int samples;
- char *server;
- char *sink;
- char *source;
- pa_threaded_mainloop *mainloop;
- pa_context *context;
-} paaudio;
-
-static paaudio glob_paaudio = {
- .samples = 4096,
-};
+static void qpa_audio_fini(void *opaque);
static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
{
@@ -106,7 +110,7 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror)
{
- paaudio *g = &glob_paaudio;
+ paaudio *g = p->g;
pa_threaded_mainloop_lock (g->mainloop);
@@ -160,7 +164,7 @@ unlock_and_fail:
static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror)
{
- paaudio *g = &glob_paaudio;
+ paaudio *g = p->g;
pa_threaded_mainloop_lock (g->mainloop);
@@ -222,7 +226,7 @@ static void *qpa_thread_out (void *arg)
}
}
- decr = to_mix = audio_MIN (pa->live, glob_paaudio.samples >> 2);
+ decr = to_mix = audio_MIN (pa->live, pa->g->conf.samples >> 2);
rpos = pa->rpos;
if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
@@ -314,7 +318,7 @@ static void *qpa_thread_in (void *arg)
}
}
- incr = to_grab = audio_MIN (pa->dead, glob_paaudio.samples >> 2);
+ incr = to_grab = audio_MIN (pa->dead, pa->g->conf.samples >> 2);
wpos = pa->wpos;
if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
@@ -430,7 +434,7 @@ static audfmt_e pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
static void context_state_cb (pa_context *c, void *userdata)
{
- paaudio *g = &glob_paaudio;
+ paaudio *g = userdata;
switch (pa_context_get_state(c)) {
case PA_CONTEXT_READY:
@@ -449,7 +453,7 @@ static void context_state_cb (pa_context *c, void *userdata)
static void stream_state_cb (pa_stream *s, void * userdata)
{
- paaudio *g = &glob_paaudio;
+ paaudio *g = userdata;
switch (pa_stream_get_state (s)) {
@@ -467,23 +471,21 @@ static void stream_state_cb (pa_stream *s, void * userdata)
static void stream_request_cb (pa_stream *s, size_t length, void *userdata)
{
- paaudio *g = &glob_paaudio;
+ paaudio *g = userdata;
pa_threaded_mainloop_signal (g->mainloop, 0);
}
static pa_stream *qpa_simple_new (
- const char *server,
+ paaudio *g,
const char *name,
pa_stream_direction_t dir,
const char *dev,
- const char *stream_name,
const pa_sample_spec *ss,
const pa_channel_map *map,
const pa_buffer_attr *attr,
int *rerror)
{
- paaudio *g = &glob_paaudio;
int r;
pa_stream *stream;
@@ -534,13 +536,15 @@ fail:
return NULL;
}
-static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
{
int error;
- static pa_sample_spec ss;
- static pa_buffer_attr ba;
+ pa_sample_spec ss;
+ pa_buffer_attr ba;
struct audsettings obt_as = *as;
PAVoiceOut *pa = (PAVoiceOut *) hw;
+ paaudio *g = pa->g = drv_opaque;
ss.format = audfmt_to_pa (as->fmt, as->endianness);
ss.channels = as->nchannels;
@@ -558,11 +562,10 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
pa->stream = qpa_simple_new (
- glob_paaudio.server,
+ g,
"qemu",
PA_STREAM_PLAYBACK,
- glob_paaudio.sink,
- "pcm.playback",
+ g->conf.sink,
&ss,
NULL, /* channel map */
&ba, /* buffering attributes */
@@ -574,7 +577,7 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
}
audio_pcm_init_info (&hw->info, &obt_as);
- hw->samples = glob_paaudio.samples;
+ hw->samples = g->conf.samples;
pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
pa->rpos = hw->rpos;
if (!pa->pcm_buf) {
@@ -601,12 +604,13 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
return -1;
}
-static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
{
int error;
- static pa_sample_spec ss;
+ pa_sample_spec ss;
struct audsettings obt_as = *as;
PAVoiceIn *pa = (PAVoiceIn *) hw;
+ paaudio *g = pa->g = drv_opaque;
ss.format = audfmt_to_pa (as->fmt, as->endianness);
ss.channels = as->nchannels;
@@ -615,11 +619,10 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
pa->stream = qpa_simple_new (
- glob_paaudio.server,
+ g,
"qemu",
PA_STREAM_RECORD,
- glob_paaudio.source,
- "pcm.capture",
+ g->conf.source,
&ss,
NULL, /* channel map */
NULL, /* buffering attributes */
@@ -631,7 +634,7 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
}
audio_pcm_init_info (&hw->info, &obt_as);
- hw->samples = glob_paaudio.samples;
+ hw->samples = g->conf.samples;
pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
pa->wpos = hw->wpos;
if (!pa->pcm_buf) {
@@ -703,7 +706,7 @@ static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...)
PAVoiceOut *pa = (PAVoiceOut *) hw;
pa_operation *op;
pa_cvolume v;
- paaudio *g = &glob_paaudio;
+ paaudio *g = pa->g;
#ifdef PA_CHECK_VERSION /* macro is present in 0.9.16+ */
pa_cvolume_init (&v); /* function is present in 0.9.13+ */
@@ -755,7 +758,7 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
PAVoiceIn *pa = (PAVoiceIn *) hw;
pa_operation *op;
pa_cvolume v;
- paaudio *g = &glob_paaudio;
+ paaudio *g = pa->g;
#ifdef PA_CHECK_VERSION
pa_cvolume_init (&v);
@@ -805,23 +808,31 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
}
/* common */
+static PAConf glob_conf = {
+ .samples = 4096,
+};
+
static void *qpa_audio_init (void)
{
- paaudio *g = &glob_paaudio;
+ paaudio *g = g_malloc(sizeof(paaudio));
+ g->conf = glob_conf;
+ g->mainloop = NULL;
+ g->context = NULL;
g->mainloop = pa_threaded_mainloop_new ();
if (!g->mainloop) {
goto fail;
}
- g->context = pa_context_new (pa_threaded_mainloop_get_api (g->mainloop), glob_paaudio.server);
+ g->context = pa_context_new (pa_threaded_mainloop_get_api (g->mainloop),
+ g->conf.server);
if (!g->context) {
goto fail;
}
pa_context_set_state_callback (g->context, context_state_cb, g);
- if (pa_context_connect (g->context, glob_paaudio.server, 0, NULL) < 0) {
+ if (pa_context_connect (g->context, g->conf.server, 0, NULL) < 0) {
qpa_logerr (pa_context_errno (g->context),
"pa_context_connect() failed\n");
goto fail;
@@ -854,12 +865,13 @@ static void *qpa_audio_init (void)
pa_threaded_mainloop_unlock (g->mainloop);
- return &glob_paaudio;
+ return g;
unlock_and_fail:
pa_threaded_mainloop_unlock (g->mainloop);
fail:
AUD_log (AUDIO_CAP, "Failed to initialize PA context");
+ qpa_audio_fini(g);
return NULL;
}
@@ -874,39 +886,38 @@ static void qpa_audio_fini (void *opaque)
if (g->context) {
pa_context_disconnect (g->context);
pa_context_unref (g->context);
- g->context = NULL;
}
if (g->mainloop) {
pa_threaded_mainloop_free (g->mainloop);
}
- g->mainloop = NULL;
+ g_free(g);
}
struct audio_option qpa_options[] = {
{
.name = "SAMPLES",
.tag = AUD_OPT_INT,
- .valp = &glob_paaudio.samples,
+ .valp = &glob_conf.samples,
.descr = "buffer size in samples"
},
{
.name = "SERVER",
.tag = AUD_OPT_STR,
- .valp = &glob_paaudio.server,
+ .valp = &glob_conf.server,
.descr = "server address"
},
{
.name = "SINK",
.tag = AUD_OPT_STR,
- .valp = &glob_paaudio.sink,
+ .valp = &glob_conf.sink,
.descr = "sink device name"
},
{
.name = "SOURCE",
.tag = AUD_OPT_STR,
- .valp = &glob_paaudio.source,
+ .valp = &glob_conf.source,
.descr = "source device name"
},
{ /* End of list */ }
diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index d24daa5ead..1140f2ea0a 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -55,6 +55,7 @@ static struct SDLAudioState {
SDL_mutex *mutex;
SDL_sem *sem;
int initialized;
+ bool driver_created;
} glob_sdl;
typedef struct SDLAudioState SDLAudioState;
@@ -332,7 +333,8 @@ static void sdl_fini_out (HWVoiceOut *hw)
sdl_close (&glob_sdl);
}
-static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
{
SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
SDLAudioState *s = &glob_sdl;
@@ -392,6 +394,10 @@ static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...)
static void *sdl_audio_init (void)
{
SDLAudioState *s = &glob_sdl;
+ if (s->driver_created) {
+ sdl_logerr("Can't create multiple sdl backends\n");
+ return NULL;
+ }
if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
sdl_logerr ("SDL failed to initialize audio subsystem\n");
@@ -413,6 +419,7 @@ static void *sdl_audio_init (void)
return NULL;
}
+ s->driver_created = true;
return s;
}
@@ -423,6 +430,7 @@ static void sdl_audio_fini (void *opaque)
SDL_DestroySemaphore (s->sem);
SDL_DestroyMutex (s->mutex);
SDL_QuitSubSystem (SDL_INIT_AUDIO);
+ s->driver_created = false;
}
static struct audio_option sdl_options[] = {
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index 7b79bedca2..5c6f726757 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -115,7 +115,8 @@ static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate)
/* playback */
-static int line_out_init (HWVoiceOut *hw, struct audsettings *as)
+static int line_out_init(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
{
SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw);
struct audsettings settings;
@@ -243,7 +244,7 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...)
/* record */
-static int line_in_init (HWVoiceIn *hw, struct audsettings *as)
+static int line_in_init(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
{
SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
struct audsettings settings;
diff --git a/audio/wavaudio.c b/audio/wavaudio.c
index 6846a1a9f7..c586020c59 100644
--- a/audio/wavaudio.c
+++ b/audio/wavaudio.c
@@ -36,15 +36,10 @@ typedef struct WAVVoiceOut {
int total_samples;
} WAVVoiceOut;
-static struct {
+typedef struct {
struct audsettings settings;
const char *wav_path;
-} conf = {
- .settings.freq = 44100,
- .settings.nchannels = 2,
- .settings.fmt = AUD_FMT_S16,
- .wav_path = "qemu.wav"
-};
+} WAVConf;
static int wav_run_out (HWVoiceOut *hw, int live)
{
@@ -105,7 +100,8 @@ static void le_store (uint8_t *buf, uint32_t val, int len)
}
}
-static int wav_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int wav_init_out(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
{
WAVVoiceOut *wav = (WAVVoiceOut *) hw;
int bits16 = 0, stereo = 0;
@@ -115,9 +111,8 @@ static int wav_init_out (HWVoiceOut *hw, struct audsettings *as)
0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
};
- struct audsettings wav_as = conf.settings;
-
- (void) as;
+ WAVConf *conf = drv_opaque;
+ struct audsettings wav_as = conf->settings;
stereo = wav_as.nchannels == 2;
switch (wav_as.fmt) {
@@ -155,10 +150,10 @@ static int wav_init_out (HWVoiceOut *hw, struct audsettings *as)
le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
le_store (hdr + 32, 1 << (bits16 + stereo), 2);
- wav->f = fopen (conf.wav_path, "wb");
+ wav->f = fopen (conf->wav_path, "wb");
if (!wav->f) {
dolog ("Failed to open wave file `%s'\nReason: %s\n",
- conf.wav_path, strerror (errno));
+ conf->wav_path, strerror (errno));
g_free (wav->pcm_buf);
wav->pcm_buf = NULL;
return -1;
@@ -226,40 +221,49 @@ static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...)
return 0;
}
+static WAVConf glob_conf = {
+ .settings.freq = 44100,
+ .settings.nchannels = 2,
+ .settings.fmt = AUD_FMT_S16,
+ .wav_path = "qemu.wav"
+};
+
static void *wav_audio_init (void)
{
- return &conf;
+ WAVConf *conf = g_malloc(sizeof(WAVConf));
+ *conf = glob_conf;
+ return conf;
}
static void wav_audio_fini (void *opaque)
{
- (void) opaque;
ldebug ("wav_fini");
+ g_free(opaque);
}
static struct audio_option wav_options[] = {
{
.name = "FREQUENCY",
.tag = AUD_OPT_INT,
- .valp = &conf.settings.freq,
+ .valp = &glob_conf.settings.freq,
.descr = "Frequency"
},
{
.name = "FORMAT",
.tag = AUD_OPT_FMT,
- .valp = &conf.settings.fmt,
+ .valp = &glob_conf.settings.fmt,
.descr = "Format"
},
{
.name = "DAC_FIXED_CHANNELS",
.tag = AUD_OPT_INT,
- .valp = &conf.settings.nchannels,
+ .valp = &glob_conf.settings.nchannels,
.descr = "Number of channels (1 - mono, 2 - stereo)"
},
{
.name = "PATH",
.tag = AUD_OPT_STR,
- .valp = &conf.wav_path,
+ .valp = &glob_conf.wav_path,
.descr = "Path to wave file"
},
{ /* End of list */ }
diff --git a/audio/winwaveaudio.c b/audio/winwaveaudio.c
deleted file mode 100644
index 8dbd145ca1..0000000000
--- a/audio/winwaveaudio.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/* public domain */
-
-#include "qemu-common.h"
-#include "sysemu/sysemu.h"
-#include "audio.h"
-
-#define AUDIO_CAP "winwave"
-#include "audio_int.h"
-
-#include <windows.h>
-#include <mmsystem.h>
-
-#include "audio_win_int.h"
-
-static struct {
- int dac_headers;
- int dac_samples;
- int adc_headers;
- int adc_samples;
-} conf = {
- .dac_headers = 4,
- .dac_samples = 1024,
- .adc_headers = 4,
- .adc_samples = 1024
-};
-
-typedef struct {
- HWVoiceOut hw;
- HWAVEOUT hwo;
- WAVEHDR *hdrs;
- HANDLE event;
- void *pcm_buf;
- int avail;
- int pending;
- int curhdr;
- int paused;
- CRITICAL_SECTION crit_sect;
-} WaveVoiceOut;
-
-typedef struct {
- HWVoiceIn hw;
- HWAVEIN hwi;
- WAVEHDR *hdrs;
- HANDLE event;
- void *pcm_buf;
- int curhdr;
- int paused;
- int rpos;
- int avail;
- CRITICAL_SECTION crit_sect;
-} WaveVoiceIn;
-
-static void winwave_log_mmresult (MMRESULT mr)
-{
- const char *str = "BUG";
-
- switch (mr) {
- case MMSYSERR_NOERROR:
- str = "Success";
- break;
-
- case MMSYSERR_INVALHANDLE:
- str = "Specified device handle is invalid";
- break;
-
- case MMSYSERR_BADDEVICEID:
- str = "Specified device id is out of range";
- break;
-
- case MMSYSERR_NODRIVER:
- str = "No device driver is present";
- break;
-
- case MMSYSERR_NOMEM:
- str = "Unable to allocate or lock memory";
- break;
-
- case WAVERR_SYNC:
- str = "Device is synchronous but waveOutOpen was called "
- "without using the WINWAVE_ALLOWSYNC flag";
- break;
-
- case WAVERR_UNPREPARED:
- str = "The data block pointed to by the pwh parameter "
- "hasn't been prepared";
- break;
-
- case WAVERR_STILLPLAYING:
- str = "There are still buffers in the queue";
- break;
-
- default:
- dolog ("Reason: Unknown (MMRESULT %#x)\n", mr);
- return;
- }
-
- dolog ("Reason: %s\n", str);
-}
-
-static void GCC_FMT_ATTR (2, 3) winwave_logerr (
- MMRESULT mr,
- const char *fmt,
- ...
- )
-{
- va_list ap;
-
- va_start (ap, fmt);
- AUD_vlog (AUDIO_CAP, fmt, ap);
- va_end (ap);
-
- AUD_log (NULL, " failed\n");
- winwave_log_mmresult (mr);
-}
-
-static void winwave_anal_close_out (WaveVoiceOut *wave)
-{
- MMRESULT mr;
-
- mr = waveOutClose (wave->hwo);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveOutClose");
- }
- wave->hwo = NULL;
-}
-
-static void CALLBACK winwave_callback_out (
- HWAVEOUT hwo,
- UINT msg,
- DWORD_PTR dwInstance,
- DWORD_PTR dwParam1,
- DWORD_PTR dwParam2
- )
-{
- WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance;
-
- switch (msg) {
- case WOM_DONE:
- {
- WAVEHDR *h = (WAVEHDR *) dwParam1;
- if (!h->dwUser) {
- h->dwUser = 1;
- EnterCriticalSection (&wave->crit_sect);
- {
- wave->avail += conf.dac_samples;
- }
- LeaveCriticalSection (&wave->crit_sect);
- if (wave->hw.poll_mode) {
- if (!SetEvent (wave->event)) {
- dolog ("DAC SetEvent failed %lx\n", GetLastError ());
- }
- }
- }
- }
- break;
-
- case WOM_CLOSE:
- case WOM_OPEN:
- break;
-
- default:
- dolog ("unknown wave out callback msg %x\n", msg);
- }
-}
-
-static int winwave_init_out (HWVoiceOut *hw, struct audsettings *as)
-{
- int i;
- int err;
- MMRESULT mr;
- WAVEFORMATEX wfx;
- WaveVoiceOut *wave;
-
- wave = (WaveVoiceOut *) hw;
-
- InitializeCriticalSection (&wave->crit_sect);
-
- err = waveformat_from_audio_settings (&wfx, as);
- if (err) {
- goto err0;
- }
-
- mr = waveOutOpen (&wave->hwo, WAVE_MAPPER, &wfx,
- (DWORD_PTR) winwave_callback_out,
- (DWORD_PTR) wave, CALLBACK_FUNCTION);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveOutOpen");
- goto err1;
- }
-
- wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
- sizeof (*wave->hdrs));
- if (!wave->hdrs) {
- goto err2;
- }
-
- audio_pcm_init_info (&hw->info, as);
- hw->samples = conf.dac_samples * conf.dac_headers;
- wave->avail = hw->samples;
-
- wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.dac_samples,
- conf.dac_headers << hw->info.shift);
- if (!wave->pcm_buf) {
- goto err3;
- }
-
- for (i = 0; i < conf.dac_headers; ++i) {
- WAVEHDR *h = &wave->hdrs[i];
-
- h->dwUser = 0;
- h->dwBufferLength = conf.dac_samples << hw->info.shift;
- h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
- h->dwFlags = 0;
-
- mr = waveOutPrepareHeader (wave->hwo, h, sizeof (*h));
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveOutPrepareHeader(%d)", i);
- goto err4;
- }
- }
-
- return 0;
-
- err4:
- g_free (wave->pcm_buf);
- err3:
- g_free (wave->hdrs);
- err2:
- winwave_anal_close_out (wave);
- err1:
- err0:
- return -1;
-}
-
-static int winwave_write (SWVoiceOut *sw, void *buf, int len)
-{
- return audio_pcm_sw_write (sw, buf, len);
-}
-
-static int winwave_run_out (HWVoiceOut *hw, int live)
-{
- WaveVoiceOut *wave = (WaveVoiceOut *) hw;
- int decr;
- int doreset;
-
- EnterCriticalSection (&wave->crit_sect);
- {
- decr = audio_MIN (live, wave->avail);
- decr = audio_pcm_hw_clip_out (hw, wave->pcm_buf, decr, wave->pending);
- wave->pending += decr;
- wave->avail -= decr;
- }
- LeaveCriticalSection (&wave->crit_sect);
-
- doreset = hw->poll_mode && (wave->pending >= conf.dac_samples);
- if (doreset && !ResetEvent (wave->event)) {
- dolog ("DAC ResetEvent failed %lx\n", GetLastError ());
- }
-
- while (wave->pending >= conf.dac_samples) {
- MMRESULT mr;
- WAVEHDR *h = &wave->hdrs[wave->curhdr];
-
- h->dwUser = 0;
- mr = waveOutWrite (wave->hwo, h, sizeof (*h));
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveOutWrite(%d)", wave->curhdr);
- break;
- }
-
- wave->pending -= conf.dac_samples;
- wave->curhdr = (wave->curhdr + 1) % conf.dac_headers;
- }
-
- return decr;
-}
-
-static void winwave_poll (void *opaque)
-{
- (void) opaque;
- audio_run ("winwave_poll");
-}
-
-static void winwave_fini_out (HWVoiceOut *hw)
-{
- int i;
- MMRESULT mr;
- WaveVoiceOut *wave = (WaveVoiceOut *) hw;
-
- mr = waveOutReset (wave->hwo);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveOutReset");
- }
-
- for (i = 0; i < conf.dac_headers; ++i) {
- mr = waveOutUnprepareHeader (wave->hwo, &wave->hdrs[i],
- sizeof (wave->hdrs[i]));
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveOutUnprepareHeader(%d)", i);
- }
- }
-
- winwave_anal_close_out (wave);
-
- if (wave->event) {
- qemu_del_wait_object (wave->event, winwave_poll, wave);
- if (!CloseHandle (wave->event)) {
- dolog ("DAC CloseHandle failed %lx\n", GetLastError ());
- }
- wave->event = NULL;
- }
-
- g_free (wave->pcm_buf);
- wave->pcm_buf = NULL;
-
- g_free (wave->hdrs);
- wave->hdrs = NULL;
-}
-
-static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
-{
- MMRESULT mr;
- WaveVoiceOut *wave = (WaveVoiceOut *) hw;
-
- switch (cmd) {
- case VOICE_ENABLE:
- {
- va_list ap;
- int poll_mode;
-
- va_start (ap, cmd);
- poll_mode = va_arg (ap, int);
- va_end (ap);
-
- if (poll_mode && !wave->event) {
- wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
- if (!wave->event) {
- dolog ("DAC CreateEvent: %lx, poll mode will be disabled\n",
- GetLastError ());
- }
- }
-
- if (wave->event) {
- int ret;
-
- ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
- hw->poll_mode = (ret == 0);
- }
- else {
- hw->poll_mode = 0;
- }
- wave->paused = 0;
- }
- return 0;
-
- case VOICE_DISABLE:
- if (!wave->paused) {
- mr = waveOutReset (wave->hwo);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveOutReset");
- }
- else {
- wave->paused = 1;
- }
- }
- if (wave->event) {
- qemu_del_wait_object (wave->event, winwave_poll, wave);
- }
- return 0;
- }
- return -1;
-}
-
-static void winwave_anal_close_in (WaveVoiceIn *wave)
-{
- MMRESULT mr;
-
- mr = waveInClose (wave->hwi);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveInClose");
- }
- wave->hwi = NULL;
-}
-
-static void CALLBACK winwave_callback_in (
- HWAVEIN *hwi,
- UINT msg,
- DWORD_PTR dwInstance,
- DWORD_PTR dwParam1,
- DWORD_PTR dwParam2
- )
-{
- WaveVoiceIn *wave = (WaveVoiceIn *) dwInstance;
-
- switch (msg) {
- case WIM_DATA:
- {
- WAVEHDR *h = (WAVEHDR *) dwParam1;
- if (!h->dwUser) {
- h->dwUser = 1;
- EnterCriticalSection (&wave->crit_sect);
- {
- wave->avail += conf.adc_samples;
- }
- LeaveCriticalSection (&wave->crit_sect);
- if (wave->hw.poll_mode) {
- if (!SetEvent (wave->event)) {
- dolog ("ADC SetEvent failed %lx\n", GetLastError ());
- }
- }
- }
- }
- break;
-
- case WIM_CLOSE:
- case WIM_OPEN:
- break;
-
- default:
- dolog ("unknown wave in callback msg %x\n", msg);
- }
-}
-
-static void winwave_add_buffers (WaveVoiceIn *wave, int samples)
-{
- int doreset;
-
- doreset = wave->hw.poll_mode && (samples >= conf.adc_samples);
- if (doreset && !ResetEvent (wave->event)) {
- dolog ("ADC ResetEvent failed %lx\n", GetLastError ());
- }
-
- while (samples >= conf.adc_samples) {
- MMRESULT mr;
- WAVEHDR *h = &wave->hdrs[wave->curhdr];
-
- h->dwUser = 0;
- mr = waveInAddBuffer (wave->hwi, h, sizeof (*h));
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveInAddBuffer(%d)", wave->curhdr);
- }
- wave->curhdr = (wave->curhdr + 1) % conf.adc_headers;
- samples -= conf.adc_samples;
- }
-}
-
-static int winwave_init_in (HWVoiceIn *hw, struct audsettings *as)
-{
- int i;
- int err;
- MMRESULT mr;
- WAVEFORMATEX wfx;
- WaveVoiceIn *wave;
-
- wave = (WaveVoiceIn *) hw;
-
- InitializeCriticalSection (&wave->crit_sect);
-
- err = waveformat_from_audio_settings (&wfx, as);
- if (err) {
- goto err0;
- }
-
- mr = waveInOpen (&wave->hwi, WAVE_MAPPER, &wfx,
- (DWORD_PTR) winwave_callback_in,
- (DWORD_PTR) wave, CALLBACK_FUNCTION);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveInOpen");
- goto err1;
- }
-
- wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
- sizeof (*wave->hdrs));
- if (!wave->hdrs) {
- goto err2;
- }
-
- audio_pcm_init_info (&hw->info, as);
- hw->samples = conf.adc_samples * conf.adc_headers;
- wave->avail = 0;
-
- wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.adc_samples,
- conf.adc_headers << hw->info.shift);
- if (!wave->pcm_buf) {
- goto err3;
- }
-
- for (i = 0; i < conf.adc_headers; ++i) {
- WAVEHDR *h = &wave->hdrs[i];
-
- h->dwUser = 0;
- h->dwBufferLength = conf.adc_samples << hw->info.shift;
- h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
- h->dwFlags = 0;
-
- mr = waveInPrepareHeader (wave->hwi, h, sizeof (*h));
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveInPrepareHeader(%d)", i);
- goto err4;
- }
- }
-
- wave->paused = 1;
- winwave_add_buffers (wave, hw->samples);
- return 0;
-
- err4:
- g_free (wave->pcm_buf);
- err3:
- g_free (wave->hdrs);
- err2:
- winwave_anal_close_in (wave);
- err1:
- err0:
- return -1;
-}
-
-static void winwave_fini_in (HWVoiceIn *hw)
-{
- int i;
- MMRESULT mr;
- WaveVoiceIn *wave = (WaveVoiceIn *) hw;
-
- mr = waveInReset (wave->hwi);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveInReset");
- }
-
- for (i = 0; i < conf.adc_headers; ++i) {
- mr = waveInUnprepareHeader (wave->hwi, &wave->hdrs[i],
- sizeof (wave->hdrs[i]));
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveInUnprepareHeader(%d)", i);
- }
- }
-
- winwave_anal_close_in (wave);
-
- if (wave->event) {
- qemu_del_wait_object (wave->event, winwave_poll, wave);
- if (!CloseHandle (wave->event)) {
- dolog ("ADC CloseHandle failed %lx\n", GetLastError ());
- }
- wave->event = NULL;
- }
-
- g_free (wave->pcm_buf);
- wave->pcm_buf = NULL;
-
- g_free (wave->hdrs);
- wave->hdrs = NULL;
-}
-
-static int winwave_run_in (HWVoiceIn *hw)
-{
- WaveVoiceIn *wave = (WaveVoiceIn *) hw;
- int live = audio_pcm_hw_get_live_in (hw);
- int dead = hw->samples - live;
- int decr, ret;
-
- if (!dead) {
- return 0;
- }
-
- EnterCriticalSection (&wave->crit_sect);
- {
- decr = audio_MIN (dead, wave->avail);
- wave->avail -= decr;
- }
- LeaveCriticalSection (&wave->crit_sect);
-
- ret = decr;
- while (decr) {
- int left = hw->samples - hw->wpos;
- int conv = audio_MIN (left, decr);
- hw->conv (hw->conv_buf + hw->wpos,
- advance (wave->pcm_buf, wave->rpos << hw->info.shift),
- conv);
-
- wave->rpos = (wave->rpos + conv) % hw->samples;
- hw->wpos = (hw->wpos + conv) % hw->samples;
- decr -= conv;
- }
-
- winwave_add_buffers (wave, ret);
- return ret;
-}
-
-static int winwave_read (SWVoiceIn *sw, void *buf, int size)
-{
- return audio_pcm_sw_read (sw, buf, size);
-}
-
-static int winwave_ctl_in (HWVoiceIn *hw, int cmd, ...)
-{
- MMRESULT mr;
- WaveVoiceIn *wave = (WaveVoiceIn *) hw;
-
- switch (cmd) {
- case VOICE_ENABLE:
- {
- va_list ap;
- int poll_mode;
-
- va_start (ap, cmd);
- poll_mode = va_arg (ap, int);
- va_end (ap);
-
- if (poll_mode && !wave->event) {
- wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
- if (!wave->event) {
- dolog ("ADC CreateEvent: %lx, poll mode will be disabled\n",
- GetLastError ());
- }
- }
-
- if (wave->event) {
- int ret;
-
- ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
- hw->poll_mode = (ret == 0);
- }
- else {
- hw->poll_mode = 0;
- }
- if (wave->paused) {
- mr = waveInStart (wave->hwi);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveInStart");
- }
- wave->paused = 0;
- }
- }
- return 0;
-
- case VOICE_DISABLE:
- if (!wave->paused) {
- mr = waveInStop (wave->hwi);
- if (mr != MMSYSERR_NOERROR) {
- winwave_logerr (mr, "waveInStop");
- }
- else {
- wave->paused = 1;
- }
- }
- if (wave->event) {
- qemu_del_wait_object (wave->event, winwave_poll, wave);
- }
- return 0;
- }
- return 0;
-}
-
-static void *winwave_audio_init (void)
-{
- return &conf;
-}
-
-static void winwave_audio_fini (void *opaque)
-{
- (void) opaque;
-}
-
-static struct audio_option winwave_options[] = {
- {
- .name = "DAC_HEADERS",
- .tag = AUD_OPT_INT,
- .valp = &conf.dac_headers,
- .descr = "DAC number of headers",
- },
- {
- .name = "DAC_SAMPLES",
- .tag = AUD_OPT_INT,
- .valp = &conf.dac_samples,
- .descr = "DAC number of samples per header",
- },
- {
- .name = "ADC_HEADERS",
- .tag = AUD_OPT_INT,
- .valp = &conf.adc_headers,
- .descr = "ADC number of headers",
- },
- {
- .name = "ADC_SAMPLES",
- .tag = AUD_OPT_INT,
- .valp = &conf.adc_samples,
- .descr = "ADC number of samples per header",
- },
- { /* End of list */ }
-};
-
-static struct audio_pcm_ops winwave_pcm_ops = {
- .init_out = winwave_init_out,
- .fini_out = winwave_fini_out,
- .run_out = winwave_run_out,
- .write = winwave_write,
- .ctl_out = winwave_ctl_out,
- .init_in = winwave_init_in,
- .fini_in = winwave_fini_in,
- .run_in = winwave_run_in,
- .read = winwave_read,
- .ctl_in = winwave_ctl_in
-};
-
-struct audio_driver winwave_audio_driver = {
- .name = "winwave",
- .descr = "Windows Waveform Audio http://msdn.microsoft.com",
- .options = winwave_options,
- .init = winwave_audio_init,
- .fini = winwave_audio_fini,
- .pcm_ops = &winwave_pcm_ops,
- .can_be_default = 1,
- .max_voices_out = INT_MAX,
- .max_voices_in = INT_MAX,
- .voice_size_out = sizeof (WaveVoiceOut),
- .voice_size_in = sizeof (WaveVoiceIn)
-};
diff --git a/configure b/configure
index 409edf94fb..222694f34d 100755
--- a/configure
+++ b/configure
@@ -285,8 +285,6 @@ sysconfdir="\${prefix}/etc"
local_statedir="\${prefix}/var"
confsuffix="/qemu"
slirp="yes"
-fmod_lib=""
-fmod_inc=""
oss_lib=""
bsd="no"
linux="no"
@@ -437,6 +435,14 @@ EOF
compile_object
}
+check_include() {
+cat > $TMPC <<EOF
+#include <$1>
+int main(void) { return 0; }
+EOF
+ compile_object
+}
+
write_c_skeleton() {
cat > $TMPC <<EOF
int main(void) { return 0; }
@@ -564,24 +570,28 @@ case $targetos in
CYGWIN*)
mingw32="yes"
QEMU_CFLAGS="-mno-cygwin $QEMU_CFLAGS"
- audio_possible_drivers="winwave sdl"
- audio_drv_list="winwave"
+ audio_possible_drivers="sdl"
+ audio_drv_list="sdl"
;;
MINGW32*)
mingw32="yes"
- audio_possible_drivers="winwave dsound sdl fmod"
- audio_drv_list="winwave"
+ audio_possible_drivers="dsound sdl"
+ if check_include dsound.h; then
+ audio_drv_list="dsound"
+ else
+ audio_drv_list=""
+ fi
;;
GNU/kFreeBSD)
bsd="yes"
audio_drv_list="oss"
- audio_possible_drivers="oss sdl esd pa"
+ audio_possible_drivers="oss sdl pa"
;;
FreeBSD)
bsd="yes"
make="${MAKE-gmake}"
audio_drv_list="oss"
- audio_possible_drivers="oss sdl esd pa"
+ audio_possible_drivers="oss sdl pa"
# needed for kinfo_getvmmap(3) in libutil.h
LIBS="-lutil $LIBS"
netmap="" # enable netmap autodetect
@@ -591,14 +601,14 @@ DragonFly)
bsd="yes"
make="${MAKE-gmake}"
audio_drv_list="oss"
- audio_possible_drivers="oss sdl esd pa"
+ audio_possible_drivers="oss sdl pa"
HOST_VARIANT_DIR="dragonfly"
;;
NetBSD)
bsd="yes"
make="${MAKE-gmake}"
audio_drv_list="oss"
- audio_possible_drivers="oss sdl esd"
+ audio_possible_drivers="oss sdl"
oss_lib="-lossaudio"
HOST_VARIANT_DIR="netbsd"
;;
@@ -606,7 +616,7 @@ OpenBSD)
bsd="yes"
make="${MAKE-gmake}"
audio_drv_list="sdl"
- audio_possible_drivers="sdl esd"
+ audio_possible_drivers="sdl"
HOST_VARIANT_DIR="openbsd"
;;
Darwin)
@@ -619,7 +629,7 @@ Darwin)
fi
cocoa="yes"
audio_drv_list="coreaudio"
- audio_possible_drivers="coreaudio sdl fmod"
+ audio_possible_drivers="coreaudio sdl"
LDFLAGS="-framework CoreFoundation -framework IOKit $LDFLAGS"
libs_softmmu="-F/System/Library/Frameworks -framework Cocoa -framework IOKit $libs_softmmu"
# Disable attempts to use ObjectiveC features in os/object.h since they
@@ -674,15 +684,12 @@ Haiku)
;;
*)
audio_drv_list="oss"
- audio_possible_drivers="oss alsa sdl esd pa"
+ audio_possible_drivers="oss alsa sdl pa"
linux="yes"
linux_user="yes"
kvm="yes"
vhost_net="yes"
vhost_scsi="yes"
- if [ "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "x32" ] ; then
- audio_possible_drivers="$audio_possible_drivers fmod"
- fi
QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES"
;;
esac
@@ -847,10 +854,6 @@ for opt do
;;
--enable-vnc) vnc="yes"
;;
- --fmod-lib=*) fmod_lib="$optarg"
- ;;
- --fmod-inc=*) fmod_inc="$optarg"
- ;;
--oss-lib=*) oss_lib="$optarg"
;;
--audio-drv-list=*) audio_drv_list="$optarg"
@@ -1349,8 +1352,6 @@ Advanced options (experts only):
--disable-guest-base disable GUEST_BASE support
--enable-pie build Position Independent Executables
--disable-pie do not build Position Independent Executables
- --fmod-lib path to FMOD library
- --fmod-inc path to FMOD includes
--oss-lib path to OSS library
--cpu=CPU Build for host CPU [$cpu]
--disable-uuid disable uuid support
@@ -2621,21 +2622,6 @@ for drv in $audio_drv_list; do
libs_softmmu="-lasound $libs_softmmu"
;;
- fmod)
- if test -z $fmod_lib || test -z $fmod_inc; then
- error_exit "You must specify path to FMOD library and headers" \
- "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so"
- fi
- audio_drv_probe $drv fmod.h $fmod_lib "return FSOUND_GetVersion();" "-I $fmod_inc"
- libs_softmmu="$fmod_lib $libs_softmmu"
- ;;
-
- esd)
- audio_drv_probe $drv esd.h -lesd 'return esd_play_stream(0, 0, "", 0);'
- libs_softmmu="-lesd $libs_softmmu"
- audio_pt_int="yes"
- ;;
-
pa)
audio_drv_probe $drv pulse/mainloop.h "-lpulse" \
"pa_mainloop *m = 0; pa_mainloop_free (m); return 0;"
@@ -2660,11 +2646,6 @@ for drv in $audio_drv_list; do
# XXX: Probes for CoreAudio, DirectSound, SDL(?)
;;
- winwave)
- libs_softmmu="-lwinmm $libs_softmmu"
- audio_win_int="yes"
- ;;
-
*)
echo "$audio_possible_drivers" | grep -q "\<$drv\>" || {
error_exit "Unknown driver '$drv' selected" \
@@ -4629,9 +4610,6 @@ echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
for drv in $audio_drv_list; do
def=CONFIG_`echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]'`
echo "$def=y" >> $config_host_mak
- if test "$drv" = "fmod"; then
- echo "FMOD_CFLAGS=-I$fmod_inc" >> $config_host_mak
- fi
done
if test "$audio_pt_int" = "yes" ; then
echo "CONFIG_AUDIO_PT_INT=y" >> $config_host_mak
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 57f8394a94..88644ceda7 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -8,7 +8,6 @@
#include "qemu/readline.h"
extern Monitor *cur_mon;
-extern Monitor *default_mon;
/* flags for monitor_init */
#define MONITOR_IS_DEFAULT 0x01
diff --git a/monitor.c b/monitor.c
index 6a4642493a..8e1a2e85b8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -226,7 +226,6 @@ static mon_cmd_t info_cmds[];
static const mon_cmd_t qmp_cmds[];
Monitor *cur_mon;
-Monitor *default_mon;
static void monitor_command_cb(void *opaque, const char *cmdline,
void *readline_opaque);
@@ -5298,9 +5297,6 @@ void monitor_init(CharDriverState *chr, int flags)
qemu_mutex_lock(&monitor_lock);
QLIST_INSERT_HEAD(&mon_list, mon, entry);
qemu_mutex_unlock(&monitor_lock);
-
- if (!default_mon || (flags & MONITOR_IS_DEFAULT))
- default_mon = mon;
}
static void bdrv_password_cb(void *opaque, const char *password,
diff --git a/trace-events b/trace-events
index 6060d36773..52b7efa9a4 100644
--- a/trace-events
+++ b/trace-events
@@ -1632,3 +1632,19 @@ cpu_unhalt(int cpu_index) "unhalting cpu %d"
# hw/arm/virt-acpi-build.c
virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out."
+
+# audio/alsaaudio.c
+alsa_revents(int revents) "revents = %d"
+alsa_pollout(int i, int fd) "i = %d fd = %d"
+alsa_set_handler(int events, int index, int fd, int err) "events=%#x index=%d fd=%d err=%d"
+alsa_wrote_zero(int len) "Failed to write %d frames (wrote zero)"
+alsa_read_zero(long len) "Failed to read %ld frames (read zero)"
+alsa_xrun_out(void) "Recovering from playback xrun"
+alsa_xrun_in(void) "Recovering from capture xrun"
+alsa_resume_out(void) "Resuming suspended output stream"
+alsa_resume_in(void) "Resuming suspended input stream"
+alsa_no_frames(int state) "No frames available and ALSA state is %d"
+
+# audio/ossaudio.c
+oss_version(int version) "OSS version = %#x"
+oss_invalid_available_size(int size, int bufsize) "Invalid available size, size=%d bufsize=%d"