From 0bac111167e33838fa869cacd16f92e5899252b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:44 +0200 Subject: [PATCH 01/20] audio: remove esd backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ESD is no longer developed and replaced by PulseAudio. Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/Makefile.objs | 1 - audio/audio_int.h | 1 - audio/esdaudio.c | 557 -------------------------------------------- configure | 18 +- 4 files changed, 6 insertions(+), 571 deletions(-) delete mode 100644 audio/esdaudio.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index 26a0ac9507..5573ac18e8 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -6,7 +6,6 @@ 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 diff --git a/audio/audio_int.h b/audio/audio_int.h index fd019a0fc3..9dd6b7f75e 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -210,7 +210,6 @@ 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; 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/configure b/configure index 409edf94fb..ee67ed17f1 100755 --- a/configure +++ b/configure @@ -575,13 +575,13 @@ MINGW32*) GNU/kFreeBSD) bsd="yes" audio_drv_list="oss" - audio_possible_drivers="oss sdl esd pa" + audio_possible_drivers="oss sdl pa" ;; FreeBSD) bsd="yes" make="${MAKE-gmake}" audio_drv_list="oss" - audio_possible_drivers="oss sdl esd pa" + audio_possible_drivers="oss sdl pa" # needed for kinfo_getvmmap(3) in libutil.h LIBS="-lutil $LIBS" netmap="" # enable netmap autodetect @@ -591,14 +591,14 @@ DragonFly) bsd="yes" make="${MAKE-gmake}" audio_drv_list="oss" - audio_possible_drivers="oss sdl esd pa" + audio_possible_drivers="oss sdl pa" HOST_VARIANT_DIR="dragonfly" ;; NetBSD) bsd="yes" make="${MAKE-gmake}" audio_drv_list="oss" - audio_possible_drivers="oss sdl esd" + audio_possible_drivers="oss sdl" oss_lib="-lossaudio" HOST_VARIANT_DIR="netbsd" ;; @@ -606,7 +606,7 @@ OpenBSD) bsd="yes" make="${MAKE-gmake}" audio_drv_list="sdl" - audio_possible_drivers="sdl esd" + audio_possible_drivers="sdl" HOST_VARIANT_DIR="openbsd" ;; Darwin) @@ -674,7 +674,7 @@ Haiku) ;; *) audio_drv_list="oss" - audio_possible_drivers="oss alsa sdl esd pa" + audio_possible_drivers="oss alsa sdl pa" linux="yes" linux_user="yes" kvm="yes" @@ -2630,12 +2630,6 @@ for drv in $audio_drv_list; do libs_softmmu="$fmod_lib $libs_softmmu" ;; - esd) - audio_drv_probe $drv esd.h -lesd 'return esd_play_stream(0, 0, "", 0);' - libs_softmmu="-lesd $libs_softmmu" - audio_pt_int="yes" - ;; - pa) audio_drv_probe $drv pulse/mainloop.h "-lpulse" \ "pa_mainloop *m = 0; pa_mainloop_free (m); return 0;" From 14382605da6bda74516f275695bd3345bc54c464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:45 +0200 Subject: [PATCH 02/20] audio: remove fmod backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/Makefile.objs | 2 - audio/audio_int.h | 1 - audio/fmodaudio.c | 685 -------------------------------------------- configure | 27 +- 4 files changed, 2 insertions(+), 713 deletions(-) delete mode 100644 audio/fmodaudio.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index 5573ac18e8..b4c0608929 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -5,12 +5,10 @@ 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_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/audio_int.h b/audio/audio_int.h index 9dd6b7f75e..7445602764 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -206,7 +206,6 @@ 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; 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/configure b/configure index ee67ed17f1..58d212adb9 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" @@ -569,7 +567,7 @@ CYGWIN*) ;; MINGW32*) mingw32="yes" - audio_possible_drivers="winwave dsound sdl fmod" + audio_possible_drivers="winwave dsound sdl" audio_drv_list="winwave" ;; GNU/kFreeBSD) @@ -619,7 +617,7 @@ Darwin) fi cocoa="yes" audio_drv_list="coreaudio" - audio_possible_drivers="coreaudio sdl fmod" + audio_possible_drivers="coreaudio sdl" LDFLAGS="-framework CoreFoundation -framework IOKit $LDFLAGS" libs_softmmu="-F/System/Library/Frameworks -framework Cocoa -framework IOKit $libs_softmmu" # Disable attempts to use ObjectiveC features in os/object.h since they @@ -680,9 +678,6 @@ Haiku) kvm="yes" vhost_net="yes" vhost_scsi="yes" - if [ "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "x32" ] ; then - audio_possible_drivers="$audio_possible_drivers fmod" - fi QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES" ;; esac @@ -847,10 +842,6 @@ for opt do ;; --enable-vnc) vnc="yes" ;; - --fmod-lib=*) fmod_lib="$optarg" - ;; - --fmod-inc=*) fmod_inc="$optarg" - ;; --oss-lib=*) oss_lib="$optarg" ;; --audio-drv-list=*) audio_drv_list="$optarg" @@ -1349,8 +1340,6 @@ Advanced options (experts only): --disable-guest-base disable GUEST_BASE support --enable-pie build Position Independent Executables --disable-pie do not build Position Independent Executables - --fmod-lib path to FMOD library - --fmod-inc path to FMOD includes --oss-lib path to OSS library --cpu=CPU Build for host CPU [$cpu] --disable-uuid disable uuid support @@ -2621,15 +2610,6 @@ for drv in $audio_drv_list; do libs_softmmu="-lasound $libs_softmmu" ;; - fmod) - if test -z $fmod_lib || test -z $fmod_inc; then - error_exit "You must specify path to FMOD library and headers" \ - "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so" - fi - audio_drv_probe $drv fmod.h $fmod_lib "return FSOUND_GetVersion();" "-I $fmod_inc" - libs_softmmu="$fmod_lib $libs_softmmu" - ;; - pa) audio_drv_probe $drv pulse/mainloop.h "-lpulse" \ "pa_mainloop *m = 0; pa_mainloop_free (m); return 0;" @@ -4623,9 +4603,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 From 3cec7cc22f95ce31565e8e2c03b06a2f7ae8bc6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:46 +0200 Subject: [PATCH 03/20] audio: remove winwave audio driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DirectSound should be a superior choice on Windows. Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/Makefile.objs | 1 - audio/audio_int.h | 1 - audio/winwaveaudio.c | 717 ------------------------------------------- configure | 13 +- 4 files changed, 4 insertions(+), 728 deletions(-) delete mode 100644 audio/winwaveaudio.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index b4c0608929..481d1aa30e 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -6,7 +6,6 @@ common-obj-$(CONFIG_COREAUDIO) += coreaudio.o common-obj-$(CONFIG_ALSA) += alsaaudio.o common-obj-$(CONFIG_DSOUND) += dsoundaudio.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 diff --git a/audio/audio_int.h b/audio/audio_int.h index 7445602764..0eba44f5a0 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -211,7 +211,6 @@ extern struct audio_driver coreaudio_audio_driver; extern struct audio_driver dsound_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/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 58d212adb9..ccf8dc7788 100755 --- a/configure +++ b/configure @@ -562,13 +562,13 @@ case $targetos in CYGWIN*) mingw32="yes" QEMU_CFLAGS="-mno-cygwin $QEMU_CFLAGS" - audio_possible_drivers="winwave sdl" - audio_drv_list="winwave" + audio_possible_drivers="sdl" + audio_drv_list="sdl" ;; MINGW32*) mingw32="yes" - audio_possible_drivers="winwave dsound sdl" - audio_drv_list="winwave" + audio_possible_drivers="dsound sdl" + audio_drv_list="dsound" ;; GNU/kFreeBSD) bsd="yes" @@ -2634,11 +2634,6 @@ for drv in $audio_drv_list; do # XXX: Probes for CoreAudio, DirectSound, SDL(?) ;; - winwave) - libs_softmmu="-lwinmm $libs_softmmu" - audio_win_int="yes" - ;; - *) echo "$audio_possible_drivers" | grep -q "\<$drv\>" || { error_exit "Unknown driver '$drv' selected" \ From 307119e7d948bcdb5918fd762153deda471e695b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Jun 2015 09:07:35 +0200 Subject: [PATCH 04/20] only enable dsound in case the header file is present Signed-off-by: Gerd Hoffmann --- configure | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/configure b/configure index ccf8dc7788..222694f34d 100755 --- a/configure +++ b/configure @@ -435,6 +435,14 @@ EOF compile_object } +check_include() { +cat > $TMPC < +int main(void) { return 0; } +EOF + compile_object +} + write_c_skeleton() { cat > $TMPC < Date: Wed, 3 Jun 2015 23:03:47 +0200 Subject: [PATCH 05/20] audio: expose drv_opaque to init_out and init_in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the opaque pointer returned by audio_driver's init is only exposed to the driver's fini, but not to audio_pcm_ops. This way if someone wants to share a variable with the driver and the pcm, he must use global variables. This patch fixes it by adding a third parameter to audio_pcm_op's init_out and init_in. Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/alsaaudio.c | 5 +++-- audio/audio_int.h | 4 ++-- audio/audio_template.h | 2 +- audio/coreaudio.c | 3 ++- audio/dsound_template.h | 6 ++++-- audio/noaudio.c | 4 ++-- audio/ossaudio.c | 5 +++-- audio/paaudio.c | 5 +++-- audio/sdlaudio.c | 3 ++- audio/spiceaudio.c | 5 +++-- audio/wavaudio.c | 5 ++--- 11 files changed, 27 insertions(+), 20 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index ed7655de86..5a5bb1445d 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -807,7 +807,8 @@ 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; @@ -916,7 +917,7 @@ 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; diff --git a/audio/audio_int.h b/audio/audio_int.h index 0eba44f5a0..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); diff --git a/audio/audio_template.h b/audio/audio_template.h index 584e536fac..f716d97c7e 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; } diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 5964c62eaf..20346bce6e 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -287,7 +287,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; diff --git a/audio/dsound_template.h b/audio/dsound_template.h index 8b37d16a8c..98276fb019 100644 --- a/audio/dsound_template.h +++ b/audio/dsound_template.h @@ -174,9 +174,11 @@ 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; 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..27c6bc625e 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -510,7 +510,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; @@ -677,7 +678,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; diff --git a/audio/paaudio.c b/audio/paaudio.c index 90ff24500b..bdf6cd52e1 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -534,7 +534,8 @@ 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; @@ -601,7 +602,7 @@ 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; diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index d24daa5ead..b95a7e0ab4 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -332,7 +332,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; 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..09083da2cf 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -105,7 +105,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; @@ -117,8 +118,6 @@ static int wav_init_out (HWVoiceOut *hw, struct audsettings *as) }; struct audsettings wav_as = conf.settings; - (void) as; - stereo = wav_as.nchannels == 2; switch (wav_as.fmt) { case AUD_FMT_S8: From 9a644c4b4dfc7ebe7994bfa568cbeaa1847ca5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:49 +0200 Subject: [PATCH 06/20] paaudio: do not use global variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/paaudio.c | 98 ++++++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index bdf6cd52e1..35e8887112 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,21 +44,9 @@ 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 GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...) { va_list ap; @@ -106,7 +108,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 +162,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 +224,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 +316,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 +432,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 +451,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 +469,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; @@ -538,10 +538,11 @@ 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; @@ -559,11 +560,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 */ @@ -575,7 +575,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) { @@ -605,9 +605,10 @@ static int qpa_init_out(HWVoiceOut *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; @@ -616,11 +617,10 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) 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 */ @@ -632,7 +632,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) } 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) { @@ -704,7 +704,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+ */ @@ -756,7 +756,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); @@ -806,23 +806,29 @@ 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 = 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; @@ -855,12 +861,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"); + g_free(g); return NULL; } @@ -875,39 +882,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 */ } From 765b37da3f2824afd45b38c038af44da42b956f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:48 +0200 Subject: [PATCH 07/20] alsaaudio: do not use global variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/alsaaudio.c | 150 +++++++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 68 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 5a5bb1445d..4bcf58f3e3 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -33,9 +33,29 @@ #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; + int verbose; +} 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; @@ -184,6 +180,7 @@ static void alsa_poll_handler (void *opaque) snd_pcm_state_t state; struct pollhlp *hlp = opaque; unsigned short revents; + ALSAConf *conf = hlp->conf; count = poll (hlp->pfds, hlp->count, 0); if (count < 0) { @@ -205,7 +202,7 @@ static void alsa_poll_handler (void *opaque) } if (!(revents & hlp->mask)) { - if (conf.verbose) { + if (conf->verbose) { dolog ("revents = %d\n", revents); } return; @@ -242,6 +239,7 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask) { int i, count, err; struct pollfd *pfds; + ALSAConf *conf = hlp->conf; count = snd_pcm_poll_descriptors_count (handle); if (count <= 0) { @@ -269,12 +267,12 @@ 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) { + if (conf->verbose) { dolog ("POLLOUT %d %d\n", i, pfds[i].fd); } qemu_set_fd_handler (pfds[i].fd, NULL, alsa_poll_handler, hlp); } - if (conf.verbose) { + if (conf->verbose) { dolog ("Set handler events=%#x index=%d fd=%d err=%d\n", pfds[i].events, i, pfds[i].fd, err); } @@ -464,14 +462,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 +509,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 && conf->verbose) { alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt); } @@ -642,7 +641,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 +663,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,7 +673,7 @@ static int alsa_open (int in, struct alsa_params_req *req, *handlep = handle; - if (conf.verbose && + if (conf->verbose && (obtfmt != req->fmt || obt->nchannels != req->nchannels || obt->freq != req->freq)) { @@ -717,6 +716,7 @@ static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) static void alsa_write_pending (ALSAVoiceOut *alsa) { HWVoiceOut *hw = &alsa->hw; + ALSAConf *conf = alsa->pollhlp.conf; while (alsa->pending) { int left_till_end_samples = hw->samples - alsa->wpos; @@ -731,7 +731,7 @@ static void alsa_write_pending (ALSAVoiceOut *alsa) if (written <= 0) { switch (written) { case 0: - if (conf.verbose) { + if (conf->verbose) { dolog ("Failed to write %d frames (wrote zero)\n", len); } return; @@ -742,7 +742,7 @@ static void alsa_write_pending (ALSAVoiceOut *alsa) len); return; } - if (conf.verbose) { + if (conf->verbose) { dolog ("Recovering from playback xrun\n"); } continue; @@ -755,7 +755,7 @@ static void alsa_write_pending (ALSAVoiceOut *alsa) len); return; } - if (conf.verbose) { + if (conf->verbose) { dolog ("Resuming suspended output stream\n"); } continue; @@ -815,18 +815,19 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, 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; } @@ -847,6 +848,7 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, } alsa->handle = handle; + alsa->pollhlp.conf = conf; return 0; } @@ -924,18 +926,19 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) 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; } @@ -956,6 +959,7 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) } alsa->handle = handle; + alsa->pollhlp.conf = conf; return 0; } @@ -986,6 +990,7 @@ static int alsa_run_in (HWVoiceIn *hw) }; snd_pcm_sframes_t avail; snd_pcm_uframes_t read_samples = 0; + ALSAConf *conf = alsa->pollhlp.conf; if (!dead) { return 0; @@ -1011,12 +1016,12 @@ static int alsa_run_in (HWVoiceIn *hw) dolog ("Failed to resume suspended input stream\n"); return 0; } - if (conf.verbose) { + if (conf->verbose) { dolog ("Resuming suspended input stream\n"); } break; default: - if (conf.verbose) { + if (conf->verbose) { dolog ("No frames available and ALSA state is %d\n", state); } return 0; @@ -1053,7 +1058,7 @@ static int alsa_run_in (HWVoiceIn *hw) if (nread <= 0) { switch (nread) { case 0: - if (conf.verbose) { + if (conf->verbose) { dolog ("Failed to read %ld frames (read zero)\n", len); } goto exit; @@ -1063,7 +1068,7 @@ static int alsa_run_in (HWVoiceIn *hw) alsa_logerr (nread, "Failed to read %ld frames\n", len); goto exit; } - if (conf.verbose) { + if (conf->verbose) { dolog ("Recovering from capture xrun\n"); } continue; @@ -1137,80 +1142,89 @@ 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, + .valp = &glob_conf.verbose, .descr = "Behave in a more verbose way" }, { /* End of list */ } From 4045a85ad1aadb1a56038ed3358e2093ba88f91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:50 +0200 Subject: [PATCH 08/20] ossaudio: do not use global variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/ossaudio.c | 110 ++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 27c6bc625e..bdc4b768e7 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -38,6 +38,17 @@ #define USE_DSP_POLICY #endif +typedef struct OSSConf { + int try_mmap; + int nfrags; + int fragsize; + const char *devpath_out; + const char *devpath_in; + int debug; + 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,20 @@ 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) { + if (conf->debug) { dolog ("OSS version = %#x\n", 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; @@ -434,6 +427,7 @@ static int oss_run_out (HWVoiceOut *hw, int live) struct audio_buf_info abinfo; struct count_info cntinfo; int bufsize; + OSSConf *conf = oss->conf; bufsize = hw->samples << hw->info.shift; @@ -458,7 +452,7 @@ static int oss_run_out (HWVoiceOut *hw, int live) } if (abinfo.bytes > bufsize) { - if (conf.debug) { + 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); @@ -467,7 +461,7 @@ static int oss_run_out (HWVoiceOut *hw, int live) } if (abinfo.bytes < 0) { - if (conf.debug) { + if (conf->debug) { dolog ("warning: Invalid available size, size=%d bufsize=%d\n", abinfo.bytes, bufsize); } @@ -520,16 +514,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; } @@ -556,7 +551,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, @@ -616,6 +611,7 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, } oss->fd = fd; + oss->conf = conf; return 0; } @@ -687,15 +683,16 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) 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; } @@ -729,6 +726,7 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) } oss->fd = fd; + oss->conf = conf; return 0; } @@ -848,69 +846,83 @@ 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", + .debug = 0, + .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, + .valp = &glob_conf.debug, .descr = "Turn on some debugging messages" }, { /* End of list */ } From f2dcc6cec285938967446d412b0477e02e26f3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:51 +0200 Subject: [PATCH 09/20] wavaudio: do not use global variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/wavaudio.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 09083da2cf..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) { @@ -116,7 +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; + WAVConf *conf = drv_opaque; + struct audsettings wav_as = conf->settings; stereo = wav_as.nchannels == 2; switch (wav_as.fmt) { @@ -154,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; @@ -225,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 */ } From 49dd6d0d33e1a59b4055713079e64062bc5092b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:53 +0200 Subject: [PATCH 10/20] paaudio: fix possible resource leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qpa_audio_init did not clean up resources properly if the initialization failed. This hopefully fixes it. Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/paaudio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index 35e8887112..fea607166f 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -47,6 +47,8 @@ typedef struct { paaudio *g; } PAVoiceIn; +static void qpa_audio_fini(void *opaque); + static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...) { va_list ap; @@ -814,6 +816,8 @@ static void *qpa_audio_init (void) { 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) { @@ -867,7 +871,7 @@ unlock_and_fail: pa_threaded_mainloop_unlock (g->mainloop); fail: AUD_log (AUDIO_CAP, "Failed to initialize PA context"); - g_free(g); + qpa_audio_fini(g); return NULL; } From 191e1f0acd32360b917fa54a52389b97d9b52b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:52 +0200 Subject: [PATCH 11/20] dsoundaudio: do not use global variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/dsound_template.h | 18 ++++--- audio/dsoundaudio.c | 106 ++++++++++++++++++++++++---------------- 2 files changed, 74 insertions(+), 50 deletions(-) diff --git a/audio/dsound_template.h b/audio/dsound_template.h index 98276fb019..85ba8582bb 100644 --- a/audio/dsound_template.h +++ b/audio/dsound_template.h @@ -67,7 +67,8 @@ static int glue (dsound_lock_, TYPE) ( LPVOID *p2p, DWORD *blen1p, DWORD *blen2p, - int entire + int entire, + dsound *s ) { HRESULT hr; @@ -75,13 +76,14 @@ static int glue (dsound_lock_, TYPE) ( LPVOID p1 = NULL, p2 = NULL; DWORD blen1 = 0, blen2 = 0; DWORD flag; + DSoundConf *conf = &s->conf; #ifdef DSBTYPE_IN flag = entire ? DSCBLOCK_ENTIREBUFFER : 0; #else flag = entire ? DSBLOCK_ENTIREBUFFER : 0; #endif - for (i = 0; i < conf.lock_retries; ++i) { + for (i = 0; i < conf->lock_retries; ++i) { hr = glue (IFACE, _Lock) ( buf, pos, @@ -96,7 +98,7 @@ static int glue (dsound_lock_, TYPE) ( if (FAILED (hr)) { #ifndef DSBTYPE_IN if (hr == DSERR_BUFFERLOST) { - if (glue (dsound_restore_, TYPE) (buf)) { + if (glue (dsound_restore_, TYPE) (buf, s)) { dsound_logerr (hr, "Could not lock " NAME "\n"); goto fail; } @@ -110,7 +112,7 @@ static int glue (dsound_lock_, TYPE) ( break; } - if (i == conf.lock_retries) { + if (i == conf->lock_retries) { dolog ("%d attempts to lock " NAME " failed\n", i); goto fail; } @@ -183,9 +185,10 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, { 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; @@ -212,7 +215,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, @@ -221,7 +224,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, @@ -271,6 +274,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..c8b09e21eb 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -41,7 +41,7 @@ /* #define DEBUG_DSOUND */ -static struct { +typedef struct { int lock_retries; int restore_retries; int getstatus_retries; @@ -50,33 +50,22 @@ static struct { 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 +77,7 @@ typedef struct { HWVoiceIn hw; int first_time; LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer; + dsound *s; } DSoundVoiceIn; static void dsound_log_hresult (HRESULT hr) @@ -281,12 +271,12 @@ 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) { + for (i = 0; i < s->conf.restore_retries; ++i) { hr = IDirectSoundBuffer_Restore (dsb); switch (hr) { @@ -311,12 +301,13 @@ 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) { + for (i = 0; i < s->conf.getstatus_retries; ++i) { hr = IDirectSoundBuffer_GetStatus (dsb, statusp); if (FAILED (hr)) { dsound_logerr (hr, "Could not get playback buffer status\n"); @@ -324,7 +315,7 @@ static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp) } if (*statusp & DSERR_BUFFERLOST) { - if (dsound_restore_out (dsb)) { + if (dsound_restore_out (dsb, s)) { return -1; } continue; @@ -376,7 +367,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 +381,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; @@ -435,6 +428,7 @@ static int dsound_open (dsound *s) WAVEFORMATEX wfx; DSBUFFERDESC dsbd; HWND hwnd; + DSoundConf *conf = &s->conf; hwnd = GetForegroundWindow (); hr = IDirectSound_SetCooperativeLevel ( @@ -449,11 +443,11 @@ static int dsound_open (dsound *s) return -1; } - if (!conf.set_primary) { + if (!conf->set_primary) { return 0; } - err = waveformat_from_audio_settings (&wfx, &conf.settings); + err = waveformat_from_audio_settings (&wfx, &conf->settings); if (err) { return -1; } @@ -514,6 +508,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 +517,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 +526,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 +536,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 +573,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 +597,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 +660,8 @@ static int dsound_run_out (HWVoiceOut *hw, int live) len, &p1, &p2, &blen1, &blen2, - 0 + 0, + s ); if (err) { return 0; @@ -766,6 +764,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 +819,8 @@ static int dsound_run_in (HWVoiceIn *hw) &p2, &blen1, &blen2, - 0 + 0, + s ); if (err) { return 0; @@ -843,12 +843,26 @@ static int dsound_run_in (HWVoiceIn *hw) return decr; } +static DSoundConf glob_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 +}; + static void dsound_audio_fini (void *opaque) { HRESULT hr; dsound *s = opaque; if (!s->dsound) { + g_free(s); return; } @@ -859,6 +873,7 @@ static void dsound_audio_fini (void *opaque) s->dsound = NULL; if (!s->dsound_capture) { + g_free(s); return; } @@ -867,17 +882,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 +909,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 +921,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; } @@ -941,61 +961,61 @@ static struct audio_option dsound_options[] = { { .name = "LOCK_RETRIES", .tag = AUD_OPT_INT, - .valp = &conf.lock_retries, + .valp = &glob_conf.lock_retries, .descr = "Number of times to attempt locking the buffer" }, { .name = "RESTOURE_RETRIES", .tag = AUD_OPT_INT, - .valp = &conf.restore_retries, + .valp = &glob_conf.restore_retries, .descr = "Number of times to attempt restoring the buffer" }, { .name = "GETSTATUS_RETRIES", .tag = AUD_OPT_INT, - .valp = &conf.getstatus_retries, + .valp = &glob_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, + .valp = &glob_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, + .valp = &glob_conf.settings.freq, .descr = "Primary buffer frequency" }, { .name = "PRIMARY_CHANNELS", .tag = AUD_OPT_INT, - .valp = &conf.settings.nchannels, + .valp = &glob_conf.settings.nchannels, .descr = "Primary buffer number of channels (1 - mono, 2 - stereo)" }, { .name = "PRIMARY_FMT", .tag = AUD_OPT_FMT, - .valp = &conf.settings.fmt, + .valp = &glob_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 */ } From d1f52a1d704de2252bc48c64ca4d46086cb249a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:54 +0200 Subject: [PATCH 12/20] coreaudio: do not use global variables where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/coreaudio.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 20346bce6e..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) @@ -296,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); @@ -337,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 */ @@ -380,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); @@ -444,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); @@ -487,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) { @@ -500,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 */ } From 81ebb07c56a28aa7ca47c38eb44690025a9dd6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Wed, 3 Jun 2015 23:03:55 +0200 Subject: [PATCH 13/20] sdlaudio: do not allow multiple instances MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since SDL uses a lot of global data, we can't create independent instances of sdl audio backend. Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/sdlaudio.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index b95a7e0ab4..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; @@ -393,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"); @@ -414,6 +419,7 @@ static void *sdl_audio_init (void) return NULL; } + s->driver_created = true; return s; } @@ -424,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[] = { From 65eb1e6b4c1c4f66deff9cdf9bfbdea267c59343 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Jun 2015 12:51:36 +0200 Subject: [PATCH 14/20] MAINTAINERS: remove malc from audio email bounces, with a appearently permanent error: "av1474@comtv.ru mail receiving disabled, rejecting" Signed-off-by: Gerd Hoffmann Reviewed-by: Gonglei --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) 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/ From 06ac27f683c52890a6d174adba8c92354fa1eceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Fri, 12 Jun 2015 14:33:02 +0200 Subject: [PATCH 15/20] audio: remove LOG_TO_MONITOR along with default_mon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting QEMU_AUDIO_LOG_TO_MONITOR=1 can crash qemu (if qemu tries to log to the monitor before it's being initialized), and also nothing else in qemu logs to the monitor. This log to monitor feature was the last thing that used the default_mon variable, so I removed it too (as using it can cause problems). Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/audio.c | 23 +++-------------------- include/monitor/monitor.h | 1 - monitor.c | 4 ---- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 9d018e9ded..cb1cba9236 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -67,7 +67,6 @@ static struct { int64_t ticks; } period; int plive; - int log_to_monitor; int try_poll_in; int try_poll_out; } conf = { @@ -97,7 +96,6 @@ static struct { .period = { .hertz = 100 }, .plive = 0, - .log_to_monitor = 0, .try_poll_in = 1, .try_poll_out = 1, }; @@ -331,20 +329,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, ...) @@ -1654,12 +1643,6 @@ static struct audio_option audio_options[] = { .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/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, From 73ad33ef7ba0d1e7c7f276663f36c4f72b9193a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Fri, 12 Jun 2015 14:33:03 +0200 Subject: [PATCH 16/20] audio: remove plive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was useless even 3 years ago, so it can probably safely go away: https://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg02427.html Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/audio.c | 12 ------------ audio/audio_template.h | 41 ----------------------------------------- 2 files changed, 53 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index cb1cba9236..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,7 +65,6 @@ static struct { int hertz; int64_t ticks; } period; - int plive; int try_poll_in; int try_poll_out; } conf = { @@ -95,7 +93,6 @@ static struct { }, .period = { .hertz = 100 }, - .plive = 0, .try_poll_in = 1, .try_poll_out = 1, }; @@ -1443,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; @@ -1637,12 +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)" - }, { /* End of list */ } }; diff --git a/audio/audio_template.h b/audio/audio_template.h index f716d97c7e..99b27b285e 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -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); From 2762955f723570944966347600b5746e7dd99388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Fri, 12 Jun 2015 14:33:04 +0200 Subject: [PATCH 17/20] dsoundaudio: remove *_retries kludges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to MSDN this may happen when the window is not in the foreground, but the default is 1 since a long time (which means no retries), so it should be ok. I've found no problems during testing it on Windows 7 and wine, so this was probably only the case with some old Windows versions. Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/dsound_template.h | 35 +++++---------------- audio/dsoundaudio.c | 68 ++++++++--------------------------------- 2 files changed, 20 insertions(+), 83 deletions(-) diff --git a/audio/dsound_template.h b/audio/dsound_template.h index 85ba8582bb..b439f33f58 100644 --- a/audio/dsound_template.h +++ b/audio/dsound_template.h @@ -72,48 +72,27 @@ static int glue (dsound_lock_, TYPE) ( ) { HRESULT hr; - int i; LPVOID p1 = NULL, p2 = NULL; DWORD blen1 = 0, blen2 = 0; DWORD flag; - DSoundConf *conf = &s->conf; #ifdef DSBTYPE_IN flag = entire ? DSCBLOCK_ENTIREBUFFER : 0; #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, s)) { - 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; } diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index c8b09e21eb..28b98bf5a1 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -42,9 +42,6 @@ /* #define DEBUG_DSOUND */ typedef struct { - int lock_retries; - int restore_retries; - int getstatus_retries; int set_primary; int bufsize_in; int bufsize_out; @@ -274,26 +271,14 @@ static void print_wave_format (WAVEFORMATEX *wfx) static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb, dsound *s) { HRESULT hr; - int i; - for (i = 0; i < s->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" @@ -305,22 +290,16 @@ static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp, dsound *s) { HRESULT hr; - int i; - for (i = 0; i < s->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, s)) { - return -1; - } - continue; - } - break; + if (*statusp & DSERR_BUFFERLOST) { + dsound_restore_out(dsb, s); + return -1; } return 0; @@ -844,9 +823,6 @@ static int dsound_run_in (HWVoiceIn *hw) } static DSoundConf glob_conf = { - .lock_retries = 1, - .restore_retries = 1, - .getstatus_retries = 1, .set_primary = 0, .bufsize_in = 16384, .bufsize_out = 16384, @@ -958,24 +934,6 @@ static void *dsound_audio_init (void) } static struct audio_option dsound_options[] = { - { - .name = "LOCK_RETRIES", - .tag = AUD_OPT_INT, - .valp = &glob_conf.lock_retries, - .descr = "Number of times to attempt locking the buffer" - }, - { - .name = "RESTOURE_RETRIES", - .tag = AUD_OPT_INT, - .valp = &glob_conf.restore_retries, - .descr = "Number of times to attempt restoring the buffer" - }, - { - .name = "GETSTATUS_RETRIES", - .tag = AUD_OPT_INT, - .valp = &glob_conf.getstatus_retries, - .descr = "Number of times to attempt getting status of the buffer" - }, { .name = "SET_PRIMARY", .tag = AUD_OPT_BOOL, From 6dd35fd81e06d469b6f5280adee0a16ee383db57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Fri, 12 Jun 2015 14:33:05 +0200 Subject: [PATCH 18/20] dsoundaudio: remove primary buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enabling this option just creates a playback buffer with the specified settings, and then ignores it. It's probably some outdated hack to set audio formats on windows. (The first created stream dictates all other streams settings, at least on some Windows versions). Setting DAC_FIXED_SETTINGS should have the same effect as setting (the now removed) primary buffer. Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/dsoundaudio.c | 104 -------------------------------------------- 1 file changed, 104 deletions(-) diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 28b98bf5a1..e9472c105c 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -42,17 +42,14 @@ /* #define DEBUG_DSOUND */ typedef struct { - int set_primary; int bufsize_in; int bufsize_out; - struct audsettings settings; int latency_millis; } DSoundConf; typedef struct { LPDIRECTSOUND dsound; LPDIRECTSOUNDCAPTURE dsound_capture; - LPDIRECTSOUNDBUFFER dsound_primary_buffer; struct audsettings settings; DSoundConf conf; } dsound; @@ -387,27 +384,10 @@ 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; - DSoundConf *conf = &s->conf; hwnd = GetForegroundWindow (); hr = IDirectSound_SetCooperativeLevel ( @@ -422,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, ...) @@ -823,12 +747,8 @@ static int dsound_run_in (HWVoiceIn *hw) } static DSoundConf glob_conf = { - .set_primary = 0, .bufsize_in = 16384, .bufsize_out = 16384, - .settings.freq = 44100, - .settings.nchannels = 2, - .settings.fmt = AUD_FMT_S16, .latency_millis = 10 }; @@ -934,36 +854,12 @@ static void *dsound_audio_init (void) } static struct audio_option dsound_options[] = { - { - .name = "SET_PRIMARY", - .tag = AUD_OPT_BOOL, - .valp = &glob_conf.set_primary, - .descr = "Set the parameters of primary buffer" - }, { .name = "LATENCY_MILLIS", .tag = AUD_OPT_INT, .valp = &glob_conf.latency_millis, .descr = "(undocumented)" }, - { - .name = "PRIMARY_FREQ", - .tag = AUD_OPT_INT, - .valp = &glob_conf.settings.freq, - .descr = "Primary buffer frequency" - }, - { - .name = "PRIMARY_CHANNELS", - .tag = AUD_OPT_INT, - .valp = &glob_conf.settings.nchannels, - .descr = "Primary buffer number of channels (1 - mono, 2 - stereo)" - }, - { - .name = "PRIMARY_FMT", - .tag = AUD_OPT_FMT, - .valp = &glob_conf.settings.fmt, - .descr = "Primary buffer format" - }, { .name = "BUFSIZE_OUT", .tag = AUD_OPT_INT, From fbb7ef56d55723a4996c288b50a16e6283eea13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Fri, 12 Jun 2015 14:33:06 +0200 Subject: [PATCH 19/20] alsaaudio: use trace events instead of verbose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/alsaaudio.c | 60 +++++++++++------------------------------------ trace-events | 12 ++++++++++ 2 files changed, 26 insertions(+), 46 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 4bcf58f3e3..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" @@ -49,7 +50,6 @@ typedef struct ALSAConf { int buffer_size_out_overridden; int period_size_out_overridden; - int verbose; } ALSAConf; struct pollhlp { @@ -180,7 +180,6 @@ static void alsa_poll_handler (void *opaque) snd_pcm_state_t state; struct pollhlp *hlp = opaque; unsigned short revents; - ALSAConf *conf = hlp->conf; count = poll (hlp->pfds, hlp->count, 0); if (count < 0) { @@ -202,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; } @@ -239,7 +236,6 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask) { int i, count, err; struct pollfd *pfds; - ALSAConf *conf = hlp->conf; count = snd_pcm_poll_descriptors_count (handle); if (count <= 0) { @@ -267,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; @@ -509,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); } @@ -673,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); } @@ -716,7 +706,6 @@ static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) static void alsa_write_pending (ALSAVoiceOut *alsa) { HWVoiceOut *hw = &alsa->hw; - ALSAConf *conf = alsa->pollhlp.conf; while (alsa->pending) { int left_till_end_samples = hw->samples - alsa->wpos; @@ -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: @@ -990,7 +973,6 @@ static int alsa_run_in (HWVoiceIn *hw) }; snd_pcm_sframes_t avail; snd_pcm_uframes_t read_samples = 0; - ALSAConf *conf = alsa->pollhlp.conf; if (!dead) { return 0; @@ -1016,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; } } @@ -1058,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: @@ -1068,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: @@ -1221,12 +1195,6 @@ static struct audio_option alsa_options[] = { .valp = &glob_conf.pcm_name_in, .descr = "ADC device name" }, - { - .name = "VERBOSE", - .tag = AUD_OPT_BOOL, - .valp = &glob_conf.verbose, - .descr = "Behave in a more verbose way" - }, { /* End of list */ } }; diff --git a/trace-events b/trace-events index 6060d36773..409a64a249 100644 --- a/trace-events +++ b/trace-events @@ -1632,3 +1632,15 @@ 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" From d95d7d802c33f6277c9fb967c14ae0cc99aeb072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= Date: Fri, 12 Jun 2015 14:33:07 +0200 Subject: [PATCH 20/20] ossaudio: use trace events instead of debug config flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kővágó, Zoltán Signed-off-by: Gerd Hoffmann --- audio/ossaudio.c | 25 ++++--------------------- trace-events | 4 ++++ 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index bdc4b768e7..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" @@ -44,7 +45,6 @@ typedef struct OSSConf { int fragsize; const char *devpath_out; const char *devpath_in; - int debug; int exclusive; int policy; } OSSConf; @@ -314,9 +314,7 @@ static int oss_open (int in, struct oss_params *req, 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; @@ -427,7 +425,6 @@ static int oss_run_out (HWVoiceOut *hw, int live) struct audio_buf_info abinfo; struct count_info cntinfo; int bufsize; - OSSConf *conf = oss->conf; bufsize = hw->samples << hw->info.shift; @@ -452,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; } @@ -852,7 +842,6 @@ static OSSConf glob_conf = { .fragsize = 4096, .devpath_out = "/dev/dsp", .devpath_in = "/dev/dsp", - .debug = 0, .exclusive = 0, .policy = 5 }; @@ -919,12 +908,6 @@ static struct audio_option oss_options[] = { .descr = "Set the timing policy of the device, -1 to use fragment mode", }, #endif - { - .name = "DEBUG", - .tag = AUD_OPT_BOOL, - .valp = &glob_conf.debug, - .descr = "Turn on some debugging messages" - }, { /* End of list */ } }; diff --git a/trace-events b/trace-events index 409a64a249..52b7efa9a4 100644 --- a/trace-events +++ b/trace-events @@ -1644,3 +1644,7 @@ 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"