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) M: Gerd Hoffmann 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); + hr = IDirectSoundBuffer_Restore (dsb); - switch (hr) { - case DS_OK: - return 0; - - case DSERR_BUFFERLOST: - continue; - - 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; } @@ -938,64 +854,22 @@ 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 -#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 -#include -#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 @@ -8,6 +8,19 @@ #include "audio_int.h" #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; @@ -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 -#include - -#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 < +int main(void) { return 0; } +EOF + compile_object +} + write_c_skeleton() { cat > $TMPC <" || { 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"