[Qemu-devel] gsoc idea
hi, i'm thinking about doing a gsoc this year, and i'm interested if you have any opinions on my idea. (i hope i'm not late for this...) currently the audio system in qemu is limited to 2 channels (stereo) sound. also it mixes all sound (if there's more than one sound card) into a single stream, you can't send them to different physical sound cards for example. if you need something like that, you'll have to either pass-through a sound card (but then you can't use it from the host), or use pulseaudio/jack/etc to send the audio over the network (which is problematic in case of a windows guest) imho the audio subsystem should be rewritten to support any number of audio channels. also, the current global mix everything together into a single output method (along with it's environment variable based configuration, since it only allows global options, not per-device) should be replaced, with a system similar to how network or drives works (i.e. each virtual sound card would be connected to an audio device, with their own options) is it a viable idea, or i should scrap it altogether?
[Qemu-devel] Removing old/unused audio backends
Hi, I'll be doing doing gsoc this year, where I'll rework the audio backend of qemu to allow multiple backend instances and multichannel audio. This will of course require modifications of the existing audio drivers in qemu, so it's probably a good idea to remove drivers that nobody use anymore (and probably bug rotten anyway). Here are the drivers that could go in my opinion: esd: no longer maintained, last release in 2008, replaced by PulseAudio fmod: not sure about this one, but apparently it's some no longer developed library that's also proprietary. sdl: is broken (http://lists.nongnu.org/archive/html/qemu-devel/2015-05/msg02198.html), and we have native drivers for almost all platforms winwave: DirectSound should be a superior choice on windows (even though it's also deprecated) alsa needed on Linux, oss on BSDs, coreaudio on Mac, dsound on Windows; spice and pa are also needed. wav is probably useful for debugging. Do you guys have any objections about removing the above mentioned audio drivers in the near future? Thanks, Zoltan
Re: [Qemu-devel] [PATCH v2 00/12] Audio backend cleanup
2015-06-03 21:08 keltezéssel, Peter Maydell írta: On 3 June 2015 at 12:44, Peter Maydell peter.mayd...@linaro.org wrote: On 3 June 2015 at 12:37, Gerd Hoffmann kra...@redhat.com wrote: Any takers to verify coreaudio changes? Alex? Peter? I can have a go but it may take me a while to get to. ...if you have a simple working test image that produces sound that would help, so I'm not trying to mess around configuring audio in the guest. Something which isn't full-fat modern OS config would be good, ie something which will run OK in TCG emulation. I've used day24 from the Qemu advent calendar for some tests, it's pretty minimal. http://www.qemu-advent-calendar.org/ Thanks, Zoltan
[Qemu-devel] [PATCH v3 04/12] audio: expose drv_opaque to init_out and init_in
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 dirty.ice...@gmail.com --- 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 74ead97..87e71c6 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -819,7 +819,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; @@ -928,7 +929,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 0eba44f..566df5e 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 584e536..f716d97 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 5964c62..20346bc 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 8b37d16..98276fb 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 cb38662..50db1f3 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 4db2ca6..069ff60 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -510,7 +510,8 @@ static void oss_fini_out
[Qemu-devel] [PATCH v3 06/12] paaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/paaudio.c | 98 ++--- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index bdf6cd5..35e8887 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -9,6 +9,19 @@ #include audio_pt_int.h typedef struct { +int samples; +char *server; +char *sink; +char *source; +} PAConf; + +typedef struct { +PAConf conf; +pa_threaded_mainloop *mainloop; +pa_context *context; +} paaudio; + +typedef struct { HWVoiceOut hw; int done; int live; @@ -17,6 +30,7 @@ typedef struct { pa_stream *stream; void *pcm_buf; struct audio_pt pt; +paaudio *g; } PAVoiceOut; typedef struct { @@ -30,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
[Qemu-devel] [PATCH v3 00/12] Audio backend cleanup
This series of patch removes the following audio backends: esd, fmod, winwave. It also cleans up the remaining drivers to do not use global variables where possible. This is a preparation for my GSoC project where I will enable multiple simultaneous audio backends. Please also test the coreaudio backend, as I do not have a Mac to test it. Patches are also available at https://github.com/DirtYiCE/qemu.git in tag audio-cleanup-v3 to simplify testing. Changes since v1: * sdl no longer removed * fixed style issues in `audio: expose drv_opaque to init_out and init_in' Changes since v2: * fixed typo in coreaudio Please review. Kővágó, Zoltán (12): audio: remove esd backend audio: remove fmod backend audio: remove winwave audio driver audio: expose drv_opaque to init_out and init_in alsaaudio: do not use global variables paaudio: do not use global variables ossaudio: do not use global variables wavaudio: do not use global variables dsoundaudio: do not use global variables paaudio: fix possible resource leak coreaudio: do not use global variables where possible sdlaudio: do not allow multiple instances audio/Makefile.objs | 4 - audio/alsaaudio.c | 165 ++- audio/audio_int.h | 7 +- audio/audio_template.h | 2 +- audio/coreaudio.c | 46 ++-- audio/dsound_template.h | 24 +- audio/dsoundaudio.c | 106 --- audio/esdaudio.c| 557 - audio/fmodaudio.c | 685 - audio/noaudio.c | 4 +- audio/ossaudio.c| 115 audio/paaudio.c | 105 +++ audio/sdlaudio.c| 10 +- audio/spiceaudio.c | 5 +- audio/wavaudio.c| 42 +-- audio/winwaveaudio.c| 717 configure | 56 +--- 17 files changed, 367 insertions(+), 2283 deletions(-) delete mode 100644 audio/esdaudio.c delete mode 100644 audio/fmodaudio.c delete mode 100644 audio/winwaveaudio.c -- 2.4.2
[Qemu-devel] [PATCH v3 12/12] sdlaudio: do not allow multiple instances
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 dirty.ice...@gmail.com --- audio/sdlaudio.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index b95a7e0..1140f2e 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[] = { -- 2.4.2
[Qemu-devel] [PATCH v3 02/12] audio: remove fmod backend
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 5573ac1..b4c0608 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 9dd6b7f..7445602 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 fabf84d..000 --- a/audio/fmodaudio.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * QEMU FMOD audio driver - * - * Copyright (c) 2004-2005 Vassili Karpov (malc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the Software), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include fmod.h -#include fmod_errors.h -#include qemu-common.h -#include audio.h - -#define AUDIO_CAP fmod -#include audio_int.h - -typedef struct FMODVoiceOut { -HWVoiceOut hw; -unsigned int old_pos; -FSOUND_SAMPLE *fmod_sample; -int channel; -} FMODVoiceOut; - -typedef struct FMODVoiceIn { -HWVoiceIn hw; -FSOUND_SAMPLE *fmod_sample; -} FMODVoiceIn; - -static struct { -const char *drvname; -int nb_samples; -int freq; -int nb_channels; -int bufsize; -int broken_adc; -} conf = { -.nb_samples = 2048 * 2, -.freq= 44100, -.nb_channels = 2, -}; - -static void GCC_FMT_ATTR (1, 2) fmod_logerr (const char *fmt, ...) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, - FMOD_ErrorString (FSOUND_GetError ())); -} - -static void GCC_FMT_ATTR (2, 3) fmod_logerr2 ( -const char *typ, -const char *fmt, -... -) -{ -va_list ap; - -AUD_log (AUDIO_CAP, Could not initialize %s\n, typ); - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, - FMOD_ErrorString (FSOUND_GetError ())); -} - -static int fmod_write (SWVoiceOut *sw, void *buf, int len) -{ -return audio_pcm_sw_write (sw, buf, len); -} - -static void fmod_clear_sample (FMODVoiceOut *fmd) -{ -HWVoiceOut *hw = fmd-hw; -int status; -void *p1 = 0, *p2 = 0; -unsigned int len1 = 0, len2 = 0; - -status = FSOUND_Sample_Lock ( -fmd-fmod_sample, -0, -hw-samples hw-info.shift, -p1, -p2, -len1, -len2 -); - -if (!status) { -fmod_logerr (Failed to lock sample\n); -return; -} - -if ((len1 hw-info.align) || (len2 hw-info.align)) { -dolog (Lock returned misaligned length %d, %d, alignment %d\n, - len1, len2, hw-info.align + 1); -goto fail; -} - -if ((len1 + len2) - (hw-samples hw-info.shift)) { -dolog (Lock returned
[Qemu-devel] [PATCH v3 07/12] ossaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/ossaudio.c | 110 ++- 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 069ff60..d247969 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 = 0x04) { -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 av1...@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
[Qemu-devel] [PATCH v3 10/12] paaudio: fix possible resource leak
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 dirty.ice...@gmail.com --- audio/paaudio.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index 35e8887..fea6071 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; } -- 2.4.2
Re: [Qemu-devel] [RFC PATCH] qapi for audio backends
2015-06-03 21:17 keltezéssel, Eric Blake írta: On 06/03/2015 10:48 AM, Kővágó, Zoltán wrote: This is a proposal to add structures into qapi-schema.json to replace the existing configuration structures used by audio backends currently. I'm going to use it to implement a new way to specify audio backend options (an -audiodev command line option, instead of environment variables. This will also allow us to use multiple audio backends in one qemu instance), so the structure used here will be the basis of the command line syntax. This is currently more or less a direct translation of the current audio backend options. I've changed some names, trying to accomplish a more consistent naming scheme. I wouldn't be surprised if there were options that doesn't work if you set their value to anything other than the default (for example, log to monitor can crash qemu, QEMU_DSOUND_RESTOURE_RETRIES has a typo, so probably nobody used it, etc). I've also tried to reduce copy-paste, when the same set of options can be given to output and input (QEMU_*_DAC_* and QEMU_*_ADC_* options), also using in and out instead of ADC and DAC, as in the world of SPDIF and HDMI it's completely possible that your computer has nothing to do with analog converters. Plus a non technician user probably has no idea what ADC and DAC stands for. Any comment is appreciated. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- qapi-schema.json | 330 +++ 1 file changed, 330 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index 0662a9b..ff67d5a 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3769,3 +3769,333 @@ # Since: 2.1 ## { 'command': 'rtc-reset-reinjection' } + +## +# @AudiodevNoneOptions +# +# The dummy audio backend has no options. +# +# Since: XXX It's okay to tentatively put 2.4 here, if you are aiming for 2.4. If you think it will be a big enough project to miss the current release window, put 2.5. +## +{ 'struct': 'AudiodevNoneOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use. +# +# @period_size_usec: #optional the period size in microseconds. Must not be +#specified with @period_size_frames. +# +# @period_size_frames: #optional the period size in frames. Must not be +# specified with @period_size_usec. +# +# @buffer_size_usec: #optional the buffer size in microseconds. Must not be +#specified with @buffer_size_frames. +# +# @buffer_size_frames: #optional the buffer size in frames. Must not be +# specified with @buffer_size_usec. Can we name these with s/_/-/? We've documented that QMP prefers dash unless there is compelling reason or consistency to worry about, and I don't see the compelling reason here. There's no particular reason other than when I looked through qapi-schema.json I've mostly seen underscores. Will fix this. +# +# Since: XXX +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data': { +'*dev':'str', +'*period_size_usec': 'int', +'*period_size_frames': 'int', +'*buffer_size_usec': 'int', +'*buffer_size_frames': 'int' } } + +## +# @AudiodevAlsaOptions +# +# Options of the alsa audio backend. +# +# @in: #optional options of the capture stream. +# +# @out: #optional options of the playback stream. +# +# @threshold: #optional Document this. This (and some other option) currently only has the documentation (undocumented), but I will try to figure out what they do... +# +# @verbose: #optional behave in a more verbose way +# +# Since: XXX +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { +'*in': 'AudiodevAlsaPerDirectionOptions', +'*out': 'AudiodevAlsaPerDirectionOptions', +'*threshold': 'int', +'*verbose': 'bool' } } + +## +# @AudiodevCoreaudioOptions +# +# Options of the coreaudio backend. +# +# @buffer_size: #optional size of the buffer in frames +# +# @buffer_count: #optional number of buffers Again, dashes would be nicer, if there is no compelling reason otherwise (I'll quit repeating it). +# +# Since: XXX (and I'll quit pointing out XXX in Since lines) +## +{ 'struct': 'AudiodevCoreaudioOptions', + 'data': { +'*buffer_size': 'int', +'*buffer_count': 'int' } } + +## +# @AudiodevDsoundPerDirectionOptions +# +# Options of the dsound backend that are used for both playback and recording. +# +# @bufsize: #optional Document this +# +# Since: XXX +## +{ 'struct': 'AudiodevDsoundPerDirectionOptions', + 'data' : { +'*bufsize': 'int' } } + +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @in: #optional options of the capture stream. +# +# @out: #optional options of the playback stream. +# +# @lock_retries: #optional number of times to attempt locking
[Qemu-devel] [PATCH v3 08/12] wavaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/wavaudio.c | 37 + 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 09083da..c586020 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 */ } -- 2.4.2
Re: [Qemu-devel] [PATCH v2 11/12] coreaudio: do not use global variables where possible
2015-06-03 21:19 keltezéssel, Peter Maydell írta: On 3 June 2015 at 11:49, Kővágó, Zoltán dirty.ice...@gmail.com wrote: Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/coreaudio.c | 43 --- 1 file changed, 24 insertions(+), 19 deletions(-) +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 = glostconf.nbuffers, .descr = Number of buffers }, /Users/pm215/src/qemu/audio/coreaudio.c:529:19: error: use of undeclared identifier 'glostconf'; did you mean 'glob_conf'? .valp = glostconf.nbuffers, ^ glob_conf /Users/pm215/src/qemu/audio/coreaudio.c:500:22: note: 'glob_conf' declared here static CoreaudioConf glob_conf = { ^ 10 warnings and 1 error generated. crap, i should used search replace... does it work with glob_conf or there are other problems? Thanks, Zoltan
[Qemu-devel] [PATCH v3 11/12] coreaudio: do not use global variables where possible
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/coreaudio.c | 43 --- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 20346bc..6dfd63e 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 */ } -- 2.4.2
[Qemu-devel] [PATCH v3 01/12] audio: remove esd backend
ESD is no longer developed and replaced by PulseAudio. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 26a0ac9..5573ac1 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 fd019a0..9dd6b7f 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 eea9cce..000 --- a/audio/esdaudio.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * QEMU ESD audio driver - * - * Copyright (c) 2006 Frederick Reeve (brushed up by malc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the Software), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include esd.h -#include qemu-common.h -#include audio.h - -#define AUDIO_CAP esd -#include audio_int.h -#include audio_pt_int.h - -typedef struct { -HWVoiceOut hw; -int done; -int live; -int decr; -int rpos; -void *pcm_buf; -int fd; -struct audio_pt pt; -} ESDVoiceOut; - -typedef struct { -HWVoiceIn hw; -int done; -int dead; -int incr; -int wpos; -void *pcm_buf; -int fd; -struct audio_pt pt; -} ESDVoiceIn; - -static struct { -int samples; -int divisor; -char *dac_host; -char *adc_host; -} conf = { -.samples = 1024, -.divisor = 2, -}; - -static void GCC_FMT_ATTR (2, 3) qesd_logerr (int err, const char *fmt, ...) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, strerror (err)); -} - -/* playback */ -static void *qesd_thread_out (void *arg) -{ -ESDVoiceOut *esd = arg; -HWVoiceOut *hw = esd-hw; -int threshold; - -threshold = conf.divisor ? hw-samples / conf.divisor : 0; - -if (audio_pt_lock (esd-pt, AUDIO_FUNC)) { -return NULL; -} - -for (;;) { -int decr, to_mix, rpos; - -for (;;) { -if (esd-done) { -goto exit; -} - -if (esd-live threshold) { -break; -} - -if (audio_pt_wait (esd-pt, AUDIO_FUNC)) { -goto exit; -} -} - -decr = to_mix = esd-live; -rpos = hw-rpos; - -if (audio_pt_unlock (esd-pt, AUDIO_FUNC)) { -return NULL; -} - -while (to_mix) { -ssize_t written; -int chunk = audio_MIN (to_mix, hw-samples - rpos); -struct st_sample *src = hw-mix_buf + rpos; - -hw-clip (esd-pcm_buf, src, chunk); - -again: -written = write (esd-fd, esd-pcm_buf, chunk hw-info.shift); -if (written == -1) { -if (errno == EINTR || errno == EAGAIN) { -goto again; -} -qesd_logerr (errno, write failed\n); -return NULL; -} - -if (written != chunk
[Qemu-devel] [PATCH v3 09/12] dsoundaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 98276fb..85ba858 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 e2d89fd..c8b09e2 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
[Qemu-devel] [PATCH v3 03/12] audio: remove winwave audio driver
DirectSound should be a superior choice on Windows. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 b4c0608..481d1aa 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 7445602..0eba44f 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 8dbd145..000 --- a/audio/winwaveaudio.c +++ /dev/null @@ -1,717 +0,0 @@ -/* public domain */ - -#include qemu-common.h -#include sysemu/sysemu.h -#include audio.h - -#define AUDIO_CAP winwave -#include audio_int.h - -#include windows.h -#include mmsystem.h - -#include audio_win_int.h - -static struct { -int dac_headers; -int dac_samples; -int adc_headers; -int adc_samples; -} conf = { -.dac_headers = 4, -.dac_samples = 1024, -.adc_headers = 4, -.adc_samples = 1024 -}; - -typedef struct { -HWVoiceOut hw; -HWAVEOUT hwo; -WAVEHDR *hdrs; -HANDLE event; -void *pcm_buf; -int avail; -int pending; -int curhdr; -int paused; -CRITICAL_SECTION crit_sect; -} WaveVoiceOut; - -typedef struct { -HWVoiceIn hw; -HWAVEIN hwi; -WAVEHDR *hdrs; -HANDLE event; -void *pcm_buf; -int curhdr; -int paused; -int rpos; -int avail; -CRITICAL_SECTION crit_sect; -} WaveVoiceIn; - -static void winwave_log_mmresult (MMRESULT mr) -{ -const char *str = BUG; - -switch (mr) { -case MMSYSERR_NOERROR: -str = Success; -break; - -case MMSYSERR_INVALHANDLE: -str = Specified device handle is invalid; -break; - -case MMSYSERR_BADDEVICEID: -str = Specified device id is out of range; -break; - -case MMSYSERR_NODRIVER: -str = No device driver is present; -break; - -case MMSYSERR_NOMEM: -str = Unable to allocate or lock memory; -break; - -case WAVERR_SYNC: -str = Device is synchronous but waveOutOpen was called -without using the WINWAVE_ALLOWSYNC flag; -break; - -case WAVERR_UNPREPARED: -str = The data block pointed to by the pwh parameter -hasn't been prepared; -break; - -case WAVERR_STILLPLAYING: -str = There are still buffers in the queue; -break; - -default: -dolog (Reason: Unknown (MMRESULT %#x)\n, mr); -return; -} - -dolog (Reason: %s\n, str); -} - -static void GCC_FMT_ATTR (2, 3) winwave_logerr ( -MMRESULT mr, -const char *fmt, -... -) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (NULL, failed\n); -winwave_log_mmresult (mr); -} - -static void winwave_anal_close_out (WaveVoiceOut *wave) -{ -MMRESULT mr; - -mr = waveOutClose (wave-hwo); -if (mr != MMSYSERR_NOERROR) { -winwave_logerr (mr, waveOutClose); -} -wave-hwo = NULL; -} - -static void CALLBACK winwave_callback_out ( -HWAVEOUT hwo, -UINT msg, -DWORD_PTR dwInstance, -DWORD_PTR dwParam1, -DWORD_PTR dwParam2 -) -{ -WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance; - -switch (msg) { -case WOM_DONE: -{ -WAVEHDR *h = (WAVEHDR *) dwParam1; -if (!h-dwUser) { -h-dwUser = 1; -EnterCriticalSection (wave-crit_sect); -{ -wave-avail += conf.dac_samples; -} -LeaveCriticalSection (wave-crit_sect); -if (wave-hw.poll_mode) { -if (!SetEvent (wave-event)) { -dolog (DAC SetEvent failed %lx\n, GetLastError ()); -} -} -} -} -break; - -case WOM_CLOSE: -case WOM_OPEN: -break; - -default
Re: [Qemu-devel] [RFC PATCH v2] qapi for audio backends
Hi, 2015-06-04 17:30 keltezéssel, Gerd Hoffmann írta: Not sure about this one, so it's not yet in this patch: * remove poll_mode: another obscure setting, and it's only matter of time until the code bitrots enough to break it. I'd tend to drop this too, but it's probably good to check what exactly it is doing and to test whenever it actually works. In my quick test it actually worked (but that was with pulseaudio's alsa emulation). Plus currently only alsa an oss seem to care about this option, so even if we keep it, we should probably move it into alsa's and oss's backend options. Any comment is appreciated. Looks good to me as draft to start working with. I expect we'll find some details which need tweeking when implementing this. Yeah, I've already hit a problem. The opts_visitor doesn't really handle nested structs (it just flattens it into a single, non hierarchic namespace), which is a problem because of the input and output options. First I need to make them required (the in and out in Audiodev) if I want the current visitor to visit them at all, but it's still not enough. Doing something like -audiodev frequency=8000 sets the input frequency to 8000 and leaves output frequency undefined. I think I should add an additional syntax: -audiodev in.frequency=8000,out.frequency=16000 (of course it should support deeper nesting like foo.bar.baz.asd=13). The question is what should happen if the user specifies frequency=8000. I see two alternatives: 0. set every frequency field to 8000 (i.e. the same as in.frequency=8000,out.frequency=8000 in this example) 1. bail out with a parameter ambiguous error In the case of audiodev, the 0. approach seems more straightforward (if the user sets frequency, he wants to set both input and output frequency), but in more generic scenarios, the 1. is maybe better. Thanks, Zoltan
[Qemu-devel] [PATCH v3 05/12] alsaaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/alsaaudio.c | 160 +- 1 file changed, 87 insertions(+), 73 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 87e71c6..d7e181b 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -33,30 +33,7 @@ #define AUDIO_CAP alsa #include audio_int.h -struct pollhlp { -snd_pcm_t *handle; -struct pollfd *pfds; -int count; -int mask; -}; - -typedef struct ALSAVoiceOut { -HWVoiceOut hw; -int wpos; -int pending; -void *pcm_buf; -snd_pcm_t *handle; -struct pollhlp pollhlp; -} ALSAVoiceOut; - -typedef struct ALSAVoiceIn { -HWVoiceIn hw; -snd_pcm_t *handle; -void *pcm_buf; -struct pollhlp pollhlp; -} ALSAVoiceIn; - -static struct { +typedef struct ALSAConf { int size_in_usec_in; int size_in_usec_out; const char *pcm_name_in; @@ -73,13 +50,32 @@ static struct { 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, +} ALSAConf; + +struct pollhlp { +snd_pcm_t *handle; +struct pollfd *pfds; +ALSAConf *conf; +int count; +int mask; }; +typedef struct ALSAVoiceOut { +HWVoiceOut hw; +int wpos; +int pending; +void *pcm_buf; +snd_pcm_t *handle; +struct pollhlp pollhlp; +} ALSAVoiceOut; + +typedef struct ALSAVoiceIn { +HWVoiceIn hw; +snd_pcm_t *handle; +void *pcm_buf; +struct pollhlp pollhlp; +} ALSAVoiceIn; + 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) { @@ -270,13 +268,13 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask) NULL, hlp); } if (pfds[i].events POLLOUT) { -if (conf.verbose) { +if (conf-verbose) { dolog (POLLOUT %d %d\n, i, pfds[i].fd); } err = 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); } @@ -476,14 +474,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; @@ -522,7 +521,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); } @@ -654,7 +653,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; @@ -676,7 +675,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); } @@ -686,7 +685,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)) { @@ -729,6
Re: [Qemu-devel] [RFC PATCH v2] qapi for audio backends
Hi, 2015-06-05 12:57 keltezéssel, Gerd Hoffmann írta: Yeah, I've already hit a problem. The opts_visitor doesn't really handle nested structs (it just flattens it into a single, non hierarchic namespace), which is a problem because of the input and output options. First I need to make them required (the in and out in Audiodev) if I want the current visitor to visit them at all, but it's still not enough. I think we should improve the visitor instead of making in out mandatory just because the current implementation (which simply implements the stuff needed for Netdev) can't handle it. It's not that simple I think. The visit_optional only receives a field name, but no info about the type of the field, but it has to decide if it wants the field using only this info. So sort of hacking an if (strcmp(name, in) == 0 || strcmp(name, out) == 0) ... into the option visitor code, the only way is probably to add a type parameter to visit_optional (struct/union/uint32/whatever) and in the opts visitor if type is struct or union, force visiting it. Is it ok? There is always the option to be more specific (in.frequency=...) if setting all parameters named 'frequency' doesn't do what you want. Also I wouldn't worry too much about possible cases which don't exist right now. I'd suggest to go for (0). Alright. Thanks, Zoltan
[Qemu-devel] [PATCH v2 08/12] wavaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/wavaudio.c | 37 + 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 09083da..c586020 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 */ } -- 2.4.2
[Qemu-devel] [PATCH v2 01/12] audio: remove esd backend
ESD is no longer developed and replaced by PulseAudio. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 26a0ac9..5573ac1 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 fd019a0..9dd6b7f 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 eea9cce..000 --- a/audio/esdaudio.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * QEMU ESD audio driver - * - * Copyright (c) 2006 Frederick Reeve (brushed up by malc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the Software), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include esd.h -#include qemu-common.h -#include audio.h - -#define AUDIO_CAP esd -#include audio_int.h -#include audio_pt_int.h - -typedef struct { -HWVoiceOut hw; -int done; -int live; -int decr; -int rpos; -void *pcm_buf; -int fd; -struct audio_pt pt; -} ESDVoiceOut; - -typedef struct { -HWVoiceIn hw; -int done; -int dead; -int incr; -int wpos; -void *pcm_buf; -int fd; -struct audio_pt pt; -} ESDVoiceIn; - -static struct { -int samples; -int divisor; -char *dac_host; -char *adc_host; -} conf = { -.samples = 1024, -.divisor = 2, -}; - -static void GCC_FMT_ATTR (2, 3) qesd_logerr (int err, const char *fmt, ...) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, strerror (err)); -} - -/* playback */ -static void *qesd_thread_out (void *arg) -{ -ESDVoiceOut *esd = arg; -HWVoiceOut *hw = esd-hw; -int threshold; - -threshold = conf.divisor ? hw-samples / conf.divisor : 0; - -if (audio_pt_lock (esd-pt, AUDIO_FUNC)) { -return NULL; -} - -for (;;) { -int decr, to_mix, rpos; - -for (;;) { -if (esd-done) { -goto exit; -} - -if (esd-live threshold) { -break; -} - -if (audio_pt_wait (esd-pt, AUDIO_FUNC)) { -goto exit; -} -} - -decr = to_mix = esd-live; -rpos = hw-rpos; - -if (audio_pt_unlock (esd-pt, AUDIO_FUNC)) { -return NULL; -} - -while (to_mix) { -ssize_t written; -int chunk = audio_MIN (to_mix, hw-samples - rpos); -struct st_sample *src = hw-mix_buf + rpos; - -hw-clip (esd-pcm_buf, src, chunk); - -again: -written = write (esd-fd, esd-pcm_buf, chunk hw-info.shift); -if (written == -1) { -if (errno == EINTR || errno == EAGAIN) { -goto again; -} -qesd_logerr (errno, write failed\n); -return NULL; -} - -if (written != chunk
[Qemu-devel] [PATCH v2 00/12] Audio backend cleanup
This series of patch removes the following audio backends: esd, fmod, winwave. It also cleans up the remaining drivers to do not use global variables where possible. This is a preparation for my GSoC project where I will enable multiple simultaneous audio backends. Please also test the coreaudio backend, as I do not have a Mac to test it. Patches are also available at https://github.com/DirtYiCE/qemu.git in tag audio-cleanup-v2 to simplify testing. Changes since v1: * sdl no longer removed * fixed style issues in `audio: expose drv_opaque to init_out and init_in' Please review. Kővágó, Zoltán (12): audio: remove esd backend audio: remove fmod backend audio: remove winwave audio driver audio: expose drv_opaque to init_out and init_in alsaaudio: do not use global variables paaudio: do not use global variables ossaudio: do not use global variables wavaudio: do not use global variables dsoundaudio: do not use global variables paaudio: fix possible resource leak coreaudio: do not use global variables where possible sdlaudio: do not allow multiple instances audio/Makefile.objs | 4 - audio/alsaaudio.c | 165 ++- audio/audio_int.h | 7 +- audio/audio_template.h | 2 +- audio/coreaudio.c | 46 ++-- audio/dsound_template.h | 24 +- audio/dsoundaudio.c | 106 --- audio/esdaudio.c| 557 - audio/fmodaudio.c | 685 - audio/noaudio.c | 4 +- audio/ossaudio.c| 115 audio/paaudio.c | 105 +++ audio/sdlaudio.c| 10 +- audio/spiceaudio.c | 5 +- audio/wavaudio.c| 42 +-- audio/winwaveaudio.c| 717 configure | 56 +--- 17 files changed, 367 insertions(+), 2283 deletions(-) delete mode 100644 audio/esdaudio.c delete mode 100644 audio/fmodaudio.c delete mode 100644 audio/winwaveaudio.c -- 2.4.2
[Qemu-devel] [PATCH v2 07/12] ossaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/ossaudio.c | 110 ++- 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 069ff60..d247969 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 = 0x04) { -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 av1...@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
[Qemu-devel] [PATCH v2 11/12] coreaudio: do not use global variables where possible
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/coreaudio.c | 43 --- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 20346bc..9f731b7 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 = glostconf.nbuffers, .descr = Number of buffers }, { /* End of list */ } -- 2.4.2
[Qemu-devel] [PATCH v2 05/12] alsaaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/alsaaudio.c | 160 +- 1 file changed, 87 insertions(+), 73 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 87e71c6..d7e181b 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -33,30 +33,7 @@ #define AUDIO_CAP alsa #include audio_int.h -struct pollhlp { -snd_pcm_t *handle; -struct pollfd *pfds; -int count; -int mask; -}; - -typedef struct ALSAVoiceOut { -HWVoiceOut hw; -int wpos; -int pending; -void *pcm_buf; -snd_pcm_t *handle; -struct pollhlp pollhlp; -} ALSAVoiceOut; - -typedef struct ALSAVoiceIn { -HWVoiceIn hw; -snd_pcm_t *handle; -void *pcm_buf; -struct pollhlp pollhlp; -} ALSAVoiceIn; - -static struct { +typedef struct ALSAConf { int size_in_usec_in; int size_in_usec_out; const char *pcm_name_in; @@ -73,13 +50,32 @@ static struct { 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, +} ALSAConf; + +struct pollhlp { +snd_pcm_t *handle; +struct pollfd *pfds; +ALSAConf *conf; +int count; +int mask; }; +typedef struct ALSAVoiceOut { +HWVoiceOut hw; +int wpos; +int pending; +void *pcm_buf; +snd_pcm_t *handle; +struct pollhlp pollhlp; +} ALSAVoiceOut; + +typedef struct ALSAVoiceIn { +HWVoiceIn hw; +snd_pcm_t *handle; +void *pcm_buf; +struct pollhlp pollhlp; +} ALSAVoiceIn; + 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) { @@ -270,13 +268,13 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask) NULL, hlp); } if (pfds[i].events POLLOUT) { -if (conf.verbose) { +if (conf-verbose) { dolog (POLLOUT %d %d\n, i, pfds[i].fd); } err = 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); } @@ -476,14 +474,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; @@ -522,7 +521,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); } @@ -654,7 +653,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; @@ -676,7 +675,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); } @@ -686,7 +685,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)) { @@ -729,6
[Qemu-devel] [PATCH v2 03/12] audio: remove winwave audio driver
DirectSound should be a superior choice on Windows. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 b4c0608..481d1aa 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 7445602..0eba44f 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 8dbd145..000 --- a/audio/winwaveaudio.c +++ /dev/null @@ -1,717 +0,0 @@ -/* public domain */ - -#include qemu-common.h -#include sysemu/sysemu.h -#include audio.h - -#define AUDIO_CAP winwave -#include audio_int.h - -#include windows.h -#include mmsystem.h - -#include audio_win_int.h - -static struct { -int dac_headers; -int dac_samples; -int adc_headers; -int adc_samples; -} conf = { -.dac_headers = 4, -.dac_samples = 1024, -.adc_headers = 4, -.adc_samples = 1024 -}; - -typedef struct { -HWVoiceOut hw; -HWAVEOUT hwo; -WAVEHDR *hdrs; -HANDLE event; -void *pcm_buf; -int avail; -int pending; -int curhdr; -int paused; -CRITICAL_SECTION crit_sect; -} WaveVoiceOut; - -typedef struct { -HWVoiceIn hw; -HWAVEIN hwi; -WAVEHDR *hdrs; -HANDLE event; -void *pcm_buf; -int curhdr; -int paused; -int rpos; -int avail; -CRITICAL_SECTION crit_sect; -} WaveVoiceIn; - -static void winwave_log_mmresult (MMRESULT mr) -{ -const char *str = BUG; - -switch (mr) { -case MMSYSERR_NOERROR: -str = Success; -break; - -case MMSYSERR_INVALHANDLE: -str = Specified device handle is invalid; -break; - -case MMSYSERR_BADDEVICEID: -str = Specified device id is out of range; -break; - -case MMSYSERR_NODRIVER: -str = No device driver is present; -break; - -case MMSYSERR_NOMEM: -str = Unable to allocate or lock memory; -break; - -case WAVERR_SYNC: -str = Device is synchronous but waveOutOpen was called -without using the WINWAVE_ALLOWSYNC flag; -break; - -case WAVERR_UNPREPARED: -str = The data block pointed to by the pwh parameter -hasn't been prepared; -break; - -case WAVERR_STILLPLAYING: -str = There are still buffers in the queue; -break; - -default: -dolog (Reason: Unknown (MMRESULT %#x)\n, mr); -return; -} - -dolog (Reason: %s\n, str); -} - -static void GCC_FMT_ATTR (2, 3) winwave_logerr ( -MMRESULT mr, -const char *fmt, -... -) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (NULL, failed\n); -winwave_log_mmresult (mr); -} - -static void winwave_anal_close_out (WaveVoiceOut *wave) -{ -MMRESULT mr; - -mr = waveOutClose (wave-hwo); -if (mr != MMSYSERR_NOERROR) { -winwave_logerr (mr, waveOutClose); -} -wave-hwo = NULL; -} - -static void CALLBACK winwave_callback_out ( -HWAVEOUT hwo, -UINT msg, -DWORD_PTR dwInstance, -DWORD_PTR dwParam1, -DWORD_PTR dwParam2 -) -{ -WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance; - -switch (msg) { -case WOM_DONE: -{ -WAVEHDR *h = (WAVEHDR *) dwParam1; -if (!h-dwUser) { -h-dwUser = 1; -EnterCriticalSection (wave-crit_sect); -{ -wave-avail += conf.dac_samples; -} -LeaveCriticalSection (wave-crit_sect); -if (wave-hw.poll_mode) { -if (!SetEvent (wave-event)) { -dolog (DAC SetEvent failed %lx\n, GetLastError ()); -} -} -} -} -break; - -case WOM_CLOSE: -case WOM_OPEN: -break; - -default
[Qemu-devel] [PATCH v2 12/12] sdlaudio: do not allow multiple instances
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 dirty.ice...@gmail.com --- audio/sdlaudio.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index b95a7e0..1140f2e 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[] = { -- 2.4.2
[Qemu-devel] [PATCH v2 10/12] paaudio: fix possible resource leak
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 dirty.ice...@gmail.com --- audio/paaudio.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index 35e8887..fea6071 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; } -- 2.4.2
[Qemu-devel] [PATCH v2 02/12] audio: remove fmod backend
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 5573ac1..b4c0608 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 9dd6b7f..7445602 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 fabf84d..000 --- a/audio/fmodaudio.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * QEMU FMOD audio driver - * - * Copyright (c) 2004-2005 Vassili Karpov (malc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the Software), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include fmod.h -#include fmod_errors.h -#include qemu-common.h -#include audio.h - -#define AUDIO_CAP fmod -#include audio_int.h - -typedef struct FMODVoiceOut { -HWVoiceOut hw; -unsigned int old_pos; -FSOUND_SAMPLE *fmod_sample; -int channel; -} FMODVoiceOut; - -typedef struct FMODVoiceIn { -HWVoiceIn hw; -FSOUND_SAMPLE *fmod_sample; -} FMODVoiceIn; - -static struct { -const char *drvname; -int nb_samples; -int freq; -int nb_channels; -int bufsize; -int broken_adc; -} conf = { -.nb_samples = 2048 * 2, -.freq= 44100, -.nb_channels = 2, -}; - -static void GCC_FMT_ATTR (1, 2) fmod_logerr (const char *fmt, ...) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, - FMOD_ErrorString (FSOUND_GetError ())); -} - -static void GCC_FMT_ATTR (2, 3) fmod_logerr2 ( -const char *typ, -const char *fmt, -... -) -{ -va_list ap; - -AUD_log (AUDIO_CAP, Could not initialize %s\n, typ); - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, - FMOD_ErrorString (FSOUND_GetError ())); -} - -static int fmod_write (SWVoiceOut *sw, void *buf, int len) -{ -return audio_pcm_sw_write (sw, buf, len); -} - -static void fmod_clear_sample (FMODVoiceOut *fmd) -{ -HWVoiceOut *hw = fmd-hw; -int status; -void *p1 = 0, *p2 = 0; -unsigned int len1 = 0, len2 = 0; - -status = FSOUND_Sample_Lock ( -fmd-fmod_sample, -0, -hw-samples hw-info.shift, -p1, -p2, -len1, -len2 -); - -if (!status) { -fmod_logerr (Failed to lock sample\n); -return; -} - -if ((len1 hw-info.align) || (len2 hw-info.align)) { -dolog (Lock returned misaligned length %d, %d, alignment %d\n, - len1, len2, hw-info.align + 1); -goto fail; -} - -if ((len1 + len2) - (hw-samples hw-info.shift)) { -dolog (Lock returned
[Qemu-devel] [PATCH v2 06/12] paaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/paaudio.c | 98 ++--- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index bdf6cd5..35e8887 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -9,6 +9,19 @@ #include audio_pt_int.h typedef struct { +int samples; +char *server; +char *sink; +char *source; +} PAConf; + +typedef struct { +PAConf conf; +pa_threaded_mainloop *mainloop; +pa_context *context; +} paaudio; + +typedef struct { HWVoiceOut hw; int done; int live; @@ -17,6 +30,7 @@ typedef struct { pa_stream *stream; void *pcm_buf; struct audio_pt pt; +paaudio *g; } PAVoiceOut; typedef struct { @@ -30,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
[Qemu-devel] [PATCH v2 04/12] audio: expose drv_opaque to init_out and init_in
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 dirty.ice...@gmail.com --- 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 74ead97..87e71c6 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -819,7 +819,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; @@ -928,7 +929,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 0eba44f..566df5e 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 584e536..f716d97 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 5964c62..20346bc 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 8b37d16..98276fb 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 cb38662..50db1f3 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 4db2ca6..069ff60 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -510,7 +510,8 @@ static void oss_fini_out
[Qemu-devel] [PATCH v2 09/12] dsoundaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 98276fb..85ba858 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 e2d89fd..c8b09e2 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
[Qemu-devel] [RFC PATCH] qapi for audio backends
This is a proposal to add structures into qapi-schema.json to replace the existing configuration structures used by audio backends currently. I'm going to use it to implement a new way to specify audio backend options (an -audiodev command line option, instead of environment variables. This will also allow us to use multiple audio backends in one qemu instance), so the structure used here will be the basis of the command line syntax. This is currently more or less a direct translation of the current audio backend options. I've changed some names, trying to accomplish a more consistent naming scheme. I wouldn't be surprised if there were options that doesn't work if you set their value to anything other than the default (for example, log to monitor can crash qemu, QEMU_DSOUND_RESTOURE_RETRIES has a typo, so probably nobody used it, etc). I've also tried to reduce copy-paste, when the same set of options can be given to output and input (QEMU_*_DAC_* and QEMU_*_ADC_* options), also using in and out instead of ADC and DAC, as in the world of SPDIF and HDMI it's completely possible that your computer has nothing to do with analog converters. Plus a non technician user probably has no idea what ADC and DAC stands for. Any comment is appreciated. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- qapi-schema.json | 330 +++ 1 file changed, 330 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index 0662a9b..ff67d5a 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3769,3 +3769,333 @@ # Since: 2.1 ## { 'command': 'rtc-reset-reinjection' } + +## +# @AudiodevNoneOptions +# +# The dummy audio backend has no options. +# +# Since: XXX +## +{ 'struct': 'AudiodevNoneOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use. +# +# @period_size_usec: #optional the period size in microseconds. Must not be +#specified with @period_size_frames. +# +# @period_size_frames: #optional the period size in frames. Must not be +# specified with @period_size_usec. +# +# @buffer_size_usec: #optional the buffer size in microseconds. Must not be +#specified with @buffer_size_frames. +# +# @buffer_size_frames: #optional the buffer size in frames. Must not be +# specified with @buffer_size_usec. +# +# Since: XXX +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data': { +'*dev':'str', +'*period_size_usec': 'int', +'*period_size_frames': 'int', +'*buffer_size_usec': 'int', +'*buffer_size_frames': 'int' } } + +## +# @AudiodevAlsaOptions +# +# Options of the alsa audio backend. +# +# @in: #optional options of the capture stream. +# +# @out: #optional options of the playback stream. +# +# @threshold: #optional +# +# @verbose: #optional behave in a more verbose way +# +# Since: XXX +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { +'*in': 'AudiodevAlsaPerDirectionOptions', +'*out': 'AudiodevAlsaPerDirectionOptions', +'*threshold': 'int', +'*verbose': 'bool' } } + +## +# @AudiodevCoreaudioOptions +# +# Options of the coreaudio backend. +# +# @buffer_size: #optional size of the buffer in frames +# +# @buffer_count: #optional number of buffers +# +# Since: XXX +## +{ 'struct': 'AudiodevCoreaudioOptions', + 'data': { +'*buffer_size': 'int', +'*buffer_count': 'int' } } + +## +# @AudiodevDsoundPerDirectionOptions +# +# Options of the dsound backend that are used for both playback and recording. +# +# @bufsize: #optional +# +# Since: XXX +## +{ 'struct': 'AudiodevDsoundPerDirectionOptions', + 'data' : { +'*bufsize': 'int' } } + +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @in: #optional options of the capture stream. +# +# @out: #optional options of the playback stream. +# +# @lock_retries: #optional number of times to attempt locking the buffer +# +# @restore_retries: #optional number of times to attempt restoring the buffer +# +# @getstatus_retries: #optional number of times to attempt getting status of the +# buffer +# +# @set_primary: #optional set the parameters of primary buffer +# +# @latency_millis: #optional +# +# @primary_freq: #optional primary buffer frequency +# +# @primary_channels: #optional primary buffer number of channels +# +# @primary_format: #optional primary buffer format +# +# Since: XXX +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { +'*in':'AudiodevDsoundPerDirectionOptions', +'*out': 'AudiodevDsoundPerDirectionOptions', +'*lock_retries': 'int', +'*restore_retries': 'int', +'*getstatus_retries': 'int', +'*set_primary': 'bool', +'*latency_millis':'int', +'*primary_freq': 'int
Re: [Qemu-devel] [PULL 00/12] audio patch queue
2015-06-09 15:03 keltezéssel, Peter Maydell írta: ...and a further long list of errors which I assume are mostly run-on from not finding the header file. This looks like it's because configure is now using dsound by default rather than winwave. Yes, the winwave backend was removed, so dsound is the new default. Thanks, Zoltan
[Qemu-devel] [PATCH 3/5] qapi: change Netdev and NetLegacy into a flat union
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- hw/arm/musicpal.c| 2 +- hw/core/qdev-properties-system.c | 2 +- hw/net/allwinner_emac.c | 2 +- hw/net/cadence_gem.c | 2 +- hw/net/dp8393x.c | 2 +- hw/net/e1000.c | 2 +- hw/net/eepro100.c| 2 +- hw/net/etraxfs_eth.c | 2 +- hw/net/fsl_etsec/etsec.c | 2 +- hw/net/lan9118.c | 2 +- hw/net/lance.c | 2 +- hw/net/mcf_fec.c | 2 +- hw/net/milkymist-minimac2.c | 2 +- hw/net/mipsnet.c | 2 +- hw/net/ne2000-isa.c | 2 +- hw/net/ne2000.c | 2 +- hw/net/opencores_eth.c | 2 +- hw/net/pcnet-pci.c | 2 +- hw/net/rocker/rocker_fp.c| 2 +- hw/net/rtl8139.c | 2 +- hw/net/smc91c111.c | 2 +- hw/net/spapr_llan.c | 2 +- hw/net/stellaris_enet.c | 2 +- hw/net/vhost_net.c | 18 +++ hw/net/virtio-net.c | 6 +-- hw/net/vmxnet3.c | 2 +- hw/net/xen_nic.c | 2 +- hw/net/xgmac.c | 2 +- hw/net/xilinx_axienet.c | 2 +- hw/net/xilinx_ethlite.c | 2 +- hw/usb/dev-network.c | 2 +- include/net/net.h| 4 +- monitor.c| 14 ++--- net/clients.h| 20 +++ net/dump.c | 9 ++-- net/hub.c| 24 - net/l2tpv3.c | 9 ++-- net/net.c| 110 +++ net/netmap.c | 6 +-- net/slirp.c | 9 ++-- net/socket.c | 11 ++-- net/tap-win32.c | 9 ++-- net/tap.c| 29 +-- net/vde.c| 9 ++-- net/vhost-user.c | 15 +++--- qapi-schema.json | 103 +--- 46 files changed, 239 insertions(+), 224 deletions(-) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index a3b1314..72e2f8f 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -379,7 +379,7 @@ static void eth_cleanup(NetClientState *nc) } static NetClientInfo net_mv88w8618_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = eth_can_receive, .receive = eth_receive, diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index aa794ca..65ab5a9 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -213,7 +213,7 @@ static void set_netdev(Object *obj, Visitor *v, void *opaque, } queues = qemu_find_net_clients_except(str, peers, - NET_CLIENT_OPTIONS_KIND_NIC, + NET_CLIENT_DRIVER_NIC, MAX_QUEUE_NUM); if (queues == 0) { err = -ENOENT; diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c index 0407dee..4fdf824 100644 --- a/hw/net/allwinner_emac.c +++ b/hw/net/allwinner_emac.c @@ -422,7 +422,7 @@ static const MemoryRegionOps aw_emac_mem_ops = { }; static NetClientInfo net_aw_emac_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = aw_emac_can_receive, .receive = aw_emac_receive, diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 494a346..d74136a 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1175,7 +1175,7 @@ static void gem_set_link(NetClientState *nc) } static NetClientInfo net_gem_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = gem_can_receive, .receive = gem_receive, diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index cd889bc..504a4a1 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -807,7 +807,7 @@ static void dp8393x_reset(DeviceState *dev) } static NetClientInfo net_dp83932_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = dp8393x_can_receive, .receive = dp8393x_receive, diff --git a/hw/net/e1000.c b/hw/net/e1000.c index bab8e2a..fc8bf0d 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1512,7 +1512,7 @@ pci_e1000_uninit(PCIDevice *dev) } static NetClientInfo net_e1000_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = e1000_can_receive, .receive = e1000_receive, diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index c374c1a..cc4e0ae 100644 --- a/hw
[Qemu-devel] [PATCH 4/5] qapi: support nested structs in OptsVisitor
The current OptsVisitor flattens the whole structure, if there are same named fields under different paths the current visitor can't cope with them (it'll just set the first field, leaving the others unspecified (if they're optional) or erroring out (if they're required). This patch add support for it, by always requiring a complete path in case of nested structs. Fields in the path are separated by dots, similar to C structs (without pointers), like `foo.bar'. You must provide a full path even in non-ambigous cases. The previous two commits hopefully ensures that this change doesn't create backward compatibility problems. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Rationale for this commit: see these threads http://lists.nongnu.org/archive/html/qemu-devel/2015-06/msg04189.html http://lists.nongnu.org/archive/html/qemu-devel/2015-06/msg04186.html Change from v2 -audiodev patch: * only fully qualified paths are allowed qapi/opts-visitor.c | 114 ++-- tests/qapi-schema/qapi-schema-test.json | 9 ++- tests/test-opts-visitor.c | 34 ++ 3 files changed, 135 insertions(+), 22 deletions(-) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index aa68814..ff61d42 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -71,6 +71,7 @@ struct OptsVisitor * schema, with a single mandatory scalar member. */ ListMode list_mode; GQueue *repeated_opts; +char *repeated_name; /* When parsing a list of repeating options as integers, values of the form * a-b, representing a closed interval, are allowed. Elements in the @@ -86,6 +87,9 @@ struct OptsVisitor * not survive or escape the OptsVisitor object. */ QemuOpt *fake_id_opt; + +/* List of field names leading to the current structure. */ +GQueue *nested_names; }; @@ -100,6 +104,7 @@ static void opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) { GQueue *list; +assert(opt); list = g_hash_table_lookup(unprocessed_opts, opt-name); if (list == NULL) { @@ -127,6 +132,9 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, if (obj) { *obj = g_malloc0(size 0 ? size : 1); } + +g_queue_push_tail(ov-nested_names, (gpointer) name); + if (ov-depth++ 0) { return; } @@ -169,6 +177,8 @@ opts_end_struct(Visitor *v, Error **errp) OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); GQueue *any; +g_queue_pop_tail(ov-nested_names); + if (--ov-depth 0) { return; } @@ -198,15 +208,54 @@ opts_end_implicit_struct(Visitor *v, Error **errp) } +static void +sum_strlen(gpointer data, gpointer user_data) +{ +const char *str = data; +size_t *sum_len = user_data; + +if (str) { /* skip NULLs */ +*sum_len += strlen(str) + 1; +} +} + +static void +append_str(gpointer data, gpointer user_data) +{ +const char *str = data; +char *concat_str = user_data; + +if (str) { +strcat(concat_str, str); +strcat(concat_str, .); +} +} + +/* lookup a name, using a fully qualified version */ static GQueue * -lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) +lookup_distinct(const OptsVisitor *ov, const char *name, char **out_key, +Error **errp) { -GQueue *list; +GQueue *list = NULL; +char *key; +size_t sum_len = strlen(name); + +g_queue_foreach(ov-nested_names, sum_strlen, sum_len); +key = g_malloc(sum_len+1); +key[0] = 0; +g_queue_foreach(ov-nested_names, append_str, key); +strcat(key, name); + +list = g_hash_table_lookup(ov-unprocessed_opts, key); +if (list out_key) { +*out_key = g_strdup(key); +} -list = g_hash_table_lookup(ov-unprocessed_opts, name); if (!list) { error_setg(errp, QERR_MISSING_PARAMETER, name); } + +g_free(key); return list; } @@ -218,7 +267,7 @@ opts_start_list(Visitor *v, const char *name, Error **errp) /* we can't traverse a list in a list */ assert(ov-list_mode == LM_NONE); -ov-repeated_opts = lookup_distinct(ov, name, errp); +ov-repeated_opts = lookup_distinct(ov, name, ov-repeated_name, errp); if (ov-repeated_opts != NULL) { ov-list_mode = LM_STARTED; } @@ -254,11 +303,9 @@ opts_next_list(Visitor *v, GenericList **list, Error **errp) /* range has been completed, fall through in order to pop option */ case LM_IN_PROGRESS: { -const QemuOpt *opt; - -opt = g_queue_pop_head(ov-repeated_opts); +g_queue_pop_head(ov-repeated_opts); if (g_queue_is_empty(ov-repeated_opts)) { -g_hash_table_remove(ov-unprocessed_opts, opt-name); +g_hash_table_remove(ov-unprocessed_opts, ov-repeated_name); return NULL; } link = (*list)-next; @@ -284,22 +331,28 @@ opts_end_list(Visitor *v, Error
[Qemu-devel] [PATCH 0/5] qapi flattening + some miscellaneous patches
I've cherry-picked the qapi related parts from my previous -audiodev patch series, we can hopefully concentrate on one thing at a time. The most important changes in this patch series are the flattening of the Netdev structures. This way we can add proper nested structure support into OptsVisitor, without requiring backward-compatibility hacks. These patches are essentially same as the patches in v3 -audiodev option, except that I updated it to master (and fixed the conflicts due to error handling related changes). Please review. Kővágó, Zoltán (5): qapi: support implicit structs in OptsVisitor qapi: convert NumaOptions into a flat union qapi: change Netdev and NetLegacy into a flat union qapi: support nested structs in OptsVisitor opts: produce valid command line in qemu_opts_print block.c | 2 +- hw/arm/musicpal.c | 2 +- hw/core/qdev-properties-system.c| 2 +- hw/net/allwinner_emac.c | 2 +- hw/net/cadence_gem.c| 2 +- hw/net/dp8393x.c| 2 +- hw/net/e1000.c | 2 +- hw/net/eepro100.c | 2 +- hw/net/etraxfs_eth.c| 2 +- hw/net/fsl_etsec/etsec.c| 2 +- hw/net/lan9118.c| 2 +- hw/net/lance.c | 2 +- hw/net/mcf_fec.c| 2 +- hw/net/milkymist-minimac2.c | 2 +- hw/net/mipsnet.c| 2 +- hw/net/ne2000-isa.c | 2 +- hw/net/ne2000.c | 2 +- hw/net/opencores_eth.c | 2 +- hw/net/pcnet-pci.c | 2 +- hw/net/rocker/rocker_fp.c | 2 +- hw/net/rtl8139.c| 2 +- hw/net/smc91c111.c | 2 +- hw/net/spapr_llan.c | 2 +- hw/net/stellaris_enet.c | 2 +- hw/net/vhost_net.c | 18 ++-- hw/net/virtio-net.c | 6 +- hw/net/vmxnet3.c| 2 +- hw/net/xen_nic.c| 2 +- hw/net/xgmac.c | 2 +- hw/net/xilinx_axienet.c | 2 +- hw/net/xilinx_ethlite.c | 2 +- hw/usb/dev-network.c| 2 +- include/net/net.h | 4 +- monitor.c | 14 +-- net/clients.h | 20 ++--- net/dump.c | 9 +- net/hub.c | 24 +++-- net/l2tpv3.c| 9 +- net/net.c | 110 +++ net/netmap.c| 6 +- net/slirp.c | 9 +- net/socket.c| 11 +-- net/tap-win32.c | 9 +- net/tap.c | 29 +++--- net/vde.c | 9 +- net/vhost-user.c| 15 ++-- numa.c | 2 +- qapi-schema.json| 150 +++- qapi/opts-visitor.c | 129 ++- tests/qapi-schema/qapi-schema-test.json | 9 +- tests/test-opts-visitor.c | 34 util/qemu-option.c | 47 +- 52 files changed, 471 insertions(+), 262 deletions(-) -- 2.4.3
[Qemu-devel] [PATCH 2/5] qapi: convert NumaOptions into a flat union
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- numa.c | 2 +- qapi-schema.json | 47 --- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/numa.c b/numa.c index 91fc6c1..8b0755d 100644 --- a/numa.c +++ b/numa.c @@ -140,7 +140,7 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) } switch (object-kind) { -case NUMA_OPTIONS_KIND_NODE: +case NUMA_DRIVER_NODE: numa_node_parse(object-node, opts, err); if (err) { goto error; diff --git a/qapi-schema.json b/qapi-schema.json index 106008c..7ebf99e 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3537,17 +3537,6 @@ 'data': { '*console':'int', 'events': [ 'InputEvent' ] } } ## -# @NumaOptions -# -# A discriminated record of NUMA options. (for OptsVisitor) -# -# Since 2.1 -## -{ 'union': 'NumaOptions', - 'data': { -'node': 'NumaNodeOptions' }} - -## # @NumaNodeOptions # # Create a guest NUMA node. (for OptsVisitor) @@ -3574,6 +3563,42 @@ '*memdev': 'str' }} ## +# @NumaDriver +# +# List of possible numa drivers. +# +# Since: 2.4 +## +{ 'enum': 'NumaDriver', + 'data': [ 'node' ] } + +## +# @NumaCommonOptions +# +# Common set of numa options. +# +# @type: the numa driver to use +# +# Since: 2.4 +## +{ 'struct': 'NumaCommonOptions', + 'data': { +'type': 'NumaDriver' } } + +## +# @NumaOptions +# +# A discriminated record of NUMA options. (for OptsVisitor) +# +# Since 2.1 +## +{ 'union': 'NumaOptions', + 'base': 'NumaCommonOptions', + 'discriminator': 'type', + 'data': { +'node': 'NumaNodeOptions' }} + +## # @HostMemPolicy # # Host memory policy types -- 2.4.3
[Qemu-devel] [PATCH 5/5] opts: produce valid command line in qemu_opts_print
This will let us print options in a format that the user would actually write it on the command line (foo=bar,baz=asd,etc=def), without prepending a spurious comma at the beginning of the list, or quoting values unnecessarily. This patch provides the following changes: * write and id=, if the option has an id * do not print separator before the first element * do not quote string arguments which only contains letters or numbers * properly escape commas (,) for QEMU, apostrophe (') for shell Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Chages from v1 -audiodev patch: * print id= * proper value escaping (apostrophe and comma) * renamed d_sep - separator block.c| 2 +- util/qemu-option.c | 47 --- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index e2e33fd..a18af00 100644 --- a/block.c +++ b/block.c @@ -3825,7 +3825,7 @@ void bdrv_img_create(const char *filename, const char *fmt, } if (!quiet) { -printf(Formatting '%s', fmt=%s, filename, fmt); +printf(Formatting '%s', fmt=%s , filename, fmt); qemu_opts_print(opts, ); puts(); } diff --git a/util/qemu-option.c b/util/qemu-option.c index efe9d27..db60ac9 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -730,14 +730,53 @@ void qemu_opts_del(QemuOpts *opts) g_free(opts); } -void qemu_opts_print(QemuOpts *opts, const char *sep) +/* print value properly escaping it for the shell (at least for bash) */ +static void escaped_print(const char *value) +{ +const char *ptr; +bool need_quote = false; + +for (ptr = value; *ptr; ++ptr) { +if (!qemu_isalnum(*ptr)) { +need_quote = true; +break; +} +} + +if (need_quote) { +putchar('\''); +for (ptr = value; *ptr; ++ptr) { +if (*ptr == '\'') { +printf('\\''); +} else if (*ptr == ',') { +printf(,,); +} else { +putchar(*ptr); +} +} +putchar('\''); +} else { +printf(%s, value); +} +} + +void qemu_opts_print(QemuOpts *opts, const char *separator) { QemuOpt *opt; QemuOptDesc *desc = opts-list-desc; +const char *sep = ; + +if (opts-id) { +printf(id=); +escaped_print(opts-id); +sep = separator; +} if (desc[0].name == NULL) { QTAILQ_FOREACH(opt, opts-head, next) { -printf(%s%s=\%s\, sep, opt-name, opt-str); +printf(%s%s=, sep, opt-name); +escaped_print(opt-str); +sep = separator; } return; } @@ -750,13 +789,15 @@ void qemu_opts_print(QemuOpts *opts, const char *sep) continue; } if (desc-type == QEMU_OPT_STRING) { -printf(%s%s='%s', sep, desc-name, value); +printf(%s%s=, sep, desc-name); +escaped_print(value); } else if ((desc-type == QEMU_OPT_SIZE || desc-type == QEMU_OPT_NUMBER) opt) { printf(%s%s=% PRId64, sep, desc-name, opt-value.uint); } else { printf(%s%s=%s, sep, desc-name, value); } +sep = separator; } } -- 2.4.3
[Qemu-devel] [PATCH 1/5] qapi: support implicit structs in OptsVisitor
They are required for flat unions (you still have to allocate the structs). Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- qapi/opts-visitor.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index 7ae33b3..aa68814 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -149,6 +149,12 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, } } +static void +opts_start_implicit_struct(Visitor *v, void **obj, size_t size, Error **errp) +{ +opts_start_struct(v, obj, NULL, NULL, size, errp); +} + static gboolean ghr_true(gpointer ign_key, gpointer ign_value, gpointer ign_user_data) @@ -185,6 +191,12 @@ opts_end_struct(Visitor *v, Error **errp) ov-fake_id_opt = NULL; } +static void +opts_end_implicit_struct(Visitor *v, Error **errp) +{ +opts_end_struct(v, errp); +} + static GQueue * lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) @@ -508,6 +520,9 @@ opts_visitor_new(const QemuOpts *opts) ov-visitor.start_struct = opts_start_struct; ov-visitor.end_struct = opts_end_struct; +ov-visitor.start_implicit_struct = opts_start_implicit_struct; +ov-visitor.end_implicit_struct = opts_end_implicit_struct; + ov-visitor.start_list = opts_start_list; ov-visitor.next_list = opts_next_list; ov-visitor.end_list = opts_end_list; -- 2.4.3
[Qemu-devel] [PATCH v3 0/8] -audiodev option
This series of patches adds a new -audiodev command line option to specify audio subsytem parameters instead of environment variables. This will later allow us to specify multiple audio backends. The syntax is something like this: -audiodev driver_name,id=id,property=value,... like: -audiodev alsa,id=foo,frequency=8000,channels=1 This series also convert numa and netdev qapi to flat unions, to avoid extra complexity in OptsVisitor. Please refer to the thread at v2 patch. You are encouraged check whether I break anything during the refactorings (especially at netdev and various audio backends). For easier testing, pull https://github.com/DirtYiCE/qemu.git tag audio-cmdline-v3. Please review (especially the qapi refactoring I did...) Changes from v2: * consistency, style issues in audio qapi * converted NumaOptions and Netdev and friends to flat union * OptsVisitor: only full paths accepted * qemu_opts_print: hopefully produces valid command line in all cases * other small fixes... Changes from v1: * updated to master, removed commits already merged * now every time-related option takes usecs * some small fixes Kővágó, Zoltán (8): qapi: support implicit structs in OptsVisitor qapi: convert NumaOptions into a flat union qapi: change Netdev and NetLegacy into a flat union qapi: qapi for audio backends qapi: support nested structs in OptsVisitor opts: produce valid command line in qemu_opts_print audio: use qapi AudioFormat instead of audfmt_e audio: -audiodev command line option Makefile| 4 +- audio/Makefile.objs | 2 +- audio/alsaaudio.c | 346 +- audio/audio.c | 792 +--- audio/audio.h | 34 +- audio/audio_int.h | 7 +- audio/audio_legacy.c| 328 + audio/audio_template.h | 13 +- audio/audio_win_int.c | 18 +- audio/coreaudio.c | 49 +- audio/dsound_template.h | 6 +- audio/dsoundaudio.c | 60 +-- audio/noaudio.c | 3 +- audio/ossaudio.c| 182 +++- audio/paaudio.c | 108 ++--- audio/sdlaudio.c| 50 +- audio/spiceaudio.c | 11 +- audio/wavaudio.c| 75 +-- audio/wavcapture.c | 2 +- block.c | 2 +- hw/arm/musicpal.c | 2 +- hw/arm/omap2.c | 2 +- hw/audio/ac97.c | 2 +- hw/audio/adlib.c| 2 +- hw/audio/cs4231a.c | 6 +- hw/audio/es1370.c | 4 +- hw/audio/gus.c | 2 +- hw/audio/hda-codec.c| 18 +- hw/audio/lm4549.c | 6 +- hw/audio/milkymist-ac97.c | 2 +- hw/audio/pcspk.c| 2 +- hw/audio/sb16.c | 14 +- hw/audio/wm8750.c | 4 +- hw/core/qdev-properties-system.c| 2 +- hw/input/tsc210x.c | 2 +- hw/net/allwinner_emac.c | 2 +- hw/net/cadence_gem.c| 2 +- hw/net/dp8393x.c| 2 +- hw/net/e1000.c | 2 +- hw/net/eepro100.c | 2 +- hw/net/etraxfs_eth.c| 2 +- hw/net/fsl_etsec/etsec.c| 2 +- hw/net/lan9118.c| 2 +- hw/net/lance.c | 2 +- hw/net/mcf_fec.c| 2 +- hw/net/milkymist-minimac2.c | 2 +- hw/net/mipsnet.c| 2 +- hw/net/ne2000-isa.c | 2 +- hw/net/ne2000.c | 2 +- hw/net/opencores_eth.c | 2 +- hw/net/pcnet-pci.c | 2 +- hw/net/rocker/rocker_fp.c | 2 +- hw/net/rtl8139.c| 2 +- hw/net/smc91c111.c | 2 +- hw/net/spapr_llan.c | 2 +- hw/net/stellaris_enet.c | 2 +- hw/net/vhost_net.c | 18 +- hw/net/virtio-net.c | 6 +- hw/net/vmxnet3.c| 2 +- hw/net/xen_nic.c| 2 +- hw/net/xgmac.c | 2 +- hw/net/xilinx_axienet.c | 2 +- hw/net/xilinx_ethlite.c | 2 +- hw/usb/dev-audio.c | 2 +- hw/usb/dev-network.c| 2 +- include/net/net.h | 4 +- monitor.c | 14 +- net/clients.h | 20 +- net
[Qemu-devel] [PATCH v3 2/8] qapi: convert NumaOptions into a flat union
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- numa.c | 2 +- qapi-schema.json | 47 --- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/numa.c b/numa.c index d227ccc..822a22e 100644 --- a/numa.c +++ b/numa.c @@ -141,7 +141,7 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) } switch (object-kind) { -case NUMA_OPTIONS_KIND_NODE: +case NUMA_DRIVER_NODE: numa_node_parse(object-node, opts, err); if (err) { goto error; diff --git a/qapi-schema.json b/qapi-schema.json index 106008c..7ebf99e 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3537,17 +3537,6 @@ 'data': { '*console':'int', 'events': [ 'InputEvent' ] } } ## -# @NumaOptions -# -# A discriminated record of NUMA options. (for OptsVisitor) -# -# Since 2.1 -## -{ 'union': 'NumaOptions', - 'data': { -'node': 'NumaNodeOptions' }} - -## # @NumaNodeOptions # # Create a guest NUMA node. (for OptsVisitor) @@ -3574,6 +3563,42 @@ '*memdev': 'str' }} ## +# @NumaDriver +# +# List of possible numa drivers. +# +# Since: 2.4 +## +{ 'enum': 'NumaDriver', + 'data': [ 'node' ] } + +## +# @NumaCommonOptions +# +# Common set of numa options. +# +# @type: the numa driver to use +# +# Since: 2.4 +## +{ 'struct': 'NumaCommonOptions', + 'data': { +'type': 'NumaDriver' } } + +## +# @NumaOptions +# +# A discriminated record of NUMA options. (for OptsVisitor) +# +# Since 2.1 +## +{ 'union': 'NumaOptions', + 'base': 'NumaCommonOptions', + 'discriminator': 'type', + 'data': { +'node': 'NumaNodeOptions' }} + +## # @HostMemPolicy # # Host memory policy types -- 2.4.3
[Qemu-devel] [PATCH v3 5/8] qapi: support nested structs in OptsVisitor
The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like `in' and `out' in `Audiodev'), the current visitor can't cope with them (for example setting `frequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified). This patch fixes it, by always requiring a complete path in case of nested structs. Fields in the path are separated by dots, similar to C structs (without pointers), like `in.frequency' or`out.frequency'. You must provide a full path even in non-ambigous cases. The previous two commits hopefully ensures that this change doesn't create backward compatibility problems. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Change from v2: * only fully qualified paths are allowed qapi/opts-visitor.c | 114 ++-- tests/qapi-schema/qapi-schema-test.json | 9 ++- tests/test-opts-visitor.c | 34 ++ 3 files changed, 135 insertions(+), 22 deletions(-) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index f02059d..7a80442 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -71,6 +71,7 @@ struct OptsVisitor * schema, with a single mandatory scalar member. */ ListMode list_mode; GQueue *repeated_opts; +char *repeated_name; /* When parsing a list of repeating options as integers, values of the form * a-b, representing a closed interval, are allowed. Elements in the @@ -86,6 +87,9 @@ struct OptsVisitor * not survive or escape the OptsVisitor object. */ QemuOpt *fake_id_opt; + +/* List of field names leading to the current structure. */ +GQueue *nested_names; }; @@ -100,6 +104,7 @@ static void opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) { GQueue *list; +assert(opt); list = g_hash_table_lookup(unprocessed_opts, opt-name); if (list == NULL) { @@ -127,6 +132,9 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, if (obj) { *obj = g_malloc0(size 0 ? size : 1); } + +g_queue_push_tail(ov-nested_names, (gpointer) name); + if (ov-depth++ 0) { return; } @@ -169,6 +177,8 @@ opts_end_struct(Visitor *v, Error **errp) OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); GQueue *any; +g_queue_pop_tail(ov-nested_names); + if (--ov-depth 0) { return; } @@ -198,15 +208,54 @@ opts_end_implicit_struct(Visitor *v, Error **errp) } +static void +sum_strlen(gpointer data, gpointer user_data) +{ +const char *str = data; +size_t *sum_len = user_data; + +if (str) { /* skip NULLs */ +*sum_len += strlen(str) + 1; +} +} + +static void +append_str(gpointer data, gpointer user_data) +{ +const char *str = data; +char *concat_str = user_data; + +if (str) { +strcat(concat_str, str); +strcat(concat_str, .); +} +} + +/* lookup a name, using a fully qualified version */ static GQueue * -lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) +lookup_distinct(const OptsVisitor *ov, const char *name, char **out_key, +Error **errp) { -GQueue *list; +GQueue *list = NULL; +char *key; +size_t sum_len = strlen(name); + +g_queue_foreach(ov-nested_names, sum_strlen, sum_len); +key = g_malloc(sum_len+1); +key[0] = 0; +g_queue_foreach(ov-nested_names, append_str, key); +strcat(key, name); + +list = g_hash_table_lookup(ov-unprocessed_opts, key); +if (list out_key) { +*out_key = g_strdup(key); +} -list = g_hash_table_lookup(ov-unprocessed_opts, name); if (!list) { error_set(errp, QERR_MISSING_PARAMETER, name); } + +g_free(key); return list; } @@ -218,7 +267,7 @@ opts_start_list(Visitor *v, const char *name, Error **errp) /* we can't traverse a list in a list */ assert(ov-list_mode == LM_NONE); -ov-repeated_opts = lookup_distinct(ov, name, errp); +ov-repeated_opts = lookup_distinct(ov, name, ov-repeated_name, errp); if (ov-repeated_opts != NULL) { ov-list_mode = LM_STARTED; } @@ -254,11 +303,9 @@ opts_next_list(Visitor *v, GenericList **list, Error **errp) /* range has been completed, fall through in order to pop option */ case LM_IN_PROGRESS: { -const QemuOpt *opt; - -opt = g_queue_pop_head(ov-repeated_opts); +g_queue_pop_head(ov-repeated_opts); if (g_queue_is_empty(ov-repeated_opts)) { -g_hash_table_remove(ov-unprocessed_opts, opt-name); +g_hash_table_remove(ov-unprocessed_opts, ov-repeated_name); return NULL; } link = (*list)-next; @@ -284,22 +331,28 @@ opts_end_list(Visitor *v, Error **errp) ov-list_mode == LM_SIGNED_INTERVAL || ov-list_mode == LM_UNSIGNED_INTERVAL); ov-repeated_opts = NULL; + +g_free(ov
[Qemu-devel] [PATCH v3 7/8] audio: use qapi AudioFormat instead of audfmt_e
I had to include an enum for audio sampling formats into qapi, but that meant duplicating the audfmt_e enum. This patch replaces audfmt_e and associated values with the qapi generated AudioFormat enum. This patch is mostly a search-and-replace, except for switches where the qapi generated AUDIO_FORMAT_MAX caused problems. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Changes from v2: * replaced case AUDIO_FORMAT_MAX with default audio/alsaaudio.c | 53 ++ audio/audio.c | 97 ++- audio/audio.h | 11 +- audio/audio_win_int.c | 18 - audio/ossaudio.c | 30 +++ audio/paaudio.c | 28 +++--- audio/sdlaudio.c | 26 ++--- audio/spiceaudio.c| 4 +- audio/wavaudio.c | 17 + audio/wavcapture.c| 2 +- hw/arm/omap2.c| 2 +- hw/audio/ac97.c | 2 +- hw/audio/adlib.c | 2 +- hw/audio/cs4231a.c| 6 +-- hw/audio/es1370.c | 4 +- hw/audio/gus.c| 2 +- hw/audio/hda-codec.c | 18 - hw/audio/lm4549.c | 6 +-- hw/audio/milkymist-ac97.c | 2 +- hw/audio/pcspk.c | 2 +- hw/audio/sb16.c | 14 +++ hw/audio/wm8750.c | 4 +- hw/input/tsc210x.c| 2 +- hw/usb/dev-audio.c| 2 +- ui/vnc.c | 14 +++ 25 files changed, 187 insertions(+), 181 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 6315b2d..2b28b99 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -88,7 +88,7 @@ struct alsa_params_req { struct alsa_params_obt { int freq; -audfmt_e fmt; +AudioFormat fmt; int endianness; int nchannels; snd_pcm_uframes_t samples; @@ -295,16 +295,16 @@ static int alsa_write (SWVoiceOut *sw, void *buf, int len) return audio_pcm_sw_write (sw, buf, len); } -static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) +static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness) { switch (fmt) { -case AUD_FMT_S8: +case AUDIO_FORMAT_S8: return SND_PCM_FORMAT_S8; -case AUD_FMT_U8: +case AUDIO_FORMAT_U8: return SND_PCM_FORMAT_U8; -case AUD_FMT_S16: +case AUDIO_FORMAT_S16: if (endianness) { return SND_PCM_FORMAT_S16_BE; } @@ -312,7 +312,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_S16_LE; } -case AUD_FMT_U16: +case AUDIO_FORMAT_U16: if (endianness) { return SND_PCM_FORMAT_U16_BE; } @@ -320,7 +320,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_U16_LE; } -case AUD_FMT_S32: +case AUDIO_FORMAT_S32: if (endianness) { return SND_PCM_FORMAT_S32_BE; } @@ -328,7 +328,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_S32_LE; } -case AUD_FMT_U32: +case AUDIO_FORMAT_U32: if (endianness) { return SND_PCM_FORMAT_U32_BE; } @@ -345,58 +345,58 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) } } -static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt, +static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, int *endianness) { switch (alsafmt) { case SND_PCM_FORMAT_S8: *endianness = 0; -*fmt = AUD_FMT_S8; +*fmt = AUDIO_FORMAT_S8; break; case SND_PCM_FORMAT_U8: *endianness = 0; -*fmt = AUD_FMT_U8; +*fmt = AUDIO_FORMAT_U8; break; case SND_PCM_FORMAT_S16_LE: *endianness = 0; -*fmt = AUD_FMT_S16; +*fmt = AUDIO_FORMAT_S16; break; case SND_PCM_FORMAT_U16_LE: *endianness = 0; -*fmt = AUD_FMT_U16; +*fmt = AUDIO_FORMAT_U16; break; case SND_PCM_FORMAT_S16_BE: *endianness = 1; -*fmt = AUD_FMT_S16; +*fmt = AUDIO_FORMAT_S16; break; case SND_PCM_FORMAT_U16_BE: *endianness = 1; -*fmt = AUD_FMT_U16; +*fmt = AUDIO_FORMAT_U16; break; case SND_PCM_FORMAT_S32_LE: *endianness = 0; -*fmt = AUD_FMT_S32; +*fmt = AUDIO_FORMAT_S32; break; case SND_PCM_FORMAT_U32_LE: *endianness = 0; -*fmt = AUD_FMT_U32; +*fmt = AUDIO_FORMAT_U32; break; case SND_PCM_FORMAT_S32_BE: *endianness = 1; -*fmt = AUD_FMT_S32; +*fmt = AUDIO_FORMAT_S32; break; case SND_PCM_FORMAT_U32_BE: *endianness = 1; -*fmt = AUD_FMT_U32; +*fmt = AUDIO_FORMAT_U32; break
[Qemu-devel] [PATCH v3 3/8] qapi: change Netdev and NetLegacy into a flat union
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- hw/arm/musicpal.c| 2 +- hw/core/qdev-properties-system.c | 2 +- hw/net/allwinner_emac.c | 2 +- hw/net/cadence_gem.c | 2 +- hw/net/dp8393x.c | 2 +- hw/net/e1000.c | 2 +- hw/net/eepro100.c| 2 +- hw/net/etraxfs_eth.c | 2 +- hw/net/fsl_etsec/etsec.c | 2 +- hw/net/lan9118.c | 2 +- hw/net/lance.c | 2 +- hw/net/mcf_fec.c | 2 +- hw/net/milkymist-minimac2.c | 2 +- hw/net/mipsnet.c | 2 +- hw/net/ne2000-isa.c | 2 +- hw/net/ne2000.c | 2 +- hw/net/opencores_eth.c | 2 +- hw/net/pcnet-pci.c | 2 +- hw/net/rocker/rocker_fp.c| 2 +- hw/net/rtl8139.c | 2 +- hw/net/smc91c111.c | 2 +- hw/net/spapr_llan.c | 2 +- hw/net/stellaris_enet.c | 2 +- hw/net/vhost_net.c | 18 +++ hw/net/virtio-net.c | 6 +-- hw/net/vmxnet3.c | 2 +- hw/net/xen_nic.c | 2 +- hw/net/xgmac.c | 2 +- hw/net/xilinx_axienet.c | 2 +- hw/net/xilinx_ethlite.c | 2 +- hw/usb/dev-network.c | 2 +- include/net/net.h| 4 +- monitor.c| 14 ++--- net/clients.h| 20 +++ net/dump.c | 9 ++-- net/hub.c| 24 - net/l2tpv3.c | 9 ++-- net/net.c| 110 +++ net/netmap.c | 6 +-- net/slirp.c | 9 ++-- net/socket.c | 11 ++-- net/tap-win32.c | 9 ++-- net/tap.c| 29 +-- net/vde.c| 9 ++-- net/vhost-user.c | 15 +++--- qapi-schema.json | 103 +--- 46 files changed, 239 insertions(+), 224 deletions(-) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index a3b1314..72e2f8f 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -379,7 +379,7 @@ static void eth_cleanup(NetClientState *nc) } static NetClientInfo net_mv88w8618_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = eth_can_receive, .receive = eth_receive, diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 0309fe5..f094548 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -213,7 +213,7 @@ static void set_netdev(Object *obj, Visitor *v, void *opaque, } queues = qemu_find_net_clients_except(str, peers, - NET_CLIENT_OPTIONS_KIND_NIC, + NET_CLIENT_DRIVER_NIC, MAX_QUEUE_NUM); if (queues == 0) { err = -ENOENT; diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c index 0407dee..4fdf824 100644 --- a/hw/net/allwinner_emac.c +++ b/hw/net/allwinner_emac.c @@ -422,7 +422,7 @@ static const MemoryRegionOps aw_emac_mem_ops = { }; static NetClientInfo net_aw_emac_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = aw_emac_can_receive, .receive = aw_emac_receive, diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 494a346..d74136a 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1175,7 +1175,7 @@ static void gem_set_link(NetClientState *nc) } static NetClientInfo net_gem_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = gem_can_receive, .receive = gem_receive, diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index cd889bc..504a4a1 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -807,7 +807,7 @@ static void dp8393x_reset(DeviceState *dev) } static NetClientInfo net_dp83932_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = dp8393x_can_receive, .receive = dp8393x_receive, diff --git a/hw/net/e1000.c b/hw/net/e1000.c index bab8e2a..fc8bf0d 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1512,7 +1512,7 @@ pci_e1000_uninit(PCIDevice *dev) } static NetClientInfo net_e1000_info = { -.type = NET_CLIENT_OPTIONS_KIND_NIC, +.type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), .can_receive = e1000_can_receive, .receive = e1000_receive, diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index c374c1a..cc4e0ae 100644 --- a/hw
[Qemu-devel] [PATCH v3 6/8] opts: produce valid command line in qemu_opts_print
This will let us print options in a format that the user would actually write it on the command line (foo=bar,baz=asd,etc=def), without prepending a spurious comma at the beginning of the list, or quoting values unnecessarily. This patch provides the following changes: * write and id=, if the option has an id * do not print separator before the first element * do not quote string arguments which only contains letters or numbers * properly escape commas (,) for QEMU, apostrophe (') for shell Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Chages from v2: * print id= * proper value escaping (apostrophe and comma) * renamed d_sep - separator block.c| 2 +- util/qemu-option.c | 47 --- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index dd4f58d..c5d456c 100644 --- a/block.c +++ b/block.c @@ -3823,7 +3823,7 @@ void bdrv_img_create(const char *filename, const char *fmt, } if (!quiet) { -printf(Formatting '%s', fmt=%s, filename, fmt); +printf(Formatting '%s', fmt=%s , filename, fmt); qemu_opts_print(opts, ); puts(); } diff --git a/util/qemu-option.c b/util/qemu-option.c index 840f5f7..911f02d 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -728,14 +728,53 @@ void qemu_opts_del(QemuOpts *opts) g_free(opts); } -void qemu_opts_print(QemuOpts *opts, const char *sep) +/* print value properly escaping it for the shell (at least for bash) */ +static void escaped_print(const char *value) +{ +const char *ptr; +bool need_quote = false; + +for (ptr = value; *ptr; ++ptr) { +if (!qemu_isalnum(*ptr)) { +need_quote = true; +break; +} +} + +if (need_quote) { +putchar('\''); +for (ptr = value; *ptr; ++ptr) { +if (*ptr == '\'') { +printf('\\''); +} else if (*ptr == ',') { +printf(,,); +} else { +putchar(*ptr); +} +} +putchar('\''); +} else { +printf(%s, value); +} +} + +void qemu_opts_print(QemuOpts *opts, const char *separator) { QemuOpt *opt; QemuOptDesc *desc = opts-list-desc; +const char *sep = ; + +if (opts-id) { +printf(id=); +escaped_print(opts-id); +sep = separator; +} if (desc[0].name == NULL) { QTAILQ_FOREACH(opt, opts-head, next) { -printf(%s%s=\%s\, sep, opt-name, opt-str); +printf(%s%s=, sep, opt-name); +escaped_print(opt-str); +sep = separator; } return; } @@ -748,13 +787,15 @@ void qemu_opts_print(QemuOpts *opts, const char *sep) continue; } if (desc-type == QEMU_OPT_STRING) { -printf(%s%s='%s', sep, desc-name, value); +printf(%s%s=, sep, desc-name); +escaped_print(value); } else if ((desc-type == QEMU_OPT_SIZE || desc-type == QEMU_OPT_NUMBER) opt) { printf(%s%s=% PRId64, sep, desc-name, opt-value.uint); } else { printf(%s%s=%s, sep, desc-name, value); } +sep = separator; } } -- 2.4.3
[Qemu-devel] [PATCH v3 8/8] audio: -audiodev command line option
This patch adds an -audiodev command line option, and deprecates the QEMU_* environment variables for audio backend configuration. It's syntax is similar to existing options (-netdev, -device, etc): -audiodev driver_name,property=value,... Audio drivers now get an Audiodev * as config paramters, instead of the global audio_option structs. There is some code in audio/audio_legacy.c that converts the old environment variables to audiodev options (this way backends do not have to worry about legacy options). It also contains a replacement of -audio-help, which prints out the equivalent -audiodev based config of the currently specified environment variables. Although now it's possible to specify multiple -audiodev options on command line, multiple audio backends are not supported yet. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Changes from v2: * fixed alsa threshold * updated to audio qapi changes Changes from v1: * updated to everything usecs without suffix * better rounding when converting between usecs and frames/samples/bytes * bugfixes in audio_legacy.c * fixed code broken by qemu_opts changes by Markus audio/Makefile.objs | 2 +- audio/alsaaudio.c | 311 ++-- audio/audio.c | 741 +--- audio/audio.h | 23 +- audio/audio_int.h | 7 +- audio/audio_legacy.c| 328 + audio/audio_template.h | 13 +- audio/coreaudio.c | 49 +--- audio/dsound_template.h | 6 +- audio/dsoundaudio.c | 60 ++-- audio/noaudio.c | 3 +- audio/ossaudio.c| 154 +++--- audio/paaudio.c | 80 ++ audio/sdlaudio.c| 24 +- audio/spiceaudio.c | 7 +- audio/wavaudio.c| 60 +--- qemu-options.hx | 230 ++- vl.c| 9 +- 18 files changed, 997 insertions(+), 1110 deletions(-) create mode 100644 audio/audio_legacy.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index 481d1aa..9d8f579 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = audio.o noaudio.o wavaudio.o mixeng.o +common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o common-obj-$(CONFIG_SDL) += sdlaudio.o common-obj-$(CONFIG_OSS) += ossaudio.o common-obj-$(CONFIG_SPICE) += spiceaudio.o diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 2b28b99..cfe4aec 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ #include alsa/asoundlib.h +#include qapi-visit.h #include qemu-common.h #include qemu/main-loop.h #include audio.h @@ -34,28 +35,9 @@ #define AUDIO_CAP alsa #include audio_int.h -typedef struct ALSAConf { -int size_in_usec_in; -int size_in_usec_out; -const char *pcm_name_in; -const char *pcm_name_out; -unsigned int buffer_size_in; -unsigned int period_size_in; -unsigned int buffer_size_out; -unsigned int period_size_out; -unsigned int threshold; - -int buffer_size_in_overridden; -int period_size_in_overridden; - -int buffer_size_out_overridden; -int period_size_out_overridden; -} ALSAConf; - struct pollhlp { snd_pcm_t *handle; struct pollfd *pfds; -ALSAConf *conf; int count; int mask; }; @@ -67,6 +49,7 @@ typedef struct ALSAVoiceOut { void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; +Audiodev *dev; } ALSAVoiceOut; typedef struct ALSAVoiceIn { @@ -74,16 +57,13 @@ typedef struct ALSAVoiceIn { snd_pcm_t *handle; void *pcm_buf; struct pollhlp pollhlp; +Audiodev *dev; } ALSAVoiceIn; struct alsa_params_req { int freq; snd_pcm_format_t fmt; int nchannels; -int size_in_usec; -int override_mask; -unsigned int buffer_size; -unsigned int period_size; }; struct alsa_params_obt { @@ -409,7 +389,8 @@ static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, static void alsa_dump_info (struct alsa_params_req *req, struct alsa_params_obt *obt, -snd_pcm_format_t obtfmt) +snd_pcm_format_t obtfmt, +AudiodevPerDirectionOptions *pdo) { dolog (parameter | requested value | obtained value\n); dolog (format| %10d | %10d\n, req-fmt, obtfmt); @@ -417,8 +398,9 @@ static void alsa_dump_info (struct alsa_params_req *req, req-nchannels, obt-nchannels); dolog (frequency | %10d | %10d\n, req-freq, obt-freq); dolog (\n); -dolog (requested: buffer size %d period size %d\n, - req-buffer_size, req-period_size); +dolog (requested: buffer size % PRId64 buffer count % PRId64 \n, + pdo-has_buffer_len ? pdo-buffer_len : 0, + pdo-has_buffer_len ? pdo-buffer_len : 0); dolog (obtained: samples %ld\n, obt-samples
[Qemu-devel] [PATCH v3 1/8] qapi: support implicit structs in OptsVisitor
They are required for flat unions (you still have to allocate the structs). Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- qapi/opts-visitor.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index f2ad6d7..f02059d 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -149,6 +149,12 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, } } +static void +opts_start_implicit_struct(Visitor *v, void **obj, size_t size, Error **errp) +{ +opts_start_struct(v, obj, NULL, NULL, size, errp); +} + static gboolean ghr_true(gpointer ign_key, gpointer ign_value, gpointer ign_user_data) @@ -185,6 +191,12 @@ opts_end_struct(Visitor *v, Error **errp) ov-fake_id_opt = NULL; } +static void +opts_end_implicit_struct(Visitor *v, Error **errp) +{ +opts_end_struct(v, errp); +} + static GQueue * lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) @@ -508,6 +520,9 @@ opts_visitor_new(const QemuOpts *opts) ov-visitor.start_struct = opts_start_struct; ov-visitor.end_struct = opts_end_struct; +ov-visitor.start_implicit_struct = opts_start_implicit_struct; +ov-visitor.end_implicit_struct = opts_end_implicit_struct; + ov-visitor.start_list = opts_start_list; ov-visitor.next_list = opts_next_list; ov-visitor.end_list = opts_end_list; -- 2.4.3
[Qemu-devel] [PATCH v3 4/8] qapi: qapi for audio backends
This patch adds structures into qapi to replace the existing configuration structures used by audio backends currently. This qapi will be the base of the -audiodev command line parameter (that replaces the old environment variables based config). This is not a 1:1 translation of the old options, I've tried to make them much more consistent (e.g. almost every backend had an option to specify buffer size, but the name was different for every backend, and some backends required usecs, while some other required frames, samples or bytes). Also tried to reduce the number of abbreviations used by the config keys. Some of the more important changes: * use `in` and `out` instead of `ADC` and `DAC`, as the former is more user friendly imho * moved buffer settings into the global setting area (so it's the same for all backends that support it. Backends that can't change buffer size will simply ignore them). Also using usecs, as it's probably more user friendly than samples or bytes. * try-poll is now an alsa and oss backend specific option (as all other backends currently ignore it) Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Changes from v2 patch: * documentation fixes * rename mmap - try-mmap, buffer - buffer-len * id is now required * converted into flat unions * renamed alsa's and oss's in an out, because it was incompatible with with flat union Changes from v1 patch: * every time-related field now take usecs (and removed -usecs, -millis suffixes) * fixed inconsisten optional marking, language issues Changes from v2 RFC patch: * in, out are no longer optional * try-poll: moved to alsa and oss (as no other backend used them) * voices: added (env variables had this option) * dsound: removed primary buffer related fields Changes from v1 RFC patch: * fixed style issues * moved definitions into a separate file * documented undocumented options (hopefully) * removed plive option. It was useless even years ago so it can probably safely go away: https://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg02427.html * removed verbose, debug options. Backends should use trace events instead. * removed *_retries options from dsound. It's a kludge. * moved buffer_usecs and buffer_count to the global config options. Some driver might ignore it (as they do not expose API to change them). * wav backend: removed frequecy, format, channels as AudiodevPerDirectionOptions already have them. Makefile | 4 +- qapi-schema.json | 3 + qapi/audio.json | 250 +++ 3 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 qapi/audio.json diff --git a/Makefile b/Makefile index 3f97904..ac566fa 100644 --- a/Makefile +++ b/Makefile @@ -257,8 +257,8 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) GEN $@) qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \ - $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \ - $(SRC_PATH)/qapi/event.json + $(SRC_PATH)/qapi/audio.json $(SRC_PATH)/qapi/block.json \ + $(SRC_PATH)/qapi/block-core.json $(SRC_PATH)/qapi/event.json qapi-types.c qapi-types.h :\ $(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) diff --git a/qapi-schema.json b/qapi-schema.json index 2a3cfe3..f1896f4 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -5,6 +5,9 @@ # QAPI common definitions { 'include': 'qapi/common.json' } +# QAPI audio definitions +{ 'include': 'qapi/audio.json' } + # QAPI block definitions { 'include': 'qapi/block.json' } diff --git a/qapi/audio.json b/qapi/audio.json new file mode 100644 index 000..e00f082 --- /dev/null +++ b/qapi/audio.json @@ -0,0 +1,250 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó dirty.ice...@gmail.com +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# @AudiodevNoOptions +# +# The none, coreaudio, sdl and spice audio backend have no options. +# +# Since: 2.4 +## +{ 'struct': 'AudiodevNoOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use (default 'default') +# +# @try-poll: #optional attempt to use poll mode, falling back to non polling +#access on failure (default on) +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data': { +'*dev': 'str', +'*try-poll': 'bool' } } + +## +# @AudiodevAlsaOptions +# +# Options of the alsa audio backend. +# +# @alsa-in: options of the capture stream +# +# @alsa-out: options of the playback stream +# +# @threshold: #optional set the threshold (in microsecods) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { +'alsa
Re: [Qemu-devel] [PATCH v3 5/8] qapi: support nested structs in OptsVisitor
2015-06-18 19:15 keltezéssel, Laszlo Ersek írta: On 06/18/15 18:43, Kővágó, Zoltán wrote: The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like `in' and `out' in `Audiodev'), the current visitor can't cope with them (for example setting `frequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified). This patch fixes it, by always requiring a complete path in case of nested structs. Fields in the path are separated by dots, similar to C structs (without pointers), like `in.frequency' or`out.frequency'. You must provide a full path even in non-ambigous cases. The previous two commits hopefully ensures that this change doesn't create backward compatibility problems. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Change from v2: * only fully qualified paths are allowed qapi/opts-visitor.c | 114 ++-- tests/qapi-schema/qapi-schema-test.json | 9 ++- tests/test-opts-visitor.c | 34 ++ 3 files changed, 135 insertions(+), 22 deletions(-) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index f02059d..7a80442 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -71,6 +71,7 @@ struct OptsVisitor * schema, with a single mandatory scalar member. */ ListMode list_mode; GQueue *repeated_opts; +char *repeated_name; /* When parsing a list of repeating options as integers, values of the form * a-b, representing a closed interval, are allowed. Elements in the @@ -86,6 +87,9 @@ struct OptsVisitor * not survive or escape the OptsVisitor object. */ QemuOpt *fake_id_opt; + +/* List of field names leading to the current structure. */ +GQueue *nested_names; }; @@ -100,6 +104,7 @@ static void opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) { GQueue *list; +assert(opt); list = g_hash_table_lookup(unprocessed_opts, opt-name); if (list == NULL) { @@ -127,6 +132,9 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, if (obj) { *obj = g_malloc0(size 0 ? size : 1); } + +g_queue_push_tail(ov-nested_names, (gpointer) name); + if (ov-depth++ 0) { return; } @@ -169,6 +177,8 @@ opts_end_struct(Visitor *v, Error **errp) OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); GQueue *any; +g_queue_pop_tail(ov-nested_names); + if (--ov-depth 0) { return; } @@ -198,15 +208,54 @@ opts_end_implicit_struct(Visitor *v, Error **errp) } +static void +sum_strlen(gpointer data, gpointer user_data) +{ +const char *str = data; +size_t *sum_len = user_data; + +if (str) { /* skip NULLs */ +*sum_len += strlen(str) + 1; +} +} + +static void +append_str(gpointer data, gpointer user_data) +{ +const char *str = data; +char *concat_str = user_data; + +if (str) { +strcat(concat_str, str); +strcat(concat_str, .); +} +} + +/* lookup a name, using a fully qualified version */ static GQueue * -lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) +lookup_distinct(const OptsVisitor *ov, const char *name, char **out_key, +Error **errp) { -GQueue *list; +GQueue *list = NULL; +char *key; +size_t sum_len = strlen(name); + +g_queue_foreach(ov-nested_names, sum_strlen, sum_len); +key = g_malloc(sum_len+1); +key[0] = 0; +g_queue_foreach(ov-nested_names, append_str, key); +strcat(key, name); + +list = g_hash_table_lookup(ov-unprocessed_opts, key); +if (list out_key) { +*out_key = g_strdup(key); +} -list = g_hash_table_lookup(ov-unprocessed_opts, name); if (!list) { error_set(errp, QERR_MISSING_PARAMETER, name); } + +g_free(key); return list; } @@ -218,7 +267,7 @@ opts_start_list(Visitor *v, const char *name, Error **errp) /* we can't traverse a list in a list */ assert(ov-list_mode == LM_NONE); -ov-repeated_opts = lookup_distinct(ov, name, errp); +ov-repeated_opts = lookup_distinct(ov, name, ov-repeated_name, errp); if (ov-repeated_opts != NULL) { ov-list_mode = LM_STARTED; } @@ -254,11 +303,9 @@ opts_next_list(Visitor *v, GenericList **list, Error **errp) /* range has been completed, fall through in order to pop option */ case LM_IN_PROGRESS: { -const QemuOpt *opt; - -opt = g_queue_pop_head(ov-repeated_opts); +g_queue_pop_head(ov-repeated_opts); if (g_queue_is_empty(ov-repeated_opts)) { -g_hash_table_remove(ov-unprocessed_opts, opt-name); +g_hash_table_remove(ov-unprocessed_opts, ov-repeated_name); return NULL; } link = (*list)-next; @@ -284,22 +331,28 @@ opts_end_list(Visitor *v, Error **errp) ov-list_mode
Re: [Qemu-devel] [PATCH v3 3/8] qapi: change Netdev and NetLegacy into a flat union
2015-06-19 16:06 keltezéssel, Stefan Hajnoczi írta: On Thu, Jun 18, 2015 at 06:43:45PM +0200, Kővágó, Zoltán wrote: @@ -713,8 +710,6 @@ int net_init_tap(const NetClientOptions *opts, const char *name, const char *vhostfdname; char ifname[128]; -assert(opts-kind == NET_CLIENT_OPTIONS_KIND_TAP); -tap = opts-tap; ... @@ -109,14 +109,11 @@ static int net_vde_init(NetClientState *peer, const char *model, return 0; } -int net_init_vde(const NetClientOptions *opts, const char *name, +int net_init_vde(const void *opts, const char *name, NetClientState *peer, Error **errp) { /* FIXME error_setg(errp, ...) on failure */ -const NetdevVdeOptions *vde; - -assert(opts-kind == NET_CLIENT_OPTIONS_KIND_VDE); -vde = opts-vde; +const NetdevVdeOptions *vde = opts; /* missing optional values have been initialized to all bits zero */ if (net_vde_init(peer, vde, name, vde-sock, vde-port, vde-group, ... @@ -228,16 +228,13 @@ static int net_vhost_check_net(void *opaque, QemuOpts *opts, Error **errp) return 0; } -int net_init_vhost_user(const NetClientOptions *opts, const char *name, +int net_init_vhost_user(const void *opts, const char *name, NetClientState *peer, Error **errp) { uint32_t queues; -const NetdevVhostUserOptions *vhost_user_opts; +const NetdevVhostUserOptions *vhost_user_opts = opts; CharDriverState *chr; -assert(opts-kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER); -vhost_user_opts = opts-vhost_user; - Why drop the assertion? Because otherwise you would have to make a version that gets a Netdev and an other that gets Netlegacy, because the common NetClientOptions is gone. Unless, of course, I'm overlooking something. (I've actually tried to simply pass the corect type as arguments, like net_init_chost_user(const NetdevVhostUserOptions *opts, ...; but then net_client_init_fun in net.c becomes problematic. Maybe replacing it with a giant swicth-case would be better?)
[Qemu-devel] [PATCH v2 4/6] qapi: AllocVisitor
Simple visitor that recursively allocates structures with only optional variables. Unions are initialized to the first type specified. Other non optional types are not supported. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- include/qapi/alloc-visitor.h | 18 + qapi/Makefile.objs | 1 + qapi/alloc-visitor.c | 62 3 files changed, 81 insertions(+) create mode 100644 include/qapi/alloc-visitor.h create mode 100644 qapi/alloc-visitor.c diff --git a/include/qapi/alloc-visitor.h b/include/qapi/alloc-visitor.h new file mode 100644 index 000..3d54295 --- /dev/null +++ b/include/qapi/alloc-visitor.h @@ -0,0 +1,18 @@ +/* + * Alloc Visitor. + * Recursively allocates structs, leaving all optional fields unset. In case of + * a non-optional field it fails. + */ + +#ifndef ALLOC_VISITOR_H +#define ALLOC_VISITOR_H + +#include qapi/visitor.h + +typedef struct AllocVisitor AllocVisitor; + +AllocVisitor *alloc_visitor_new(void); +void alloc_visitor_cleanup(AllocVisitor *v); +Visitor *alloc_visitor_get_visitor(AllocVisitor *v); + +#endif diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs index 2278970..7bc26a3 100644 --- a/qapi/Makefile.objs +++ b/qapi/Makefile.objs @@ -4,3 +4,4 @@ util-obj-y += string-input-visitor.o string-output-visitor.o util-obj-y += opts-visitor.o util-obj-y += qmp-event.o util-obj-y += qapi-util.o +util-obj-y += alloc-visitor.o diff --git a/qapi/alloc-visitor.c b/qapi/alloc-visitor.c new file mode 100644 index 000..dbb83af --- /dev/null +++ b/qapi/alloc-visitor.c @@ -0,0 +1,62 @@ +#include qapi/alloc-visitor.h +#include qemu-common.h +#include qapi/visitor-impl.h + +struct AllocVisitor { +Visitor visitor; +}; + +static void alloc_start_struct(Visitor *v, void **obj, const char* kind, + const char *name, size_t size, Error **errp) +{ +if (obj) { +*obj = g_malloc0(size); +} +} + +static void alloc_end_struct(Visitor *v, Error **errp) +{ +} + +static void alloc_start_implicit_struct(Visitor *v, void **obj, size_t size, +Error **errp) +{ +if (obj) { +*obj = g_malloc0(size); +} +} + +static void alloc_end_implicit_struct(Visitor *v, Error **errp) +{ +} + +static void alloc_type_enum(Visitor *v, int *obj, const char *strings[], +const char *kind, const char *name, Error **errp) +{ +assert(*strings); /* there is at least one valid enum value... */ +*obj = 0; +} + +AllocVisitor *alloc_visitor_new(void) +{ +AllocVisitor *v = g_malloc0(sizeof(AllocVisitor)); + +v-visitor.start_struct = alloc_start_struct; +v-visitor.end_struct = alloc_end_struct; +v-visitor.start_implicit_struct = alloc_start_implicit_struct; +v-visitor.end_implicit_struct = alloc_end_implicit_struct; + +v-visitor.type_enum = alloc_type_enum; + +return v; +} + +void alloc_visitor_cleanup(AllocVisitor *v) +{ +g_free(v); +} + +Visitor *alloc_visitor_get_visitor(AllocVisitor *v) +{ +return v-visitor; +} -- 2.4.3
[Qemu-devel] [PATCH v2 6/6] audio: -audiodev command line option
This patch adds an -audiodev command line option, and deprecates the QEMU_* environment variables for audio backend configuration. It's syntax is similar to existing options (-netdev, -device, etc): -audiodev driver_name,property=value,... Audio drivers now get an Audiodev * as config paramters, instead of the global audio_option structs. There is some code in audio/audio_legacy.c that converts the old environment variables to audiodev options (this way backends do not have to worry about legacy options, also print out them with -audio-help, to ease migrating to -audiodev). Although now it's possible to specify multiple -audiodev options on command line, multiple audio backends are not supported yet. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Changes from v1: * updated to everything usecs without suffix * better rounding when converting between usecs and frames/samples/bytes * bugfixes in audio_legacy.c * fixed code broken by qemu_opts changes by Markus audio/Makefile.objs | 2 +- audio/alsaaudio.c | 284 ++ audio/audio.c | 747 +--- audio/audio.h | 23 +- audio/audio_int.h | 7 +- audio/audio_legacy.c| 328 + audio/audio_template.h | 13 +- audio/coreaudio.c | 49 +--- audio/dsound_template.h | 6 +- audio/dsoundaudio.c | 60 ++-- audio/noaudio.c | 3 +- audio/ossaudio.c| 155 +++--- audio/paaudio.c | 81 ++ audio/sdlaudio.c| 24 +- audio/spiceaudio.c | 7 +- audio/wavaudio.c| 61 +--- qemu-options.hx | 218 +- vl.c| 9 +- 18 files changed, 994 insertions(+), 1083 deletions(-) create mode 100644 audio/audio_legacy.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index 481d1aa..9d8f579 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = audio.o noaudio.o wavaudio.o mixeng.o +common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o common-obj-$(CONFIG_SDL) += sdlaudio.o common-obj-$(CONFIG_OSS) += ossaudio.o common-obj-$(CONFIG_SPICE) += spiceaudio.o diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 4d38f5d..a660ae1 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -22,6 +22,8 @@ * THE SOFTWARE. */ #include alsa/asoundlib.h +#include qapi/alloc-visitor.h +#include qapi-visit.h #include qemu-common.h #include qemu/main-loop.h #include audio.h @@ -34,28 +36,9 @@ #define AUDIO_CAP alsa #include audio_int.h -typedef struct ALSAConf { -int size_in_usec_in; -int size_in_usec_out; -const char *pcm_name_in; -const char *pcm_name_out; -unsigned int buffer_size_in; -unsigned int period_size_in; -unsigned int buffer_size_out; -unsigned int period_size_out; -unsigned int threshold; - -int buffer_size_in_overridden; -int period_size_in_overridden; - -int buffer_size_out_overridden; -int period_size_out_overridden; -} ALSAConf; - struct pollhlp { snd_pcm_t *handle; struct pollfd *pfds; -ALSAConf *conf; int count; int mask; }; @@ -67,6 +50,7 @@ typedef struct ALSAVoiceOut { void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; +Audiodev *dev; } ALSAVoiceOut; typedef struct ALSAVoiceIn { @@ -74,16 +58,13 @@ typedef struct ALSAVoiceIn { snd_pcm_t *handle; void *pcm_buf; struct pollhlp pollhlp; +Audiodev *dev; } ALSAVoiceIn; struct alsa_params_req { int freq; snd_pcm_format_t fmt; int nchannels; -int size_in_usec; -int override_mask; -unsigned int buffer_size; -unsigned int period_size; }; struct alsa_params_obt { @@ -409,7 +390,8 @@ static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, static void alsa_dump_info (struct alsa_params_req *req, struct alsa_params_obt *obt, -snd_pcm_format_t obtfmt) +snd_pcm_format_t obtfmt, +AudiodevPerDirectionOptions *pdo) { dolog (parameter | requested value | obtained value\n); dolog (format| %10d | %10d\n, req-fmt, obtfmt); @@ -417,8 +399,9 @@ static void alsa_dump_info (struct alsa_params_req *req, req-nchannels, obt-nchannels); dolog (frequency | %10d | %10d\n, req-freq, obt-freq); dolog (\n); -dolog (requested: buffer size %d period size %d\n, - req-buffer_size, req-period_size); +dolog (requested: buffer size % PRId64 buffer count % PRId64 \n, + pdo-has_buffer ? pdo-buffer : 0, + pdo-has_buffer ? pdo-buffer : 0); dolog (obtained: samples %ld\n, obt-samples); } @@ -452,23 +435,24 @@ static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold) } } -static int alsa_open (int
[Qemu-devel] [PATCH v2 3/6] opts: do not print separator before first item in qemu_opts_print
This allows to print options in a format that the user would actually write it on the command line (foo=bar,baz=asd,etc=def), without prepending a spurious comma at the beginning of the list. Only block.c depended on the old behavior, but it was also updated. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- block.c| 2 +- util/qemu-option.c | 5 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index dd4f58d..c5d456c 100644 --- a/block.c +++ b/block.c @@ -3823,7 +3823,7 @@ void bdrv_img_create(const char *filename, const char *fmt, } if (!quiet) { -printf(Formatting '%s', fmt=%s, filename, fmt); +printf(Formatting '%s', fmt=%s , filename, fmt); qemu_opts_print(opts, ); puts(); } diff --git a/util/qemu-option.c b/util/qemu-option.c index 840f5f7..b347d92 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -728,14 +728,16 @@ void qemu_opts_del(QemuOpts *opts) g_free(opts); } -void qemu_opts_print(QemuOpts *opts, const char *sep) +void qemu_opts_print(QemuOpts *opts, const char *d_sep) { QemuOpt *opt; QemuOptDesc *desc = opts-list-desc; +const char *sep = ; if (desc[0].name == NULL) { QTAILQ_FOREACH(opt, opts-head, next) { printf(%s%s=\%s\, sep, opt-name, opt-str); +sep = d_sep; } return; } @@ -755,6 +757,7 @@ void qemu_opts_print(QemuOpts *opts, const char *sep) } else { printf(%s%s=%s, sep, desc-name, value); } +sep = d_sep; } } -- 2.4.3
[Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
This patch adds structures into qapi to replace the existing configuration structures used by audio backends currently. This qapi will be the base of the -audiodev command line parameter (that replaces the old environment variables based config). This is not a 1:1 translation of the old options, I've tried to make them much more consistent (e.g. almost every backend had an option to specify buffer size, but the name was different for every backend, and some backends required usecs, while some other required frames, samples or bytes). Also tried to reduce the number of abbreviations used by the config keys. Some of the more important changes: * use `in` and `out` instead of `ADC` and `DAC`, as the former is more user friendly imho * moved buffer settings into the global setting area (so it's the same for all backends that support it. Backends that can't change buffer size will simply ignore them). Also using usecs, as it's probably more user friendly than samples or bytes. * try-poll is now an alsa and oss backend specific option (as all other backends currently ignore it) Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Changes from v1 patch: * every time-related field now take usecs (and removed -usecs, -millis suffixes) * fixed inconsisten optional marking, language issues Changes from v2 RFC patch: * in, out are no longer optional * try-poll: moved to alsa and oss (as no other backend used them) * voices: added (env variables had this option) * dsound: removed primary buffer related fields Changes from v1 RFC patch: * fixed style issues * moved definitions into a separate file * documented undocumented options (hopefully) * removed plive option. It was useless even years ago so it can probably safely go away: https://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg02427.html * removed verbose, debug options. Backends should use trace events instead. * removed *_retries options from dsound. It's a kludge. * moved buffer_usecs and buffer_count to the global config options. Some driver might ignore it (as they do not expose API to change them). * wav backend: removed frequecy, format, channels as AudiodevPerDirectionOptions already have them. Makefile | 4 +- qapi-schema.json | 3 + qapi/audio.json | 223 +++ 3 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 qapi/audio.json diff --git a/Makefile b/Makefile index 3f97904..ac566fa 100644 --- a/Makefile +++ b/Makefile @@ -257,8 +257,8 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) GEN $@) qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \ - $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \ - $(SRC_PATH)/qapi/event.json + $(SRC_PATH)/qapi/audio.json $(SRC_PATH)/qapi/block.json \ + $(SRC_PATH)/qapi/block-core.json $(SRC_PATH)/qapi/event.json qapi-types.c qapi-types.h :\ $(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) diff --git a/qapi-schema.json b/qapi-schema.json index 106008c..e751ea3 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -5,6 +5,9 @@ # QAPI common definitions { 'include': 'qapi/common.json' } +# QAPI audio definitions +{ 'include': 'qapi/audio.json' } + # QAPI block definitions { 'include': 'qapi/block.json' } diff --git a/qapi/audio.json b/qapi/audio.json new file mode 100644 index 000..2851689 --- /dev/null +++ b/qapi/audio.json @@ -0,0 +1,223 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó dirty.ice...@gmail.com +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# @AudiodevNoOptions +# +# The none, coreaudio, sdl and spice audio backend have no options. +# +# Since: 2.4 +## +{ 'struct': 'AudiodevNoOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use +# +# @try-poll: #optional attempt to use poll mode +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data': { +'*dev': 'str', +'*try-poll': 'bool' } } + +## +# @AudiodevAlsaOptions +# +# Options of the alsa audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @threshold: #optional set the threshold (in frames) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { +'in': 'AudiodevAlsaPerDirectionOptions', +'out':'AudiodevAlsaPerDirectionOptions', +'*threshold': 'int' } } + +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @latency: #optional add extra latency to playback (in microseconds) +# +# Since: 2.4 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data
[Qemu-devel] [PATCH v2 0/6] -audiodev option
This series of patches adds a new -audiodev command line option to specify audio subsytem parameters instead of environment variables. This will later allow us to specify multiple audio backends. The syntax is something like this: -audiodev driver_name,property=value,... like: -audiodev alsa,frequency=8000,channels=1 The first commit adds a qapi Audiodev struct that describes the audio backend options. The next 4 commits are some miscellaneous additions that are needed by the last commit which finally adds the -audiodev option. For users with esoteric platforms or needs please check I did not break anything accidentally. For easier testing, pull https://github.com/DirtYiCE/qemu.git tag audio-cmdline-v2. Please review. --- Changes from v1: * updated to master, removed commits already merged * now every time-related option takes usecs * some small fixes Kővágó, Zoltán (6): qapi: qapi for audio backends qapi: support nested structs in OptsVisitor opts: do not print separator before first item in qemu_opts_print qapi: AllocVisitor audio: use qapi AudioFormat instead of audfmt_e audio: -audiodev command line option Makefile| 4 +- audio/Makefile.objs | 2 +- audio/alsaaudio.c | 337 +- audio/audio.c | 798 ++-- audio/audio.h | 34 +- audio/audio_int.h | 7 +- audio/audio_legacy.c| 328 + audio/audio_template.h | 13 +- audio/audio_win_int.c | 18 +- audio/coreaudio.c | 49 +- audio/dsound_template.h | 6 +- audio/dsoundaudio.c | 60 +-- audio/noaudio.c | 3 +- audio/ossaudio.c| 183 +++- audio/paaudio.c | 109 ++--- audio/sdlaudio.c| 50 +- audio/spiceaudio.c | 11 +- audio/wavaudio.c| 76 +-- audio/wavcapture.c | 2 +- block.c | 2 +- hw/arm/omap2.c | 2 +- hw/audio/ac97.c | 2 +- hw/audio/adlib.c| 2 +- hw/audio/cs4231a.c | 6 +- hw/audio/es1370.c | 4 +- hw/audio/gus.c | 2 +- hw/audio/hda-codec.c| 18 +- hw/audio/lm4549.c | 6 +- hw/audio/milkymist-ac97.c | 2 +- hw/audio/pcspk.c| 2 +- hw/audio/sb16.c | 14 +- hw/audio/wm8750.c | 4 +- hw/input/tsc210x.c | 2 +- hw/usb/dev-audio.c | 2 +- include/qapi/alloc-visitor.h| 18 + qapi-schema.json| 3 + qapi/Makefile.objs | 1 + qapi/alloc-visitor.c| 62 +++ qapi/audio.json | 223 + qapi/opts-visitor.c | 144 -- qemu-options.hx | 218 - tests/qapi-schema/qapi-schema-test.json | 9 +- tests/test-opts-visitor.c | 34 ++ ui/vnc.c| 14 +- util/qemu-option.c | 5 +- vl.c| 9 +- 46 files changed, 1627 insertions(+), 1273 deletions(-) create mode 100644 audio/audio_legacy.c create mode 100644 include/qapi/alloc-visitor.h create mode 100644 qapi/alloc-visitor.c create mode 100644 qapi/audio.json -- 2.4.3
[Qemu-devel] [PATCH v2 5/6] audio: use qapi AudioFormat instead of audfmt_e
I had to include an enum for audio sampling formats into qapi, but that meant duplicating the audfmt_e enum. This patch replaces audfmt_e and associated values with the qapi generated AudioFormat enum. This patch is mostly a search-and-replace, except for switches where the qapi generated AUDIO_FORMAT_MAX caused problems. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/alsaaudio.c | 53 ++ audio/audio.c | 97 ++- audio/audio.h | 11 +- audio/audio_win_int.c | 18 - audio/ossaudio.c | 30 +++ audio/paaudio.c | 28 +++--- audio/sdlaudio.c | 26 ++--- audio/spiceaudio.c| 4 +- audio/wavaudio.c | 17 + audio/wavcapture.c| 2 +- hw/arm/omap2.c| 2 +- hw/audio/ac97.c | 2 +- hw/audio/adlib.c | 2 +- hw/audio/cs4231a.c| 6 +-- hw/audio/es1370.c | 4 +- hw/audio/gus.c| 2 +- hw/audio/hda-codec.c | 18 - hw/audio/lm4549.c | 6 +-- hw/audio/milkymist-ac97.c | 2 +- hw/audio/pcspk.c | 2 +- hw/audio/sb16.c | 14 +++ hw/audio/wm8750.c | 4 +- hw/input/tsc210x.c| 2 +- hw/usb/dev-audio.c| 2 +- ui/vnc.c | 14 +++ 25 files changed, 187 insertions(+), 181 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 6315b2d..4d38f5d 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -88,7 +88,7 @@ struct alsa_params_req { struct alsa_params_obt { int freq; -audfmt_e fmt; +AudioFormat fmt; int endianness; int nchannels; snd_pcm_uframes_t samples; @@ -295,16 +295,16 @@ static int alsa_write (SWVoiceOut *sw, void *buf, int len) return audio_pcm_sw_write (sw, buf, len); } -static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) +static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness) { switch (fmt) { -case AUD_FMT_S8: +case AUDIO_FORMAT_S8: return SND_PCM_FORMAT_S8; -case AUD_FMT_U8: +case AUDIO_FORMAT_U8: return SND_PCM_FORMAT_U8; -case AUD_FMT_S16: +case AUDIO_FORMAT_S16: if (endianness) { return SND_PCM_FORMAT_S16_BE; } @@ -312,7 +312,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_S16_LE; } -case AUD_FMT_U16: +case AUDIO_FORMAT_U16: if (endianness) { return SND_PCM_FORMAT_U16_BE; } @@ -320,7 +320,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_U16_LE; } -case AUD_FMT_S32: +case AUDIO_FORMAT_S32: if (endianness) { return SND_PCM_FORMAT_S32_BE; } @@ -328,7 +328,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_S32_LE; } -case AUD_FMT_U32: +case AUDIO_FORMAT_U32: if (endianness) { return SND_PCM_FORMAT_U32_BE; } @@ -345,58 +345,58 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) } } -static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt, +static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, int *endianness) { switch (alsafmt) { case SND_PCM_FORMAT_S8: *endianness = 0; -*fmt = AUD_FMT_S8; +*fmt = AUDIO_FORMAT_S8; break; case SND_PCM_FORMAT_U8: *endianness = 0; -*fmt = AUD_FMT_U8; +*fmt = AUDIO_FORMAT_U8; break; case SND_PCM_FORMAT_S16_LE: *endianness = 0; -*fmt = AUD_FMT_S16; +*fmt = AUDIO_FORMAT_S16; break; case SND_PCM_FORMAT_U16_LE: *endianness = 0; -*fmt = AUD_FMT_U16; +*fmt = AUDIO_FORMAT_U16; break; case SND_PCM_FORMAT_S16_BE: *endianness = 1; -*fmt = AUD_FMT_S16; +*fmt = AUDIO_FORMAT_S16; break; case SND_PCM_FORMAT_U16_BE: *endianness = 1; -*fmt = AUD_FMT_U16; +*fmt = AUDIO_FORMAT_U16; break; case SND_PCM_FORMAT_S32_LE: *endianness = 0; -*fmt = AUD_FMT_S32; +*fmt = AUDIO_FORMAT_S32; break; case SND_PCM_FORMAT_U32_LE: *endianness = 0; -*fmt = AUD_FMT_U32; +*fmt = AUDIO_FORMAT_U32; break; case SND_PCM_FORMAT_S32_BE: *endianness = 1; -*fmt = AUD_FMT_S32; +*fmt = AUDIO_FORMAT_S32; break; case SND_PCM_FORMAT_U32_BE: *endianness = 1; -*fmt = AUD_FMT_U32; +*fmt = AUDIO_FORMAT_U32; break; default: @@ -639,19 +639,22 @@ static int alsa_open (int
[Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like `in' and `out' in `Audiodev'), the current visitor can't cope with them (for example setting `frequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified). This patch fixes it, by the following changes: 1) Specifying just the field name will apply to all fields that has the specified name (this means it would set both in's and out's frequency to 44100 in the above example). 2) Optionally user can specify the path in the hierarchy. Names are separated by a dot (e.g. `in.frequency', `foo.bar.something', etc). The user need not specify the whole path, only the last few components (i.e. `bar.something' is equivalent to `foo.bar.something' if only `foo' has a `bar' field). This way 1) is just a special case of this when only the last component is specified. 3) In case of an ambiguity (e.g `frequency=44100,in.frequency=8000') the longest matching (the most specific) path wins (so in this example, in's frequency would become 8000, because `in.frequency' is more specific that `frequency', and out's frequency would become 44100, because only `frequency' matches it). Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- qapi/opts-visitor.c | 144 +--- tests/qapi-schema/qapi-schema-test.json | 9 +- tests/test-opts-visitor.c | 34 3 files changed, 157 insertions(+), 30 deletions(-) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index f2ad6d7..409d8b7 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -64,13 +64,14 @@ struct OptsVisitor /* Non-null iff depth is positive. Each key is a QemuOpt name. Each value * is a non-empty GQueue, enumerating all QemuOpt occurrences with that * name. */ -GHashTable *unprocessed_opts; +GHashTable *unprocessed_opts, *opts; /* The list currently being traversed with opts_start_list() / * opts_next_list(). The list must have a struct element type in the * schema, with a single mandatory scalar member. */ ListMode list_mode; GQueue *repeated_opts; +char *repeated_name; /* When parsing a list of repeating options as integers, values of the form * a-b, representing a closed interval, are allowed. Elements in the @@ -86,6 +87,9 @@ struct OptsVisitor * not survive or escape the OptsVisitor object. */ QemuOpt *fake_id_opt; + +/* List of field names leading to the current structure. */ +GQueue *nested_names; }; @@ -97,11 +101,12 @@ destroy_list(gpointer list) static void -opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) +opts_visitor_insert(OptsVisitor *ov, const QemuOpt *opt) { GQueue *list; +assert(opt); -list = g_hash_table_lookup(unprocessed_opts, opt-name); +list = g_hash_table_lookup(ov-opts, opt-name); if (list == NULL) { list = g_queue_new(); @@ -109,7 +114,8 @@ opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) * key_destroy_func in opts_start_struct(). Thus cast away key * const-ness in order to suppress gcc's warning. */ -g_hash_table_insert(unprocessed_opts, (gpointer)opt-name, list); +g_hash_table_insert(ov-opts, (gpointer)opt-name, list); +g_hash_table_insert(ov-unprocessed_opts, (gpointer)opt-name, list); } /* Similarly, destroy_list() doesn't call g_queue_free_full(). */ @@ -127,17 +133,27 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, if (obj) { *obj = g_malloc0(size 0 ? size : 1); } + +/* assuming name is a statically allocated string (or at least it's lifetime + * is longer than the visitor's) */ +if (!name) { +name = ; +} +g_queue_push_tail(ov-nested_names, (gpointer) name); + if (ov-depth++ 0) { return; } -ov-unprocessed_opts = g_hash_table_new_full(g_str_hash, g_str_equal, - NULL, destroy_list); +ov-opts = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, destroy_list); +ov-unprocessed_opts = g_hash_table_new(g_str_hash, g_str_equal); + QTAILQ_FOREACH(opt, ov-opts_root-head, next) { /* ensured by qemu-option.c::opts_do_parse() */ assert(strcmp(opt-name, id) != 0); -opts_visitor_insert(ov-unprocessed_opts, opt); +opts_visitor_insert(ov, opt); } if (ov-opts_root-id != NULL) { @@ -145,7 +161,7 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, ov-fake_id_opt-name = g_strdup(id); ov-fake_id_opt-str = g_strdup(ov-opts_root-id); -opts_visitor_insert(ov-unprocessed_opts, ov-fake_id_opt); +opts_visitor_insert(ov, ov-fake_id_opt); } } @@ -163,6 +179,8 @@ opts_end_struct
[Qemu-devel] [PATCH 07/12] qapi: qapi for audio backends
This patch adds structures into qapi to replace the existing configuration structures used by audio backends currently. This qapi will be the base of the -audiodev command line parameter (that replaces the old environment variables based config). This is not a 1:1 translation of the old options, I've tried to make them much more consistent (e.g. almost every backend had an option to specify buffer size, but the name was different for every backend, and some backends required usecs, while some other required frames, samples or bytes). Also tried to reduce the number of abbreviations used by the config keys. Some of the more important changes: * use `in` and `out` instead of `ADC` and `DAC`, as the former is more user friendly imho * moved buffer settings into the global setting area (so it's the same for all backends that support it. Backends that can't change buffer size will simply ignore them). Also using usecs, as it's probably more user friendly than samples or bytes. * try-poll is now an alsa and oss backend specific option (as all other backends currently ignore it) Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Changes from v2 RFC patch: * in, out are no longer optional * try-poll: moved to alsa and oss (as no other backend used them) * voices: added (env variables had this option) * dsound: removed primary buffer related fields Changes from v1 RFC patch: * fixed style issues * moved definitions into a separate file * documented undocumented options (hopefully) * removed plive option. It was useless even years ago so it can probably safely go away: https://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg02427.html * removed verbose, debug options. Backends should use trace events instead. * removed *_retries options from dsound. It's a kludge. * moved buffer_usecs and buffer_count to the global config options. Some driver might ignore it (as they do not expose API to change them). * wav backend: removed frequecy, format, channels as AudiodevPerDirectionOptions already have them. Makefile | 4 +- qapi-schema.json | 3 + qapi/audio.json | 217 +++ 3 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 qapi/audio.json diff --git a/Makefile b/Makefile index 2d52536..982563e 100644 --- a/Makefile +++ b/Makefile @@ -257,8 +257,8 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) GEN $@) qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \ - $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \ - $(SRC_PATH)/qapi/event.json + $(SRC_PATH)/qapi/audio.json $(SRC_PATH)/qapi/block.json \ + $(SRC_PATH)/qapi/block-core.json $(SRC_PATH)/qapi/event.json qapi-types.c qapi-types.h :\ $(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) diff --git a/qapi-schema.json b/qapi-schema.json index 6e17a5c..26c470a 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -5,6 +5,9 @@ # QAPI common definitions { 'include': 'qapi/common.json' } +# QAPI audio definitions +{ 'include': 'qapi/audio.json' } + # QAPI block definitions { 'include': 'qapi/block.json' } diff --git a/qapi/audio.json b/qapi/audio.json new file mode 100644 index 000..157ccf6 --- /dev/null +++ b/qapi/audio.json @@ -0,0 +1,217 @@ +# -*- mode: python -*- + +## +# @AudiodevNoneOptions +# +# The none, coreaudio, sdl and spice audio backend has no options. +# +# Since: 2.4 +## +{ 'struct': 'AudiodevNoneOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use +# +# @try-poll: #optional attempt to use poll mode +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data': { +'*dev': 'str', +'*try-poll': 'bool' } } + +## +# @AudiodevAlsaOptions +# +# Options of the alsa audio backend. +# +# @in: #optional options of the capture stream +# +# @out: #optional options of the playback stream +# +# @threshold: #optional set the threshold (in frames) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { +'in': 'AudiodevAlsaPerDirectionOptions', +'out':'AudiodevAlsaPerDirectionOptions', +'*threshold': 'int' } } + +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @latency-millis: #optional add extra latency to playback +# +# Since: 2.4 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { +'*latency-millis': 'int' } } + +## +# @AudiodevOssPerDirectionOptions +# +# Options of the oss backend that are used for both playback and recording. +# +# @dev: #optional path of the oss device +# +# @try-poll: #optional attempt to use poll mode +# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssPerDirectionOptions', + 'data
[Qemu-devel] [PATCH 10/12] qapi: AllocVisitor
Simple visitor that recursively allocates structures with only optional variables. Unions are initialized to the first type specified. Other non optional types are not supported. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- include/qapi/alloc-visitor.h | 18 + qapi/Makefile.objs | 1 + qapi/alloc-visitor.c | 62 3 files changed, 81 insertions(+) create mode 100644 include/qapi/alloc-visitor.h create mode 100644 qapi/alloc-visitor.c diff --git a/include/qapi/alloc-visitor.h b/include/qapi/alloc-visitor.h new file mode 100644 index 000..3d54295 --- /dev/null +++ b/include/qapi/alloc-visitor.h @@ -0,0 +1,18 @@ +/* + * Alloc Visitor. + * Recursively allocates structs, leaving all optional fields unset. In case of + * a non-optional field it fails. + */ + +#ifndef ALLOC_VISITOR_H +#define ALLOC_VISITOR_H + +#include qapi/visitor.h + +typedef struct AllocVisitor AllocVisitor; + +AllocVisitor *alloc_visitor_new(void); +void alloc_visitor_cleanup(AllocVisitor *v); +Visitor *alloc_visitor_get_visitor(AllocVisitor *v); + +#endif diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs index 2278970..7bc26a3 100644 --- a/qapi/Makefile.objs +++ b/qapi/Makefile.objs @@ -4,3 +4,4 @@ util-obj-y += string-input-visitor.o string-output-visitor.o util-obj-y += opts-visitor.o util-obj-y += qmp-event.o util-obj-y += qapi-util.o +util-obj-y += alloc-visitor.o diff --git a/qapi/alloc-visitor.c b/qapi/alloc-visitor.c new file mode 100644 index 000..dbb83af --- /dev/null +++ b/qapi/alloc-visitor.c @@ -0,0 +1,62 @@ +#include qapi/alloc-visitor.h +#include qemu-common.h +#include qapi/visitor-impl.h + +struct AllocVisitor { +Visitor visitor; +}; + +static void alloc_start_struct(Visitor *v, void **obj, const char* kind, + const char *name, size_t size, Error **errp) +{ +if (obj) { +*obj = g_malloc0(size); +} +} + +static void alloc_end_struct(Visitor *v, Error **errp) +{ +} + +static void alloc_start_implicit_struct(Visitor *v, void **obj, size_t size, +Error **errp) +{ +if (obj) { +*obj = g_malloc0(size); +} +} + +static void alloc_end_implicit_struct(Visitor *v, Error **errp) +{ +} + +static void alloc_type_enum(Visitor *v, int *obj, const char *strings[], +const char *kind, const char *name, Error **errp) +{ +assert(*strings); /* there is at least one valid enum value... */ +*obj = 0; +} + +AllocVisitor *alloc_visitor_new(void) +{ +AllocVisitor *v = g_malloc0(sizeof(AllocVisitor)); + +v-visitor.start_struct = alloc_start_struct; +v-visitor.end_struct = alloc_end_struct; +v-visitor.start_implicit_struct = alloc_start_implicit_struct; +v-visitor.end_implicit_struct = alloc_end_implicit_struct; + +v-visitor.type_enum = alloc_type_enum; + +return v; +} + +void alloc_visitor_cleanup(AllocVisitor *v) +{ +g_free(v); +} + +Visitor *alloc_visitor_get_visitor(AllocVisitor *v) +{ +return v-visitor; +} -- 2.4.2
[Qemu-devel] [PATCH 11/12] audio: use qapi AudioFormat instead of audfmt_e
I had to include an enum for audio sampling formats into qapi, but that meant duplicating the audfmt_e enum. This patch replaces audfmt_e and associated values with the qapi generated AudioFormat enum. This patch is mostly a search-and-replace, except for switches where the qapi generated AUDIO_FORMAT_MAX caused problems. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/alsaaudio.c | 53 ++ audio/audio.c | 97 ++- audio/audio.h | 11 +- audio/audio_win_int.c | 18 - audio/ossaudio.c | 30 +++ audio/paaudio.c | 28 +++--- audio/sdlaudio.c | 26 ++--- audio/spiceaudio.c| 4 +- audio/wavaudio.c | 17 + audio/wavcapture.c| 2 +- hw/arm/omap2.c| 2 +- hw/audio/ac97.c | 2 +- hw/audio/adlib.c | 2 +- hw/audio/cs4231a.c| 6 +-- hw/audio/es1370.c | 4 +- hw/audio/gus.c| 2 +- hw/audio/hda-codec.c | 18 - hw/audio/lm4549.c | 6 +-- hw/audio/milkymist-ac97.c | 2 +- hw/audio/pcspk.c | 2 +- hw/audio/sb16.c | 14 +++ hw/audio/wm8750.c | 4 +- hw/input/tsc210x.c| 2 +- hw/usb/dev-audio.c| 2 +- ui/vnc.c | 14 +++ 25 files changed, 187 insertions(+), 181 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index b0a451a..6882638 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -88,7 +88,7 @@ struct alsa_params_req { struct alsa_params_obt { int freq; -audfmt_e fmt; +AudioFormat fmt; int endianness; int nchannels; snd_pcm_uframes_t samples; @@ -307,16 +307,16 @@ static int alsa_write (SWVoiceOut *sw, void *buf, int len) return audio_pcm_sw_write (sw, buf, len); } -static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) +static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness) { switch (fmt) { -case AUD_FMT_S8: +case AUDIO_FORMAT_S8: return SND_PCM_FORMAT_S8; -case AUD_FMT_U8: +case AUDIO_FORMAT_U8: return SND_PCM_FORMAT_U8; -case AUD_FMT_S16: +case AUDIO_FORMAT_S16: if (endianness) { return SND_PCM_FORMAT_S16_BE; } @@ -324,7 +324,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_S16_LE; } -case AUD_FMT_U16: +case AUDIO_FORMAT_U16: if (endianness) { return SND_PCM_FORMAT_U16_BE; } @@ -332,7 +332,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_U16_LE; } -case AUD_FMT_S32: +case AUDIO_FORMAT_S32: if (endianness) { return SND_PCM_FORMAT_S32_BE; } @@ -340,7 +340,7 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) return SND_PCM_FORMAT_S32_LE; } -case AUD_FMT_U32: +case AUDIO_FORMAT_U32: if (endianness) { return SND_PCM_FORMAT_U32_BE; } @@ -357,58 +357,58 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness) } } -static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt, +static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, int *endianness) { switch (alsafmt) { case SND_PCM_FORMAT_S8: *endianness = 0; -*fmt = AUD_FMT_S8; +*fmt = AUDIO_FORMAT_S8; break; case SND_PCM_FORMAT_U8: *endianness = 0; -*fmt = AUD_FMT_U8; +*fmt = AUDIO_FORMAT_U8; break; case SND_PCM_FORMAT_S16_LE: *endianness = 0; -*fmt = AUD_FMT_S16; +*fmt = AUDIO_FORMAT_S16; break; case SND_PCM_FORMAT_U16_LE: *endianness = 0; -*fmt = AUD_FMT_U16; +*fmt = AUDIO_FORMAT_U16; break; case SND_PCM_FORMAT_S16_BE: *endianness = 1; -*fmt = AUD_FMT_S16; +*fmt = AUDIO_FORMAT_S16; break; case SND_PCM_FORMAT_U16_BE: *endianness = 1; -*fmt = AUD_FMT_U16; +*fmt = AUDIO_FORMAT_U16; break; case SND_PCM_FORMAT_S32_LE: *endianness = 0; -*fmt = AUD_FMT_S32; +*fmt = AUDIO_FORMAT_S32; break; case SND_PCM_FORMAT_U32_LE: *endianness = 0; -*fmt = AUD_FMT_U32; +*fmt = AUDIO_FORMAT_U32; break; case SND_PCM_FORMAT_S32_BE: *endianness = 1; -*fmt = AUD_FMT_S32; +*fmt = AUDIO_FORMAT_S32; break; case SND_PCM_FORMAT_U32_BE: *endianness = 1; -*fmt = AUD_FMT_U32; +*fmt = AUDIO_FORMAT_U32; break; default: @@ -651,19 +651,22 @@ static int alsa_open (int
[Qemu-devel] [PATCH 12/12] audio: -audiodev command line option
This patch adds an -audiodev command line option, and deprecates the QEMU_* environment variables for audio backend configuration. It's syntax is similar to existing options (-netdev, -device, etc): -audiodev driver_name,property=value,... Audio drivers now get an Audiodev * as config paramters, instead of the global audio_option structs. There is some code in audio/audio_legacy.c that converts the old environment variables to audiodev options (this way backends do not have to worry about legacy options, also print out them with -audio-help, to ease migrating to -audiodev). Although now it's possible to specify multiple -audiodev options on command line, multiple audio backends are not supported yet. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/Makefile.objs | 2 +- audio/alsaaudio.c | 284 ++ audio/audio.c | 745 +--- audio/audio.h | 21 +- audio/audio_int.h | 7 +- audio/audio_legacy.c| 319 + audio/audio_template.h | 13 +- audio/coreaudio.c | 49 +--- audio/dsound_template.h | 6 +- audio/dsoundaudio.c | 56 +--- audio/noaudio.c | 3 +- audio/ossaudio.c| 155 +++--- audio/paaudio.c | 81 ++ audio/sdlaudio.c| 24 +- audio/spiceaudio.c | 7 +- audio/wavaudio.c| 61 +--- qemu-options.hx | 218 +- vl.c| 9 +- 18 files changed, 979 insertions(+), 1081 deletions(-) create mode 100644 audio/audio_legacy.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index 481d1aa..9d8f579 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = audio.o noaudio.o wavaudio.o mixeng.o +common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o common-obj-$(CONFIG_SDL) += sdlaudio.o common-obj-$(CONFIG_OSS) += ossaudio.o common-obj-$(CONFIG_SPICE) += spiceaudio.o diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 6882638..06230c8 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -22,6 +22,8 @@ * THE SOFTWARE. */ #include alsa/asoundlib.h +#include qapi/alloc-visitor.h +#include qapi-visit.h #include qemu-common.h #include qemu/main-loop.h #include audio.h @@ -34,28 +36,9 @@ #define AUDIO_CAP alsa #include audio_int.h -typedef struct ALSAConf { -int size_in_usec_in; -int size_in_usec_out; -const char *pcm_name_in; -const char *pcm_name_out; -unsigned int buffer_size_in; -unsigned int period_size_in; -unsigned int buffer_size_out; -unsigned int period_size_out; -unsigned int threshold; - -int buffer_size_in_overridden; -int period_size_in_overridden; - -int buffer_size_out_overridden; -int period_size_out_overridden; -} ALSAConf; - struct pollhlp { snd_pcm_t *handle; struct pollfd *pfds; -ALSAConf *conf; int count; int mask; }; @@ -67,6 +50,7 @@ typedef struct ALSAVoiceOut { void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; +Audiodev *dev; } ALSAVoiceOut; typedef struct ALSAVoiceIn { @@ -74,16 +58,13 @@ typedef struct ALSAVoiceIn { snd_pcm_t *handle; void *pcm_buf; struct pollhlp pollhlp; +Audiodev *dev; } ALSAVoiceIn; struct alsa_params_req { int freq; snd_pcm_format_t fmt; int nchannels; -int size_in_usec; -int override_mask; -unsigned int buffer_size; -unsigned int period_size; }; struct alsa_params_obt { @@ -421,7 +402,8 @@ static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, static void alsa_dump_info (struct alsa_params_req *req, struct alsa_params_obt *obt, -snd_pcm_format_t obtfmt) +snd_pcm_format_t obtfmt, +AudiodevPerDirectionOptions *pdo) { dolog (parameter | requested value | obtained value\n); dolog (format| %10d | %10d\n, req-fmt, obtfmt); @@ -429,8 +411,9 @@ static void alsa_dump_info (struct alsa_params_req *req, req-nchannels, obt-nchannels); dolog (frequency | %10d | %10d\n, req-freq, obt-freq); dolog (\n); -dolog (requested: buffer size %d period size %d\n, - req-buffer_size, req-period_size); +dolog (requested: buffer size % PRId64 buffer count % PRId64 \n, + pdo-has_buffer_usecs ? pdo-buffer_usecs : 0, + pdo-has_buffer_count ? pdo-buffer_count : 0); dolog (obtained: samples %ld\n, obt-samples); } @@ -464,23 +447,24 @@ 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, - ALSAConf *conf) +static int alsa_open(bool in, struct
[Qemu-devel] [PATCH 06/12] ossaudio: use trace events instead of debug config flag
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 d247969..d5362ab 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 = 0x04) { 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 av1...@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; } @@ -850,7 +840,6 @@ static OSSConf glob_conf = { .fragsize = 4096, .devpath_out = /dev/dsp, .devpath_in = /dev/dsp, -.debug = 0, .exclusive = 0, .policy = 5 }; @@ -917,12 +906,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 0f372bb..2be8e09 100644 --- a/trace-events +++ b/trace-events @@ -1638,3 +1638,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 -- 2.4.2
[Qemu-devel] [PATCH 05/12] alsaaudio: use trace events instead of verbose
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 d7e181b..b0a451a 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) { @@ -268,16 +264,11 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask) 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); err = 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); if (err) { dolog (Failed to set handler events=%#x index=%d fd=%d err=%d\n, @@ -521,7 +512,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); } @@ -685,10 +676,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); } @@ -728,7 +718,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; @@ -743,9 +732,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: @@ -754,9 +741,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: @@ -767,9 +752,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: @@ -1002,7 +985,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; @@ -1028,14 +1010,10 @@ static int alsa_run_in (HWVoiceIn *hw) dolog (Failed to resume suspended input stream\n); return 0; } -if (conf-verbose) { -dolog
[Qemu-devel] [PATCH 02/12] audio: remove plive
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 dirty.ice...@gmail.com --- 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 cb1cba9..5be4b15 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 f716d97..99b27b2 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); -- 2.4.2
[Qemu-devel] [PATCH 00/12] -audiodev option
Note: this patch depends on my not-yet-merged audio cleanup patches: https://lists.nongnu.org/archive/html/qemu-devel/2015-06/msg02558.html This series of patches adds a new -audiodev command line option to specify audio subsytem parameters instead of environment variables. This will later allow us to specify multiple audio backends. The syntax is something like this: -audiodev driver_name,property=value,... like: -audiodev alsa,frequency=8000,channels=1 The first 6 commits are cleanup commits of the audio backends. The next commit adds a qapi Audiodev struct that describes the audio backend options. The next 4 commits are some miscellaneous additions that are needed by the last commit which finally adds the -audiodev option. For users with esoteric platforms or needs please check I did not break anything accidentally. For easier testing, pull https://github.com/DirtYiCE/qemu.git tag audio-cmdline-v1. Please review. Kővágó, Zoltán (12): audio: remove LOG_TO_MONITOR along with default_mon audio: remove plive dsoundaudio: remove *_retries kludges dsoundaudio: remove primary buffer alsaaudio: use trace events instead of verbose ossaudio: use trace events instead of debug config flag qapi: qapi for audio backends qapi: support nested structs in OptsVisitor opts: do not print separator before first item in qemu_opts_print qapi: AllocVisitor audio: use qapi AudioFormat instead of audfmt_e audio: -audiodev command line option Makefile| 4 +- audio/Makefile.objs | 2 +- audio/alsaaudio.c | 397 +-- audio/audio.c | 831 +--- audio/audio.h | 32 +- audio/audio_int.h | 7 +- audio/audio_legacy.c| 319 audio/audio_template.h | 54 +-- audio/audio_win_int.c | 18 +- audio/coreaudio.c | 49 +- audio/dsound_template.h | 41 +- audio/dsoundaudio.c | 228 ++--- audio/noaudio.c | 3 +- audio/ossaudio.c| 208 +++- audio/paaudio.c | 109 ++--- audio/sdlaudio.c| 50 +- audio/spiceaudio.c | 11 +- audio/wavaudio.c| 76 +-- audio/wavcapture.c | 2 +- block.c | 2 +- hw/arm/omap2.c | 2 +- hw/audio/ac97.c | 2 +- hw/audio/adlib.c| 2 +- hw/audio/cs4231a.c | 6 +- hw/audio/es1370.c | 4 +- hw/audio/gus.c | 2 +- hw/audio/hda-codec.c| 18 +- hw/audio/lm4549.c | 6 +- hw/audio/milkymist-ac97.c | 2 +- hw/audio/pcspk.c| 2 +- hw/audio/sb16.c | 14 +- hw/audio/wm8750.c | 4 +- hw/input/tsc210x.c | 2 +- hw/usb/dev-audio.c | 2 +- include/monitor/monitor.h | 1 - include/qapi/alloc-visitor.h| 18 + monitor.c | 4 - qapi-schema.json| 3 + qapi/Makefile.objs | 1 + qapi/alloc-visitor.c| 62 +++ qapi/audio.json | 217 + qapi/opts-visitor.c | 144 -- qemu-options.hx | 218 - tests/qapi-schema/qapi-schema-test.json | 9 +- tests/test-opts-visitor.c | 34 ++ trace-events| 16 + ui/vnc.c| 14 +- util/qemu-option.c | 5 +- vl.c| 9 +- 49 files changed, 1663 insertions(+), 1603 deletions(-) create mode 100644 audio/audio_legacy.c create mode 100644 include/qapi/alloc-visitor.h create mode 100644 qapi/alloc-visitor.c create mode 100644 qapi/audio.json -- 2.4.2
[Qemu-devel] [PATCH 01/12] audio: remove LOG_TO_MONITOR along with default_mon
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 dirty.ice...@gmail.com --- 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 9d018e9..cb1cba9 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 57f8394..88644ce 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_DEFAULT0x01 diff --git a/monitor.c b/monitor.c index 9afee7b..06aee1f 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); @@ -5270,9 +5269,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, -- 2.4.2
[Qemu-devel] [PATCH 03/12] dsoundaudio: remove *_retries kludges
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 dirty.ice...@gmail.com --- 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 85ba858..b439f33 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 c8b09e2..28b98bf 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, @@ -959,24 +935,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
[Qemu-devel] [PATCH 04/12] dsoundaudio: remove primary buffer
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 dirty.ice...@gmail.com --- audio/dsoundaudio.c | 104 1 file changed, 104 deletions(-) diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 28b98bf..e9472c1 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 }; @@ -935,36 +855,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, .valp = glob_conf.bufsize_out, -- 2.4.2
[Qemu-devel] [PATCH 08/12] qapi: support nested structs in OptsVisitor
The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like `in' and `out' in `Audiodev'), the current visitor can't cope with them (for example setting `frequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified). This patch fixes it, by the following changes: 1) Specifying just the field name will apply to all fields that has the specified name (this means it would set both in's and out's frequency to 44100 in the above example). 2) Optionally user can specify the path in the hierarchy. Names are separated by a dot (e.g. `in.frequency', `foo.bar.something', etc). The user need not specify the whole path, only the last few components (i.e. `bar.something' is equivalent to `foo.bar.something' if only `foo' has a `bar' field). This way 1) is just a special case of this when only the last component is specified. 3) In case of an ambiguity (e.g `frequency=44100,in.frequency=8000') the longest matching (the most specific) path wins (so in this example, in's frequency would become 8000, because `in.frequency' is more specific that `frequency', and out's frequency would become 44100, because only `frequency' matches it). Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- qapi/opts-visitor.c | 144 +--- tests/qapi-schema/qapi-schema-test.json | 9 +- tests/test-opts-visitor.c | 34 3 files changed, 157 insertions(+), 30 deletions(-) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index f2ad6d7..409d8b7 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -64,13 +64,14 @@ struct OptsVisitor /* Non-null iff depth is positive. Each key is a QemuOpt name. Each value * is a non-empty GQueue, enumerating all QemuOpt occurrences with that * name. */ -GHashTable *unprocessed_opts; +GHashTable *unprocessed_opts, *opts; /* The list currently being traversed with opts_start_list() / * opts_next_list(). The list must have a struct element type in the * schema, with a single mandatory scalar member. */ ListMode list_mode; GQueue *repeated_opts; +char *repeated_name; /* When parsing a list of repeating options as integers, values of the form * a-b, representing a closed interval, are allowed. Elements in the @@ -86,6 +87,9 @@ struct OptsVisitor * not survive or escape the OptsVisitor object. */ QemuOpt *fake_id_opt; + +/* List of field names leading to the current structure. */ +GQueue *nested_names; }; @@ -97,11 +101,12 @@ destroy_list(gpointer list) static void -opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) +opts_visitor_insert(OptsVisitor *ov, const QemuOpt *opt) { GQueue *list; +assert(opt); -list = g_hash_table_lookup(unprocessed_opts, opt-name); +list = g_hash_table_lookup(ov-opts, opt-name); if (list == NULL) { list = g_queue_new(); @@ -109,7 +114,8 @@ opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) * key_destroy_func in opts_start_struct(). Thus cast away key * const-ness in order to suppress gcc's warning. */ -g_hash_table_insert(unprocessed_opts, (gpointer)opt-name, list); +g_hash_table_insert(ov-opts, (gpointer)opt-name, list); +g_hash_table_insert(ov-unprocessed_opts, (gpointer)opt-name, list); } /* Similarly, destroy_list() doesn't call g_queue_free_full(). */ @@ -127,17 +133,27 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, if (obj) { *obj = g_malloc0(size 0 ? size : 1); } + +/* assuming name is a statically allocated string (or at least it's lifetime + * is longer than the visitor's) */ +if (!name) { +name = ; +} +g_queue_push_tail(ov-nested_names, (gpointer) name); + if (ov-depth++ 0) { return; } -ov-unprocessed_opts = g_hash_table_new_full(g_str_hash, g_str_equal, - NULL, destroy_list); +ov-opts = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, destroy_list); +ov-unprocessed_opts = g_hash_table_new(g_str_hash, g_str_equal); + QTAILQ_FOREACH(opt, ov-opts_root-head, next) { /* ensured by qemu-option.c::opts_do_parse() */ assert(strcmp(opt-name, id) != 0); -opts_visitor_insert(ov-unprocessed_opts, opt); +opts_visitor_insert(ov, opt); } if (ov-opts_root-id != NULL) { @@ -145,7 +161,7 @@ opts_start_struct(Visitor *v, void **obj, const char *kind, ov-fake_id_opt-name = g_strdup(id); ov-fake_id_opt-str = g_strdup(ov-opts_root-id); -opts_visitor_insert(ov-unprocessed_opts, ov-fake_id_opt); +opts_visitor_insert(ov, ov-fake_id_opt); } } @@ -163,6 +179,8 @@ opts_end_struct
[Qemu-devel] [PATCH 09/12] opts: do not print separator before first item in qemu_opts_print
This allows to print options in a format that the user would actually write it on the command line (foo=bar,baz=asd,etc=def), without prepending a spurious comma at the beginning of the list. Only block.c depended on the old behavior, but it was also updated. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- block.c| 2 +- util/qemu-option.c | 5 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index 2b9ceae..ef335bc 100644 --- a/block.c +++ b/block.c @@ -3644,7 +3644,7 @@ void bdrv_img_create(const char *filename, const char *fmt, } if (!quiet) { -printf(Formatting '%s', fmt=%s, filename, fmt); +printf(Formatting '%s', fmt=%s , filename, fmt); qemu_opts_print(opts, ); puts(); } diff --git a/util/qemu-option.c b/util/qemu-option.c index 840f5f7..b347d92 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -728,14 +728,16 @@ void qemu_opts_del(QemuOpts *opts) g_free(opts); } -void qemu_opts_print(QemuOpts *opts, const char *sep) +void qemu_opts_print(QemuOpts *opts, const char *d_sep) { QemuOpt *opt; QemuOptDesc *desc = opts-list-desc; +const char *sep = ; if (desc[0].name == NULL) { QTAILQ_FOREACH(opt, opts-head, next) { printf(%s%s=\%s\, sep, opt-name, opt-str); +sep = d_sep; } return; } @@ -755,6 +757,7 @@ void qemu_opts_print(QemuOpts *opts, const char *sep) } else { printf(%s%s=%s, sep, desc-name, value); } +sep = d_sep; } } -- 2.4.2
Re: [Qemu-devel] [PATCH 07/12] qapi: qapi for audio backends
2015-06-13 00:11 keltezéssel, Eric Blake írta: +## +# @AudiodevAlsaOptions +# +# Options of the alsa audio backend. +# +# @in: #optional options of the capture stream +# +# @out: #optional options of the playback stream Marked optional here... +# +# @threshold: #optional set the threshold (in frames) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { +'in': 'AudiodevAlsaPerDirectionOptions', +'out':'AudiodevAlsaPerDirectionOptions', ...but not here. Oups. The code is the correct (they are not optional), I forgot updating the documentation. (Same goes for the other mismatches). +'*threshold': 'int' } } + +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @latency-millis: #optional add extra latency to playback +# +# Since: 2.4 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { +'*latency-millis': 'int' } } Style question - should we just call this 'latency', and document the milliseconds unit in the description? But having the name latency_millis in C code might not be all that bad, so you may not want to change this one. There is also a buffer-usecs, so I vote for keeping latency-millis. Also there is timer-period in Audiodev. Maybe it should be renamed to timer-period-hz, to keep consistency. Or maybe change all of them to usecs. Other issues acked. Thanks, Zoltan
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
2015-06-17 18:06 keltezéssel, Markus Armbruster írta: Kővágó Zoltán dirty.ice...@gmail.com writes: 2015-06-17 15:37 keltezéssel, Markus Armbruster írta: Kővágó Zoltán dirty.ice...@gmail.com writes: 2015-06-17 13:48 keltezéssel, Markus Armbruster írta: Kővágó Zoltán dirty.ice...@gmail.com writes: 2015-06-17 09:46 keltezéssel, Markus Armbruster írta: [...] +## +# @AudiodevBackendOptions +# +# A discriminated record of audio backends. +# +# Since: 2.4 +## +{ 'union': 'AudiodevBackendOptions', + 'data': { +'none': 'AudiodevNoOptions', +'alsa': 'AudiodevAlsaOptions', +'coreaudio': 'AudiodevNoOptions', +'dsound':'AudiodevDsoundOptions', +'oss': 'AudiodevOssOptions', +'pa':'AudiodevPaOptions', +'sdl': 'AudiodevNoOptions', +'spice': 'AudiodevNoOptions', +'wav': 'AudiodevWavOptions' } } + +## +# @AudioFormat +# +# An enumeration of possible audio formats. +# +# Since: 2.4 +## +{ 'enum': 'AudioFormat', + 'data': [ 'u8', 's8', 'u16', 's16', 'u32', 's32' ] } + +## +# @AudiodevPerDirectionOptions +# +# General audio backend options that are used for both playback and recording. +# +# @fixed-settings: #optional use fixed settings for host DAC/ADC +# +# @frequency: #optional frequency to use when using fixed settings +# +# @channels: #optional number of channels when using fixed settings +# +# @format: #optional sample format to use when using fixed settings Are these guys used when @fixed-settings is off? No. If @fixed-settings, are the other three all required? If not, what are their defaults? No, they all have defaults: 44100 Hz, 2 channels and s16 format. Okay, this sort of explains why you have @fixed-settings. My first thought was that @fixed-settings is redundant, because we can have any of @frequency, @channels, @format imply fixed settings. Except that doesn't let you ask for the *default* fixed settings, as you have to specify at least one. What's the default for @fixed-settings? It's on by default. What if I specify frequency, channels or format together with explicit fixed-settings: false? They will be ignored. The audio system currently work like this: when an audio frontend wants to open an output with some format (frequency, channels, format) it checks fixed-settings. If it's false, it will just open the stream with the frontend specified settings. If it's true, it'll convert it into the format specified by @frequency, @channels, @format, then pass this converted/recoded stream to the backend. So user typically specifies either fixed-settings=off, or any combination of the other three (including none of them). Correct? We could reject the non-sensical combination of fixed-settings=off plus any of the other three instead of silently ignoring their values. Matter of taste, your choice. Whatever you do, make sure to document how these four work together. Thank you for educating me so patiently. The audio backend currently works like that you can pass any non-sensical values to it, like negative frequency, or 'kdp' count of channels, it will silently fallback to some default value, or just fail, but qemu will continue to run. We can make the new config more strict (and we should, I think), so if you have any idea where should we be more strict (without creating a backward compatibility headache), don't hesitate to point it out.
Re: [Qemu-devel] [PATCH v2 4/6] qapi: AllocVisitor
2015-06-17 09:56 keltezéssel, Markus Armbruster írta: Kővágó, Zoltán dirty.ice...@gmail.com writes: Simple visitor that recursively allocates structures with only optional variables. Unions are initialized to the first type specified. Other non optional types are not supported. Sounds dubious :) Can you explain why it's useful? I guess later patches provide an example. Oh, crap, ignore this commit. Just realized that in the refactorings I did I removed all references to this visitor... so it's not needed.
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
2015-06-17 13:48 keltezéssel, Markus Armbruster írta: Kővágó Zoltán dirty.ice...@gmail.com writes: 2015-06-17 09:46 keltezéssel, Markus Armbruster írta: Copying Eric for additional QAPI schema expertise. My questions inline, pretty sure they show my ignorance. Kővágó, Zoltán dirty.ice...@gmail.com writes: This patch adds structures into qapi to replace the existing configuration structures used by audio backends currently. This qapi will be the base of the -audiodev command line parameter (that replaces the old environment variables based config). This is not a 1:1 translation of the old options, I've tried to make them much more consistent (e.g. almost every backend had an option to specify buffer size, but the name was different for every backend, and some backends required usecs, while some other required frames, samples or bytes). Also tried to reduce the number of abbreviations used by the config keys. Some of the more important changes: * use `in` and `out` instead of `ADC` and `DAC`, as the former is more user friendly imho * moved buffer settings into the global setting area (so it's the same for all backends that support it. Backends that can't change buffer size will simply ignore them). Also using usecs, as it's probably more user friendly than samples or bytes. * try-poll is now an alsa and oss backend specific option (as all other backends currently ignore it) Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Changes from v1 patch: * every time-related field now take usecs (and removed -usecs, -millis suffixes) * fixed inconsisten optional marking, language issues Changes from v2 RFC patch: * in, out are no longer optional * try-poll: moved to alsa and oss (as no other backend used them) * voices: added (env variables had this option) * dsound: removed primary buffer related fields Changes from v1 RFC patch: * fixed style issues * moved definitions into a separate file * documented undocumented options (hopefully) * removed plive option. It was useless even years ago so it can probably safely go away: https://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg02427.html * removed verbose, debug options. Backends should use trace events instead. * removed *_retries options from dsound. It's a kludge. * moved buffer_usecs and buffer_count to the global config options. Some driver might ignore it (as they do not expose API to change them). * wav backend: removed frequecy, format, channels as AudiodevPerDirectionOptions already have them. Makefile | 4 +- qapi-schema.json | 3 + qapi/audio.json | 223 +++ 3 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 qapi/audio.json diff --git a/Makefile b/Makefile index 3f97904..ac566fa 100644 --- a/Makefile +++ b/Makefile @@ -257,8 +257,8 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) GEN $@) qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \ - $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \ - $(SRC_PATH)/qapi/event.json + $(SRC_PATH)/qapi/audio.json $(SRC_PATH)/qapi/block.json \ + $(SRC_PATH)/qapi/block-core.json $(SRC_PATH)/qapi/event.json qapi-types.c qapi-types.h :\ $(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) diff --git a/qapi-schema.json b/qapi-schema.json index 106008c..e751ea3 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -5,6 +5,9 @@ # QAPI common definitions { 'include': 'qapi/common.json' } +# QAPI audio definitions +{ 'include': 'qapi/audio.json' } + # QAPI block definitions { 'include': 'qapi/block.json' } diff --git a/qapi/audio.json b/qapi/audio.json new file mode 100644 index 000..2851689 --- /dev/null +++ b/qapi/audio.json @@ -0,0 +1,223 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó dirty.ice...@gmail.com +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# @AudiodevNoOptions +# +# The none, coreaudio, sdl and spice audio backend have no options. +# +# Since: 2.4 +## +{ 'struct': 'AudiodevNoOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use Who picks the default, QEMU or ALSA? It defaults to default, which tells alsa to use the default device... Then make it # @dev: #optional the name of the alsa device to use (default 'default') +# +# @try-poll: #optional attempt to use poll mode What happens when the attempt fails? It falls back to non polling (timer based) mode. Okay, assuming that's the user interface we want. +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
2015-06-17 13:18 keltezéssel, Markus Armbruster írta: Copying Kevin because similar issues exist in the block layer. Gerd Hoffmann kra...@redhat.com writes: On Mi, 2015-06-17 at 09:50 +0200, Markus Armbruster wrote: Copying László because his fingerprints are on OptsVisitor. Kővágó, Zoltán dirty.ice...@gmail.com writes: The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like `in' and `out' in `Audiodev'), the current visitor can't cope with them (for example setting frequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified). This patch fixes it, by the following changes: 1) Specifying just the field name will apply to all fields that has the specified name (this means it would set both in's and out's frequency to 44100 in the above example). What if they have different types? What if one of them can't take the value? Currently it will error out, requiring the user to be more explicit. Probably not the best solution, but I can't really think of a better solution. (If we would ignore invalid values that would be very confusing imho.) 2) Optionally user can specify the path in the hierarchy. Names are separated by a dot (e.g. `in.frequency', `foo.bar.something', etc). The user need not specify the whole path, only the last few components (i.e. `bar.something' is equivalent to `foo.bar.something' if only `foo' has a `bar' field). This way 1) is just a special case of this when only the last component is specified. 3) In case of an ambiguity (e.g frequency=44100,in.frequency=8000') the longest matching (the most specific) path wins (so in this example, in's frequency would become 8000, because `in.frequency' is more specific that frequency', and out's frequency would become 44100, because only frequency' matches it). The current rule for multiple assignments is last one wins. E.g. in -drive if=none,file=tmp.img,file=tmp.qcow2 file=tmp.qcow2 wins. If I understand correctly, this patch amends the rule to last most specific one wins. Correct? Yes. (But I didn't really checked that as I didn't know about the last one win, and just thought it's an artifact of the current implementation.) Can you explain why the complexity is needed, i.e. why we can't just require full paths always? Keeping the short names is required for -netdev backward compatibility. I suspect mostly because NetLegacy and Netdev aren't flat unions. Could be self-inflicted pain. What about flattening them instead? Assuming that's possible; I'd have to try. Restricting to short or full (i.e. something= or foo.bar.something=, but disallow bar.something=) should not be a problem. I'm not sure this simplifies things much though. We have to build the full path anyway, and I think bar.something= is just a convenient thing we get almost for free ... We've been bitten by convenience features before. Adding them tends to be cheap, but maintaining compatibility can become a terrible headache.
Re: [Qemu-devel] [PATCH v2 6/6] audio: -audiodev command line option
2015-06-17 10:13 keltezéssel, Markus Armbruster írta: Kővágó, Zoltán dirty.ice...@gmail.com writes: This patch adds an -audiodev command line option, and deprecates the QEMU_* environment variables for audio backend configuration. It's syntax is similar to existing options (-netdev, -device, etc): -audiodev driver_name,property=value,... Sounds really good. Please wrap your commit message lines a bit earlier, around column 70. Audio drivers now get an Audiodev * as config paramters, instead of the global audio_option structs. There is some code in audio/audio_legacy.c that converts the old environment variables to audiodev options (this way backends do not have to worry about legacy options, also print out them with -audio-help, to ease migrating to -audiodev). The parenthesis isn't as clear as the rest of your message, probably because it deals with two separate things. Suggest to move out the bit about help into its own paragraph. Although now it's possible to specify multiple -audiodev options on command line, multiple audio backends are not supported yet. What happens when I specify multiple -audiodev? You get an error and qemu terminates. How should the command line look like when multiple audio backends are supported? There's an id property of audiodev, so you can identify them: -audiodev alsa,id=foo,... -audiodev pa,id=bar,... and audio devices should get an extra parameter, like audiodev or something like that: -device usb-audio,audiodev=foo -device usb-audio,audiodev=bar And you have two cards, one connected to the alsa device and the other connected to pulseaudio. Do we have a clear backward-compatible path from here to there? Currently if you specify an -audiodev option, the environment variables are completely ignored, and it will create an audio backend using the specified options. If you do not provide an -audiodev, it will initialize the audio subsystem using the old environment variables when you add the first sound card (so no -audiodev and no sound device means no audio subsystem, just like the old times). About multiple backends: if the user does not specify the id of the backend when creating the sound card, just use the first -audiodev specified on the command line (or the legacy config, if there's no -audiodev). This way we stay backward-compatible (there won't be multiple -audiodevs in legacy configs). [...] 18 files changed, 994 insertions(+), 1083 deletions(-) create mode 100644 audio/audio_legacy.c Very nice delta, but the size is a bit intimidating :) [...]
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
2015-06-17 09:46 keltezéssel, Markus Armbruster írta: Copying Eric for additional QAPI schema expertise. My questions inline, pretty sure they show my ignorance. Kővágó, Zoltán dirty.ice...@gmail.com writes: This patch adds structures into qapi to replace the existing configuration structures used by audio backends currently. This qapi will be the base of the -audiodev command line parameter (that replaces the old environment variables based config). This is not a 1:1 translation of the old options, I've tried to make them much more consistent (e.g. almost every backend had an option to specify buffer size, but the name was different for every backend, and some backends required usecs, while some other required frames, samples or bytes). Also tried to reduce the number of abbreviations used by the config keys. Some of the more important changes: * use `in` and `out` instead of `ADC` and `DAC`, as the former is more user friendly imho * moved buffer settings into the global setting area (so it's the same for all backends that support it. Backends that can't change buffer size will simply ignore them). Also using usecs, as it's probably more user friendly than samples or bytes. * try-poll is now an alsa and oss backend specific option (as all other backends currently ignore it) Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- Changes from v1 patch: * every time-related field now take usecs (and removed -usecs, -millis suffixes) * fixed inconsisten optional marking, language issues Changes from v2 RFC patch: * in, out are no longer optional * try-poll: moved to alsa and oss (as no other backend used them) * voices: added (env variables had this option) * dsound: removed primary buffer related fields Changes from v1 RFC patch: * fixed style issues * moved definitions into a separate file * documented undocumented options (hopefully) * removed plive option. It was useless even years ago so it can probably safely go away: https://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg02427.html * removed verbose, debug options. Backends should use trace events instead. * removed *_retries options from dsound. It's a kludge. * moved buffer_usecs and buffer_count to the global config options. Some driver might ignore it (as they do not expose API to change them). * wav backend: removed frequecy, format, channels as AudiodevPerDirectionOptions already have them. Makefile | 4 +- qapi-schema.json | 3 + qapi/audio.json | 223 +++ 3 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 qapi/audio.json diff --git a/Makefile b/Makefile index 3f97904..ac566fa 100644 --- a/Makefile +++ b/Makefile @@ -257,8 +257,8 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) GEN $@) qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \ - $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \ - $(SRC_PATH)/qapi/event.json + $(SRC_PATH)/qapi/audio.json $(SRC_PATH)/qapi/block.json \ + $(SRC_PATH)/qapi/block-core.json $(SRC_PATH)/qapi/event.json qapi-types.c qapi-types.h :\ $(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) diff --git a/qapi-schema.json b/qapi-schema.json index 106008c..e751ea3 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -5,6 +5,9 @@ # QAPI common definitions { 'include': 'qapi/common.json' } +# QAPI audio definitions +{ 'include': 'qapi/audio.json' } + # QAPI block definitions { 'include': 'qapi/block.json' } diff --git a/qapi/audio.json b/qapi/audio.json new file mode 100644 index 000..2851689 --- /dev/null +++ b/qapi/audio.json @@ -0,0 +1,223 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó dirty.ice...@gmail.com +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# @AudiodevNoOptions +# +# The none, coreaudio, sdl and spice audio backend have no options. +# +# Since: 2.4 +## +{ 'struct': 'AudiodevNoOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use Who picks the default, QEMU or ALSA? It defaults to default, which tells alsa to use the default device... +# +# @try-poll: #optional attempt to use poll mode What happens when the attempt fails? It falls back to non polling (timer based) mode. +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data': { +'*dev': 'str', +'*try-poll': 'bool' } } + +## +# @AudiodevAlsaOptions +# +# Options of the alsa audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @threshold: #optional set the threshold (in frames) when
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
2015-06-17 10:41 keltezéssel, Gerd Hoffmann írta: On Mi, 2015-06-17 at 09:50 +0200, Markus Armbruster wrote: Copying László because his fingerprints are on OptsVisitor. Kővágó, Zoltán dirty.ice...@gmail.com writes: The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like `in' and `out' in `Audiodev'), the current visitor can't cope with them (for example setting `frequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified). This patch fixes it, by the following changes: 1) Specifying just the field name will apply to all fields that has the specified name (this means it would set both in's and out's frequency to 44100 in the above example). 2) Optionally user can specify the path in the hierarchy. Names are separated by a dot (e.g. `in.frequency', `foo.bar.something', etc). The user need not specify the whole path, only the last few components (i.e. `bar.something' is equivalent to `foo.bar.something' if only `foo' has a `bar' field). This way 1) is just a special case of this when only the last component is specified. 3) In case of an ambiguity (e.g `frequency=44100,in.frequency=8000') the longest matching (the most specific) path wins (so in this example, in's frequency would become 8000, because `in.frequency' is more specific that `frequency', and out's frequency would become 44100, because only `frequency' matches it). Can you explain why the complexity is needed, i.e. why we can't just require full paths always? Keeping the short names is required for -netdev backward compatibility. Restricting to short or full (i.e. something= or foo.bar.something=, but disallow bar.something=) should not be a problem. I'm not sure this simplifies things much though. We have to build the full path anyway, and I think bar.something= is just a convenient thing we get almost for free ... With the current implementation you can specify (see my previous patch) in.try-poll=off in case of alsa. If we would need full paths, it would look like opts.data.in.try-poll=off, which is probably not something we want.
Re: [Qemu-devel] [PATCH v2 5/6] audio: use qapi AudioFormat instead of audfmt_e
2015-06-17 10:01 keltezéssel, Markus Armbruster írta: Kővágó, Zoltán dirty.ice...@gmail.com writes: I had to include an enum for audio sampling formats into qapi, but that meant duplicating the audfmt_e enum. This patch replaces audfmt_e and associated values with the qapi generated AudioFormat enum. This patch is mostly a search-and-replace, except for switches where the qapi generated AUDIO_FORMAT_MAX caused problems. [...] diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 6315b2d..4d38f5d 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c [...] @@ -639,19 +639,22 @@ static int alsa_open (int in, struct alsa_params_req *req, bytes_per_sec = freq (nchannels == 2); switch (obt-fmt) { -case AUD_FMT_S8: -case AUD_FMT_U8: +case AUDIO_FORMAT_S8: +case AUDIO_FORMAT_U8: break; -case AUD_FMT_S16: -case AUD_FMT_U16: +case AUDIO_FORMAT_S16: +case AUDIO_FORMAT_U16: bytes_per_sec = 1; break; -case AUD_FMT_S32: -case AUD_FMT_U32: +case AUDIO_FORMAT_S32: +case AUDIO_FORMAT_U32: bytes_per_sec = 2; break; + +case AUDIO_FORMAT_MAX: +break; Can this happen? Not under normal circumstances, but gcc warns otherwise. } threshold = (conf-threshold * bytes_per_sec) / 1000; diff --git a/audio/audio.c b/audio/audio.c index 5be4b15..112b57b 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -75,7 +75,7 @@ static struct { .settings = { .freq = 44100, .nchannels = 2, -.fmt = AUD_FMT_S16, +.fmt = AUDIO_FORMAT_S16, .endianness = AUDIO_HOST_ENDIANNESS, } }, @@ -87,7 +87,7 @@ static struct { .settings = { .freq = 44100, .nchannels = 2, -.fmt = AUD_FMT_S16, +.fmt = AUDIO_FORMAT_S16, .endianness = AUDIO_HOST_ENDIANNESS, } }, @@ -219,58 +219,61 @@ static char *audio_alloc_prefix (const char *s) return r; } -static const char *audio_audfmt_to_string (audfmt_e fmt) +static const char *audio_audfmt_to_string (AudioFormat fmt) { switch (fmt) { -case AUD_FMT_U8: +case AUDIO_FORMAT_U8: return U8; -case AUD_FMT_U16: +case AUDIO_FORMAT_U16: return U16; -case AUD_FMT_S8: +case AUDIO_FORMAT_S8: return S8; -case AUD_FMT_S16: +case AUDIO_FORMAT_S16: return S16; -case AUD_FMT_U32: +case AUDIO_FORMAT_U32: return U32; -case AUD_FMT_S32: +case AUDIO_FORMAT_S32: return S32; + +case AUDIO_FORMAT_MAX: default: would be more defensive. Same elsewhere. Ok, I'll change them to default. +abort(); } dolog (Bogus audfmt %d returning S16\n, fmt); return S16; } [...]
Re: [Qemu-devel] [PATCH v2 6/6] audio: -audiodev command line option
2015-06-17 14:27 keltezéssel, Markus Armbruster írta: Kővágó Zoltán dirty.ice...@gmail.com writes: 2015-06-17 10:13 keltezéssel, Markus Armbruster írta: Kővágó, Zoltán dirty.ice...@gmail.com writes: This patch adds an -audiodev command line option, and deprecates the QEMU_* environment variables for audio backend configuration. It's syntax is similar to existing options (-netdev, -device, etc): -audiodev driver_name,property=value,... Sounds really good. Please wrap your commit message lines a bit earlier, around column 70. Audio drivers now get an Audiodev * as config paramters, instead of the global audio_option structs. There is some code in audio/audio_legacy.c that converts the old environment variables to audiodev options (this way backends do not have to worry about legacy options, also print out them with -audio-help, to ease migrating to -audiodev). The parenthesis isn't as clear as the rest of your message, probably because it deals with two separate things. Suggest to move out the bit about help into its own paragraph. Although now it's possible to specify multiple -audiodev options on command line, multiple audio backends are not supported yet. What happens when I specify multiple -audiodev? You get an error and qemu terminates. Unlikely to create backward compatibility trouble. Works for me. How should the command line look like when multiple audio backends are supported? There's an id property of audiodev, so you can identify them: -audiodev alsa,id=foo,... -audiodev pa,id=bar,... and audio devices should get an extra parameter, like audiodev or something like that: -device usb-audio,audiodev=foo -device usb-audio,audiodev=bar And you have two cards, one connected to the alsa device and the other connected to pulseaudio. Good, because it's consistent with how we connect other kinds of frontends/backends. Multiple audio frontends (device models) can connect to the same audio backend, can't they? Yes. (It's mandatory, since currently all audio frontends connect to a single backend.) Is backend property id mandatory? Hmm, judging from PATCH 1 it isn't. It generally is for other kinds of backends, e.g. -netdev, -chardev and (in the future) -blockdev. It's optional with -drive only because -drive is crazy. It's optional right now (because I thought specifying an id when you have a single backend is pretty pointless), but it's probably better then if I change it to mandatory. Do we have a clear backward-compatible path from here to there? Currently if you specify an -audiodev option, the environment variables are completely ignored, and it will create an audio backend using the specified options. If you do not provide an -audiodev, it will initialize the audio subsystem using the old environment variables when you add the first sound card (so no -audiodev and no sound device means no audio subsystem, just like the old times). Should we document this? Where? Maybe adding a phrase to -audiodev documentation like If you specify this option, the deprecated environment variables will be ignored. About multiple backends: if the user does not specify the id of the backend when creating the sound card, just use the first -audiodev specified on the command line (or the legacy config, if there's no -audiodev). This way we stay backward-compatible (there won't be multiple -audiodevs in legacy configs). Old way (before your patch): there is only one audio backend, and it's configuration comes from a bunch of environment variables. New way (we're not there yet): you can have multiple audio backends, and you connect frontends to backends using backend ID as usual, i.e. id=ID on the backend, audiodev=ID on the frontend. Required backward compatibility: the old way still works, i.e. when there's no new-way backend, and no frontend has an audiodev=..., then we create a backend configured from the environment. Anything beyond required backward compatibility should be carefully judged on its UI merits. If I understand your description correctly, the plan is to default a frontend's audiodev to the first backend, and if there is none, create one configured from the environment. That's definitely beyond required. Is it a good user interface? The create one configured from the environment is needed for backward compatibility. Specifying an audiodev=... on frontend makes no sense without an -audiodev, so that's not allowed. The only question is what happens with an -audiodev, but no audiodev= on the frontend. We can't make audiodev= required because that would break compatibility. So we either a) make audiodev= required but only when there's an -audiodev, or b) try to find a sensible default when audiodev= is not specified. Imho b is better, because having a parameter that's sometimes required, sometimes forbidden is a bit confusing.
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
2015-06-17 15:37 keltezéssel, Markus Armbruster írta: Kővágó Zoltán dirty.ice...@gmail.com writes: 2015-06-17 13:48 keltezéssel, Markus Armbruster írta: Kővágó Zoltán dirty.ice...@gmail.com writes: 2015-06-17 09:46 keltezéssel, Markus Armbruster írta: Copying Eric for additional QAPI schema expertise. My questions inline, pretty sure they show my ignorance. Kővágó, Zoltán dirty.ice...@gmail.com writes: [...] +## +# @AudiodevPaOptions +# +# Options of the pa (PulseAudio) audio backend. +# +# @server: #optional PulseAudio server address +# +# @sink: #optional sink device name +# +# @source: #optional source device name Who picks the defaults, QEMU or PA? PA Is there a way to explicitly ask for the PA default? Something like source=default? Not really right now. The default is a NULL pointer (pulseaudio api wise), so unless we add an arbitrary keyword (like default), it's not possible to ask explicitly for the default. (But omitting them will choose the default, of course.) Treating an empty string like NULL should get us a way to ask for the default, and a way to document the default concisely, like (default '') plus a suitable explanation what '' means. I'm not saying you should do that. I'm saying whatever you do, document what happens when an optional parameter is absent :) +# +# Since: 2.4 +## +{ 'struct': 'AudiodevPaOptions', + 'data': { +'*server': 'str', +'*sink': 'str', +'*source': 'str' } } + +## +# @AudiodevWavOptions +# +# Options of the wav audio backend. +# +# @path: #optional path of the wav file to record +# +# Since: 2.4 +## +{ 'struct': 'AudiodevWavOptions', + 'data': { +'*path': 'str' } } Who picks the default? It defaults to qemu.wav Make it # @path: #optional path of the wav file to record (default 'qemu.wav') + + +## +# @AudiodevBackendOptions +# +# A discriminated record of audio backends. +# +# Since: 2.4 +## +{ 'union': 'AudiodevBackendOptions', + 'data': { +'none': 'AudiodevNoOptions', +'alsa': 'AudiodevAlsaOptions', +'coreaudio': 'AudiodevNoOptions', +'dsound':'AudiodevDsoundOptions', +'oss': 'AudiodevOssOptions', +'pa':'AudiodevPaOptions', +'sdl': 'AudiodevNoOptions', +'spice': 'AudiodevNoOptions', +'wav': 'AudiodevWavOptions' } } + +## +# @AudioFormat +# +# An enumeration of possible audio formats. +# +# Since: 2.4 +## +{ 'enum': 'AudioFormat', + 'data': [ 'u8', 's8', 'u16', 's16', 'u32', 's32' ] } + +## +# @AudiodevPerDirectionOptions +# +# General audio backend options that are used for both playback and recording. +# +# @fixed-settings: #optional use fixed settings for host DAC/ADC +# +# @frequency: #optional frequency to use when using fixed settings +# +# @channels: #optional number of channels when using fixed settings +# +# @format: #optional sample format to use when using fixed settings Are these guys used when @fixed-settings is off? No. If @fixed-settings, are the other three all required? If not, what are their defaults? No, they all have defaults: 44100 Hz, 2 channels and s16 format. Okay, this sort of explains why you have @fixed-settings. My first thought was that @fixed-settings is redundant, because we can have any of @frequency, @channels, @format imply fixed settings. Except that doesn't let you ask for the *default* fixed settings, as you have to specify at least one. What's the default for @fixed-settings? It's on by default. What if I specify frequency, channels or format together with explicit fixed-settings: false? They will be ignored. The audio system currently work like this: when an audio frontend wants to open an output with some format (frequency, channels, format) it checks fixed-settings. If it's false, it will just open the stream with the frontend specified settings. If it's true, it'll convert it into the format specified by @frequency, @channels, @format, then pass this converted/recoded stream to the backend. I guess I should also document it... Yes, please. +# +# @buffer: #optional the buffer size (in microseconds) @buffer suggests this is a buffer, not a buffer length given as time span. @buffer-len? Ok. (It used to be called buffer-usecs before I changed everything to microseconds.) +# +# @buffer-count: #optional number of buffers +# +# Since: 2.4 +## +{ 'struct': 'AudiodevPerDirectionOptions', + 'data': { +'*fixed-settings': 'bool', +'*frequency': 'int', +'*channels': 'int', +'*voices': 'int', +'*format': 'AudioFormat', +'*buffer': 'int', +'*buffer-count': 'int' } } [...]
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
2015-06-17 15:41 keltezéssel, Markus Armbruster írta: Kővágó Zoltán dirty.ice...@gmail.com writes: 2015-06-17 13:18 keltezéssel, Markus Armbruster írta: Copying Kevin because similar issues exist in the block layer. Gerd Hoffmann kra...@redhat.com writes: On Mi, 2015-06-17 at 09:50 +0200, Markus Armbruster wrote: Copying László because his fingerprints are on OptsVisitor. Kővágó, Zoltán dirty.ice...@gmail.com writes: The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like `in' and `out' in `Audiodev'), the current visitor can't cope with them (for example setting frequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified). This patch fixes it, by the following changes: 1) Specifying just the field name will apply to all fields that has the specified name (this means it would set both in's and out's frequency to 44100 in the above example). What if they have different types? What if one of them can't take the value? Currently it will error out, requiring the user to be more explicit. Probably not the best solution, but I can't really think of a better solution. (If we would ignore invalid values that would be very confusing imho.) Yes, we clearly don't want foo=0 to set a.foo and b.foo, but foo=x set only a.foo, because the former can take any string, but the latter only a number. Can we require the LHS to be unambiguous? Originally I designed it that way because it allows you to specify frequency=44100 and set both in.frequency and out.frequency. But this could also be the convenience feature that we not really need. I don't see any other downside of making it unambigous.
Re: [Qemu-devel] [RFC PATCH] qapi for audio backends
2015-06-04 09:43 keltezéssel, Gerd Hoffmann írta: +# +# @mmap: #optional try using memory mapped access IIRC this doesn't work everywhere, especially when the oss api is implemented as library. Linux had that, but on linux everybody uses alsa these days ... Dunno about other platforms. idk, the code tries to mmap first, and if it fails, falls back to non mmapped access. But something is broken there, as with QEMU_OSS_MMAP=1 it fails (on linux with alsa oss emulation with pulseaudio alsa emulation...). But it ought to work on linux, according to the comments. Maybe it needs the native oss, and not the alsa emulation. +# @exclusive: #optional open device in exclusive mode (vmix wont work) +# @dsp_policy: #optional set the timing policy of the device, -1 to use fragment +# mode (option ignored on some platforms) Would be interesting to know on which platforms this actually has an effect (both options) ... From a quick google it looks like whatever platform that have oss4 (the dsp_policy). exclusive just adds O_EXCL to open flags. IIRC 'vmix' was a feature of the commercial, ossaudio driver package.
[Qemu-devel] [RFC PATCH v2] qapi for audio backends
Changes from v1: * fixed style issues * moved definitions into a separate file * documented undocumented options (hopefully) * removed plive option. It was useless even years ago so it can probably safely go away: https://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg02427.html * removed verbose, debug options. Backends should use trace events instead. * removed *_retries options from dsound. It's a kludge. * moved buffer_usecs and buffer_count to the global config options. Some driver might ignore it (as they do not expose API to change them). * wav backend: removed frequecy, format, channels as AudiodevPerDirectionOptions already have them. Not sure about this one, so it's not yet in this patch: * remove poll_mode: another obscure setting, and it's only matter of time until the code bitrots enough to break it. This is a proposal to add structures into qapi to replace the existing configuration structures used by audio backends currently. I'm going to use it to implement a new way to specify audio backend options (an -audiodev command line option, instead of environment variables. This will also allow us to use multiple audio backends in one qemu instance), so the structure used here will be the basis of the command line syntax. This is currently more or less a direct translation of the current audio backend options. I've changed some names, trying to accomplish a more consistent naming scheme. I wouldn't be surprised if there were options that doesn't work if you set their value to anything other than the default (for example, log to monitor can crash qemu, QEMU_DSOUND_RESTOURE_RETRIES has a typo, so probably nobody used it, etc). I've also tried to reduce copy-paste, when the same set of options can be given to output and input (QEMU_*_DAC_* and QEMU_*_ADC_* options), also using in and out instead of ADC and DAC, as in the world of SPDIF and HDMI it's completely possible that your computer has nothing to do with analog converters. Plus a non technician user probably has no idea what ADC and DAC stands for. Any comment is appreciated. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- qapi-schema.json | 3 + qapi/audio.json | 225 +++ 2 files changed, 228 insertions(+) create mode 100644 qapi/audio.json diff --git a/qapi-schema.json b/qapi-schema.json index 0662a9b..ebec127 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -5,6 +5,9 @@ # QAPI common definitions { 'include': 'qapi/common.json' } +# QAPI audio definitions +{ 'include': 'qapi/audio.json' } + # QAPI block definitions { 'include': 'qapi/block.json' } diff --git a/qapi/audio.json b/qapi/audio.json new file mode 100644 index 000..c864a77 --- /dev/null +++ b/qapi/audio.json @@ -0,0 +1,225 @@ +# -*- mode: python -*- + +## +# @AudiodevNoneOptions +# +# The none, coreaudio, sdl and spice audio backend has no options. +# +# Since: 2.4 +## +{ 'struct': 'AudiodevNoneOptions', + 'data': { } } + +## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to use +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'data': { +'*dev':'str' } } + +## +# @AudiodevAlsaOptions +# +# Options of the alsa audio backend. +# +# @in: #optional options of the capture stream +# +# @out: #optional options of the playback stream +# +# @threshold: #optional set the threshold (in frames) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { +'*in': 'AudiodevAlsaPerDirectionOptions', +'*out': 'AudiodevAlsaPerDirectionOptions', +'*threshold': 'int' } } + +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @set-primary: #optional set the parameters of primary buffer +# +# @latency-millis: #optional add extra latency to playback +# +# @primary-frequency: #optional primary buffer frequency +# +# @primary-channels: #optional primary buffer number of channels +# +# @primary-format: #optional primary buffer format +# +# Since: 2.4 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { +'*set-primary': 'bool', +'*latency-millis':'int', +'*primary-frequency': 'int', +'*primary-channels': 'int', +'*primary-format':'AudioFormat' } } + +## +# @AudiodevOssPerDirectionOptions +# +# Options of the oss backend that are used for both playback and recording. +# +# @dev: #optional path of the oss device +# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssPerDirectionOptions', + 'data': { +'*dev': 'str' } } + +## +# @AudiodevOssOptions +# +# Options of the oss audio backend. +# +# @in: #optional options of the capture stream +# +# @out: #optional options of the playback stream +# +# @mmap: #optional try using memory mapped access +# +# @exclusive: #optional open device in exclusive mode (vmix wont work) +# +# @dsp-policy: #optional
[Qemu-devel] [PATCH 05/12] audio: expose drv_opaque to init_out and init_in
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 dirty.ice...@gmail.com --- audio/alsaaudio.c | 9 +++-- audio/audio_int.h | 4 ++-- audio/audio_template.h | 2 +- audio/coreaudio.c | 5 - audio/dsound_template.h | 6 -- audio/noaudio.c | 6 -- audio/ossaudio.c| 9 +++-- audio/paaudio.c | 9 +++-- audio/spiceaudio.c | 9 +++-- audio/wavaudio.c| 4 +++- 10 files changed, 46 insertions(+), 17 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 74ead97..eb33bff 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -819,7 +819,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; @@ -827,6 +828,8 @@ static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as) snd_pcm_t *handle; struct audsettings obt_as; +(void) drv_opaque; + req.fmt = aud_to_alsafmt (as-fmt, as-endianness); req.freq = as-freq; req.nchannels = as-nchannels; @@ -928,7 +931,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; @@ -936,6 +939,8 @@ static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as) snd_pcm_t *handle; struct audsettings obt_as; +(void) drv_opaque; + req.fmt = aud_to_alsafmt (as-fmt, as-endianness); req.freq = as-freq; req.nchannels = as-nchannels; diff --git a/audio/audio_int.h b/audio/audio_int.h index 92a2f3c..a3efe7b 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 584e536..f716d97 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 5964c62..f38fd82 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; @@ -296,6 +297,8 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as) const char *typ = playback; AudioValueRange frameRange; +(void) drv_opaque; + /* create mutex */ err = pthread_mutex_init(core-mutex, NULL); if (err) { diff --git a/audio/dsound_template.h b/audio/dsound_template.h index 8b37d16..98276fb 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 cb38662..dd1a87a 100644 --- a/audio/noaudio.c +++ b/audio
[Qemu-devel] [PATCH 01/12] audio: remove esd backend
ESD is no longer developed and replaced by PulseAudio. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 26a0ac9..5573ac1 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 fd019a0..9dd6b7f 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 eea9cce..000 --- a/audio/esdaudio.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * QEMU ESD audio driver - * - * Copyright (c) 2006 Frederick Reeve (brushed up by malc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the Software), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include esd.h -#include qemu-common.h -#include audio.h - -#define AUDIO_CAP esd -#include audio_int.h -#include audio_pt_int.h - -typedef struct { -HWVoiceOut hw; -int done; -int live; -int decr; -int rpos; -void *pcm_buf; -int fd; -struct audio_pt pt; -} ESDVoiceOut; - -typedef struct { -HWVoiceIn hw; -int done; -int dead; -int incr; -int wpos; -void *pcm_buf; -int fd; -struct audio_pt pt; -} ESDVoiceIn; - -static struct { -int samples; -int divisor; -char *dac_host; -char *adc_host; -} conf = { -.samples = 1024, -.divisor = 2, -}; - -static void GCC_FMT_ATTR (2, 3) qesd_logerr (int err, const char *fmt, ...) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, strerror (err)); -} - -/* playback */ -static void *qesd_thread_out (void *arg) -{ -ESDVoiceOut *esd = arg; -HWVoiceOut *hw = esd-hw; -int threshold; - -threshold = conf.divisor ? hw-samples / conf.divisor : 0; - -if (audio_pt_lock (esd-pt, AUDIO_FUNC)) { -return NULL; -} - -for (;;) { -int decr, to_mix, rpos; - -for (;;) { -if (esd-done) { -goto exit; -} - -if (esd-live threshold) { -break; -} - -if (audio_pt_wait (esd-pt, AUDIO_FUNC)) { -goto exit; -} -} - -decr = to_mix = esd-live; -rpos = hw-rpos; - -if (audio_pt_unlock (esd-pt, AUDIO_FUNC)) { -return NULL; -} - -while (to_mix) { -ssize_t written; -int chunk = audio_MIN (to_mix, hw-samples - rpos); -struct st_sample *src = hw-mix_buf + rpos; - -hw-clip (esd-pcm_buf, src, chunk); - -again: -written = write (esd-fd, esd-pcm_buf, chunk hw-info.shift); -if (written == -1) { -if (errno == EINTR || errno == EAGAIN) { -goto again; -} -qesd_logerr (errno, write failed\n); -return NULL; -} - -if (written != chunk
[Qemu-devel] [PATCH 03/12] audio: remove sdl backend
It's broken and we have native drivers for almost all platforms. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/Makefile.objs | 3 - audio/audio_int.h | 1 - audio/sdlaudio.c| 458 configure | 24 ++- 4 files changed, 11 insertions(+), 475 deletions(-) delete mode 100644 audio/sdlaudio.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index b4c0608..3c84972 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -1,5 +1,4 @@ common-obj-y = audio.o noaudio.o wavaudio.o mixeng.o -common-obj-$(CONFIG_SDL) += sdlaudio.o common-obj-$(CONFIG_OSS) += ossaudio.o common-obj-$(CONFIG_SPICE) += spiceaudio.o common-obj-$(CONFIG_COREAUDIO) += coreaudio.o @@ -10,5 +9,3 @@ 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 - -sdlaudio.o-cflags := $(SDL_CFLAGS) diff --git a/audio/audio_int.h b/audio/audio_int.h index 7445602..d593879 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -204,7 +204,6 @@ struct AudioState { 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 alsa_audio_driver; extern struct audio_driver coreaudio_audio_driver; diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c deleted file mode 100644 index d24daa5..000 --- a/audio/sdlaudio.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * QEMU SDL 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 SDL.h -#include SDL_thread.h -#include qemu-common.h -#include audio.h - -#ifndef _WIN32 -#ifdef __sun__ -#define _POSIX_PTHREAD_SEMANTICS 1 -#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) -#include pthread.h -#endif -#endif - -#define AUDIO_CAP sdl -#include audio_int.h - -typedef struct SDLVoiceOut { -HWVoiceOut hw; -int live; -int rpos; -int decr; -} SDLVoiceOut; - -static struct { -int nb_samples; -} conf = { -.nb_samples = 1024 -}; - -static struct SDLAudioState { -int exit; -SDL_mutex *mutex; -SDL_sem *sem; -int initialized; -} glob_sdl; -typedef struct SDLAudioState SDLAudioState; - -static void GCC_FMT_ATTR (1, 2) sdl_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, SDL_GetError ()); -} - -static int sdl_lock (SDLAudioState *s, const char *forfn) -{ -if (SDL_LockMutex (s-mutex)) { -sdl_logerr (SDL_LockMutex for %s failed\n, forfn); -return -1; -} -return 0; -} - -static int sdl_unlock (SDLAudioState *s, const char *forfn) -{ -if (SDL_UnlockMutex (s-mutex)) { -sdl_logerr (SDL_UnlockMutex for %s failed\n, forfn); -return -1; -} -return 0; -} - -static int sdl_post (SDLAudioState *s, const char *forfn) -{ -if (SDL_SemPost (s-sem)) { -sdl_logerr (SDL_SemPost for %s failed\n, forfn); -return -1; -} -return 0; -} - -static int sdl_wait (SDLAudioState *s, const char *forfn) -{ -if (SDL_SemWait (s-sem)) { -sdl_logerr (SDL_SemWait for %s failed\n, forfn); -return -1; -} -return 0; -} - -static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn) -{ -if (sdl_unlock (s, forfn)) { -return -1; -} - -return sdl_post (s, forfn); -} - -static int aud_to_sdlfmt (audfmt_e fmt) -{ -switch (fmt) { -case AUD_FMT_S8: -return AUDIO_S8; - -case AUD_FMT_U8: -return AUDIO_U8; - -case AUD_FMT_S16: -return AUDIO_S16LSB; - -case AUD_FMT_U16: -return AUDIO_U16LSB; - -default: -dolog (Internal
[Qemu-devel] [PATCH 09/12] wavaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/wavaudio.c | 37 + 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 5132aed..8acea8f 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; (void) as; (void) drv_opaque; @@ -157,10 +153,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; @@ -228,40 +224,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 */ } -- 2.4.2
[Qemu-devel] [PATCH 02/12] audio: remove fmod backend
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 5573ac1..b4c0608 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 9dd6b7f..7445602 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 fabf84d..000 --- a/audio/fmodaudio.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * QEMU FMOD audio driver - * - * Copyright (c) 2004-2005 Vassili Karpov (malc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the Software), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include fmod.h -#include fmod_errors.h -#include qemu-common.h -#include audio.h - -#define AUDIO_CAP fmod -#include audio_int.h - -typedef struct FMODVoiceOut { -HWVoiceOut hw; -unsigned int old_pos; -FSOUND_SAMPLE *fmod_sample; -int channel; -} FMODVoiceOut; - -typedef struct FMODVoiceIn { -HWVoiceIn hw; -FSOUND_SAMPLE *fmod_sample; -} FMODVoiceIn; - -static struct { -const char *drvname; -int nb_samples; -int freq; -int nb_channels; -int bufsize; -int broken_adc; -} conf = { -.nb_samples = 2048 * 2, -.freq= 44100, -.nb_channels = 2, -}; - -static void GCC_FMT_ATTR (1, 2) fmod_logerr (const char *fmt, ...) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, - FMOD_ErrorString (FSOUND_GetError ())); -} - -static void GCC_FMT_ATTR (2, 3) fmod_logerr2 ( -const char *typ, -const char *fmt, -... -) -{ -va_list ap; - -AUD_log (AUDIO_CAP, Could not initialize %s\n, typ); - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (AUDIO_CAP, Reason: %s\n, - FMOD_ErrorString (FSOUND_GetError ())); -} - -static int fmod_write (SWVoiceOut *sw, void *buf, int len) -{ -return audio_pcm_sw_write (sw, buf, len); -} - -static void fmod_clear_sample (FMODVoiceOut *fmd) -{ -HWVoiceOut *hw = fmd-hw; -int status; -void *p1 = 0, *p2 = 0; -unsigned int len1 = 0, len2 = 0; - -status = FSOUND_Sample_Lock ( -fmd-fmod_sample, -0, -hw-samples hw-info.shift, -p1, -p2, -len1, -len2 -); - -if (!status) { -fmod_logerr (Failed to lock sample\n); -return; -} - -if ((len1 hw-info.align) || (len2 hw-info.align)) { -dolog (Lock returned misaligned length %d, %d, alignment %d\n, - len1, len2, hw-info.align + 1); -goto fail; -} - -if ((len1 + len2) - (hw-samples hw-info.shift)) { -dolog (Lock returned
Re: [Qemu-devel] [PATCH 00/12] Audio backend cleanup
2015-06-01 15:38 keltezéssel, Michael Tokarev írta: 01.06.2015 16:23, Kővágó, Zoltán wrote: This series of patch removes the following audio backends: esd, fmod, sdl, winwave. Why do you remove sdl backend? This is my preferred backend so far, it works better than all other backends available to me... I'm removing it because it's broken (see http://lists.nongnu.org/archive/html/qemu-devel/2015-05/msg02198.html for an example), and nobody had an objection about removing sdl when I asked it on the list about a week ago (http://lists.nongnu.org/archive/html/qemu-devel/2015-05/msg04116.html). Thanks, Zoltan
[Qemu-devel] [PATCH 00/12] Audio backend cleanup
This series of patch removes the following audio backends: esd, fmod, sdl, winwave. It also cleans up the remaining drivers to do not use global variables where possible. This is a preparation for my GSoC project where I will enable multiple simultaneous audio backends. Please also test the coreaudio backend, as I do not have a Mac to test it. Patches are also available at https://github.com/DirtYiCE/qemu.git in branch audio-cleanup to simplify testing. Please review. Kővágó, Zoltán (12): audio: remove esd backend audio: remove fmod backend audio: remove sdl backend audio: remove winwave audio driver audio: expose drv_opaque to init_out and init_in alsaaudio: do not use global variables paaudio: do not use global variables ossaudio: do not use global variables wavaudio: do not use global variables dsoundaudio: do not use global variables paaudio: fix possible resource leak coreaudio: do not use global variables where possible audio/Makefile.objs | 7 - audio/alsaaudio.c | 155 ++- audio/audio_int.h | 8 +- audio/audio_template.h | 2 +- audio/coreaudio.c | 46 ++-- audio/dsound_template.h | 24 +- audio/dsoundaudio.c | 106 --- audio/esdaudio.c| 557 - audio/fmodaudio.c | 685 - audio/noaudio.c | 6 +- audio/ossaudio.c| 115 audio/paaudio.c | 105 +++ audio/sdlaudio.c| 458 --- audio/spiceaudio.c | 9 +- audio/wavaudio.c| 41 +-- audio/winwaveaudio.c| 717 configure | 60 +--- 17 files changed, 360 insertions(+), 2741 deletions(-) delete mode 100644 audio/esdaudio.c delete mode 100644 audio/fmodaudio.c delete mode 100644 audio/sdlaudio.c delete mode 100644 audio/winwaveaudio.c -- 2.4.2
[Qemu-devel] [PATCH 12/12] coreaudio: do not use global variables where possible
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/coreaudio.c | 45 - 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index f38fd82..6dfd63e 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,8 +292,7 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, int err; const char *typ = playback; AudioValueRange frameRange; - -(void) drv_opaque; +CoreaudioConf *conf = drv_opaque; /* create mutex */ err = pthread_mutex_init(core-mutex, NULL); @@ -339,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 */ @@ -382,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); @@ -446,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); @@ -489,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) { @@ -502,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 */ } -- 2.4.2
[Qemu-devel] [PATCH 10/12] dsoundaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- 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 98276fb..85ba858 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 e2d89fd..c8b09e2 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
[Qemu-devel] [PATCH 08/12] ossaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/ossaudio.c | 114 +-- 1 file changed, 61 insertions(+), 53 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 80ac610..d247969 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 = 0x04) { -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 av1...@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,18 +514,17 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, int fd; audfmt_e effective_fmt; struct audsettings obt_as; - -(void) drv_opaque; +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; } @@ -558,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
[Qemu-devel] [PATCH 04/12] audio: remove winwave audio driver
DirectSound should be a superior choice on Windows. Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/Makefile.objs | 1 - audio/audio_int.h| 1 - audio/winwaveaudio.c | 717 --- configure| 11 +- 4 files changed, 2 insertions(+), 728 deletions(-) delete mode 100644 audio/winwaveaudio.c diff --git a/audio/Makefile.objs b/audio/Makefile.objs index 3c84972..89b61e1 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -5,7 +5,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 d593879..92a2f3c 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -210,7 +210,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 8dbd145..000 --- a/audio/winwaveaudio.c +++ /dev/null @@ -1,717 +0,0 @@ -/* public domain */ - -#include qemu-common.h -#include sysemu/sysemu.h -#include audio.h - -#define AUDIO_CAP winwave -#include audio_int.h - -#include windows.h -#include mmsystem.h - -#include audio_win_int.h - -static struct { -int dac_headers; -int dac_samples; -int adc_headers; -int adc_samples; -} conf = { -.dac_headers = 4, -.dac_samples = 1024, -.adc_headers = 4, -.adc_samples = 1024 -}; - -typedef struct { -HWVoiceOut hw; -HWAVEOUT hwo; -WAVEHDR *hdrs; -HANDLE event; -void *pcm_buf; -int avail; -int pending; -int curhdr; -int paused; -CRITICAL_SECTION crit_sect; -} WaveVoiceOut; - -typedef struct { -HWVoiceIn hw; -HWAVEIN hwi; -WAVEHDR *hdrs; -HANDLE event; -void *pcm_buf; -int curhdr; -int paused; -int rpos; -int avail; -CRITICAL_SECTION crit_sect; -} WaveVoiceIn; - -static void winwave_log_mmresult (MMRESULT mr) -{ -const char *str = BUG; - -switch (mr) { -case MMSYSERR_NOERROR: -str = Success; -break; - -case MMSYSERR_INVALHANDLE: -str = Specified device handle is invalid; -break; - -case MMSYSERR_BADDEVICEID: -str = Specified device id is out of range; -break; - -case MMSYSERR_NODRIVER: -str = No device driver is present; -break; - -case MMSYSERR_NOMEM: -str = Unable to allocate or lock memory; -break; - -case WAVERR_SYNC: -str = Device is synchronous but waveOutOpen was called -without using the WINWAVE_ALLOWSYNC flag; -break; - -case WAVERR_UNPREPARED: -str = The data block pointed to by the pwh parameter -hasn't been prepared; -break; - -case WAVERR_STILLPLAYING: -str = There are still buffers in the queue; -break; - -default: -dolog (Reason: Unknown (MMRESULT %#x)\n, mr); -return; -} - -dolog (Reason: %s\n, str); -} - -static void GCC_FMT_ATTR (2, 3) winwave_logerr ( -MMRESULT mr, -const char *fmt, -... -) -{ -va_list ap; - -va_start (ap, fmt); -AUD_vlog (AUDIO_CAP, fmt, ap); -va_end (ap); - -AUD_log (NULL, failed\n); -winwave_log_mmresult (mr); -} - -static void winwave_anal_close_out (WaveVoiceOut *wave) -{ -MMRESULT mr; - -mr = waveOutClose (wave-hwo); -if (mr != MMSYSERR_NOERROR) { -winwave_logerr (mr, waveOutClose); -} -wave-hwo = NULL; -} - -static void CALLBACK winwave_callback_out ( -HWAVEOUT hwo, -UINT msg, -DWORD_PTR dwInstance, -DWORD_PTR dwParam1, -DWORD_PTR dwParam2 -) -{ -WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance; - -switch (msg) { -case WOM_DONE: -{ -WAVEHDR *h = (WAVEHDR *) dwParam1; -if (!h-dwUser) { -h-dwUser = 1; -EnterCriticalSection (wave-crit_sect); -{ -wave-avail += conf.dac_samples; -} -LeaveCriticalSection (wave-crit_sect); -if (wave-hw.poll_mode) { -if (!SetEvent (wave-event)) { -dolog (DAC SetEvent failed %lx\n, GetLastError ()); -} -} -} -} -break; - -case WOM_CLOSE: -case WOM_OPEN: -break; - -default
[Qemu-devel] [PATCH 11/12] paaudio: fix possible resource leak
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 dirty.ice...@gmail.com --- audio/paaudio.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index 35e8887..fea6071 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; } -- 2.4.2
[Qemu-devel] [PATCH 06/12] alsaaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/alsaaudio.c | 154 +- 1 file changed, 82 insertions(+), 72 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index eb33bff..d7e181b 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) { @@ -270,13 +268,13 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask) NULL, hlp); } if (pfds[i].events POLLOUT) { -if (conf.verbose) { +if (conf-verbose) { dolog (POLLOUT %d %d\n, i, pfds[i].fd); } err = 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); } @@ -476,14 +474,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; @@ -522,7 +521,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); } @@ -654,7 +653,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; @@ -676,7 +675,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); } @@ -686,7 +685,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
[Qemu-devel] [PATCH 07/12] paaudio: do not use global variables
Signed-off-by: Kővágó, Zoltán dirty.ice...@gmail.com --- audio/paaudio.c | 102 +--- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index 11c2d29..35e8887 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -9,6 +9,19 @@ #include audio_pt_int.h typedef struct { +int samples; +char *server; +char *sink; +char *source; +} PAConf; + +typedef struct { +PAConf conf; +pa_threaded_mainloop *mainloop; +pa_context *context; +} paaudio; + +typedef struct { HWVoiceOut hw; int done; int live; @@ -17,6 +30,7 @@ typedef struct { pa_stream *stream; void *pcm_buf; struct audio_pt pt; +paaudio *g; } PAVoiceOut; typedef struct { @@ -30,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,12 +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; - -(void) drv_opaque; +paaudio *g = pa-g = drv_opaque; ss.format = audfmt_to_pa (as-fmt, as-endianness); ss.channels = as-nchannels; @@ -561,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 */ @@ -577,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) { @@ -607,11 +605,10 @@ static int qpa_init_out(HWVoiceOut *hw, struct