-audiodev option
v2 cover -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
Signature · 1 line
2.4.3
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)
---
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
Makefile +2 -2
@@ -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)
qapi-schema.json +3 -0
@@ -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' }
qapi/audio.json new file +223 -0
223 lines not on this page · raw message
Signature · 1 line
2.4.3
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
Copying Eric for additional QAPI schema expertise.
My questions inline, pretty sure they show my ignorance.
Quoted 102 lines · Zoltán
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:
* useinandoutinstead ofADCandDAC, 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 <[email protected]>---
Changes from v1 patch:
* every time-related field now take usecs (and removed -usecs, -millis suffixes)
* fixed inconsisten optional marking, language issuesChanges 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 fieldsChanges 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*_retriesoptions from dsound. It's a kludge.
* movedbuffer_usecsandbuffer_countto 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.jsonMakefile +2
-2@@ -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)qapi-schema.json +3
-0@@ -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' }qapi/audio.json new file +13
-0@@ -0,0 +1,223 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó <[email protected]> +# +# 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
qapi/audio.json line 23
Quoted 10 lines
qapi/audio.json new file +10
-0+## +{ '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?
qapi/audio.json line 25
Quoted 2 lines
qapi/audio.json new file +2
-0+# +# @try-poll: #optional attempt to use poll mode
What happens when the attempt fails?
Quoted 16 lines
qapi/audio.json new file +16
-0+# +# 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
qapi/audio.json line 51
Quoted 10 lines
qapi/audio.json new file +10
-0+# +# @threshold: #optional set the threshold (in frames) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { + 'in': 'AudiodevAlsaPerDirectionOptions', + 'out': 'AudiodevAlsaPerDirectionOptions', + '*threshold': 'int' } }
Do we have an established term for a "direction"?
If not: the use with 'in' and 'out' tempts me to name the type AudiodevAlsaIOOptions.
Just rambling, use what you think is best.
qapi/audio.json line 58
Quoted 7 lines
qapi/audio.json new file +7
-0+ +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @latency: #optional add extra latency to playback (in microseconds)
We already use seconds, milliseconds and nanoseconds. You make the zoo complete.
qapi/audio.json line 71
Quoted 13 lines
qapi/audio.json new file +13
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { + '*latency': 'int' } } + +## +# @AudiodevOssPerDirectionOptions +# +# Options of the oss backend that are used for both playback and recording. +# +# @dev: #optional path of the oss device
Who picks the default, QEMU or OSS?
For ALSA, you documented @dev to be "the name", here it's "path". Intentional difference?
qapi/audio.json line 80
Quoted 9 lines
qapi/audio.json new file +9
-0+# +# @try-poll: #optional attempt to use poll mode +# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssPerDirectionOptions', + 'data': { + '*dev': 'str', + '*try-poll': 'bool' } }
Same as for ALSA. Keeping them separate is fine with me.
qapi/audio.json line 91
Quoted 11 lines
qapi/audio.json new file +11
-0+ +## +# @AudiodevOssOptions +# +# Options of the oss audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @mmap: #optional try using memory mapped access
What happens when the attempt fails?
Should this be called try-mmap?
qapi/audio.json line 96
Quoted 5 lines
qapi/audio.json new file +5
-0+# +# @exclusive: #optional open device in exclusive mode (vmix won't work) +# +# @dsp-policy: #optional set the timing policy of the device, -1 to use fragment +# mode (option ignored on some platforms)
What are the possible values besides -1?
Quoted 11 lines
qapi/audio.json new file +11
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssOptions', + 'data': { + 'in': 'AudiodevOssPerDirectionOptions', + 'out': 'AudiodevOssPerDirectionOptions', + '*mmap': 'bool', + '*exclusive': 'bool', + '*dsp-policy': 'int' } } +
qapi/audio.json line 117
Quoted 10 lines
qapi/audio.json new file +10
-0+## +# @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?
Quoted 11 lines
qapi/audio.json new file +11
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevPaOptions', + 'data': { + '*server': 'str', + '*sink': 'str', + '*source': 'str' } } + +## +# @AudiodevWavOptions
qapi/audio.json line 138
Quoted 10 lines
qapi/audio.json new file +10
-0+# +# 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?
Quoted 33 lines
qapi/audio.json new file +33
-0+ + +## +# @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
qapi/audio.json line 181
Quoted 10 lines
qapi/audio.json new file +10
-0+# +# 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?
qapi/audio.json line 183
Quoted 2 lines
qapi/audio.json new file +2
-0+# +# @buffer: #optional the buffer size (in microseconds)
@buffer suggests this is a buffer, not a buffer length given as time span. @buffer-len?
Quoted 30 lines
qapi/audio.json new file +30
-0+# +# @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' } } + +## +# @Audiodev +# +# Captures the configuration of an audio backend. +# +# @id: identifier of the backend +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @timer-period: #optional timer period (in microseconds, 0: use lowest +# possible) +# +# @opts: audio backend specific options
qapi/audio.json line 223
Quoted 10 lines
qapi/audio.json new file +10
-0+# +# Since: 2.4 +## +{ 'struct': 'Audiodev', + 'data': { + '*id': 'str', + 'in': 'AudiodevPerDirectionOptions', + 'out': 'AudiodevPerDirectionOptions', + '*timer-period': 'int', + 'opts': 'AudiodevBackendOptions' } }
Have you considered making this a flat union, similar ro BlockdevOptions?
Don't get deceived by the number of my questions, this is solid work.
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
Quoted 112 lines
Copying Eric for additional QAPI schema expertise.
My questions inline, pretty sure they show my ignorance.
Quoted 106 lines · Zoltán
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:
* useinandoutinstead ofADCandDAC, 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 <[email protected]>---
Changes from v1 patch:
* every time-related field now take usecs (and removed -usecs, -millis suffixes)
* fixed inconsisten optional marking, language issuesChanges 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 fieldsChanges 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*_retriesoptions from dsound. It's a kludge.
* movedbuffer_usecsandbuffer_countto 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.jsonMakefile +2
-2@@ -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)qapi-schema.json +3
-0@@ -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' }qapi/audio.json new file +17
-0@@ -0,0 +1,223 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó <[email protected]> +# +# 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': { } } +
Quoted 8 lines
qapi/audio.json line 23
Quoted 6 lines
qapi/audio.json new file +6
-0+## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to useWho picks the default, QEMU or ALSA?
It defaults to "default", which tells alsa to use the default device...
Quoted 5 lines
qapi/audio.json line 25
Quoted 3 lines
qapi/audio.json new file +2
-0+# +# @try-poll: #optional attempt to use poll modeWhat happens when the attempt fails?
It falls back to non polling (timer based) mode.
Quoted 29 lines
Quoted 16 lines
qapi/audio.json new file +16
-0+# +# 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 streamqapi/audio.json line 51
Quoted 10 lines
qapi/audio.json new file +10
-0+# +# @threshold: #optional set the threshold (in frames) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { + 'in': 'AudiodevAlsaPerDirectionOptions', + 'out': 'AudiodevAlsaPerDirectionOptions', + '*threshold': 'int' } }Do we have an established term for a "direction"?
Quoted 4 lines
If not: the use with 'in' and 'out' tempts me to name the type AudiodevAlsaIOOptions.
Just rambling, use what you think is best.
I don't know, so far nobody rambled about my naming...
Quoted 11 lines
qapi/audio.json line 58
Quoted 8 lines
qapi/audio.json new file +7
-0+ +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @latency: #optional add extra latency to playback (in microseconds)We already use seconds, milliseconds and nanoseconds. You make the zoo complete.
Hmm. The audio backend previously used microseconds, milliseconds, Hertz, frames, samples and bytes as time measurement, now at least everything use microseconds. Milliseconds precision is not enough, while nanosecond precision doesn't really make sense imho.
Quoted 7 lines
Quoted 7 lines
qapi/audio.json new file +7
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { + '*latency': 'int' } } +
Quoted 8 lines
qapi/audio.json line 71
Quoted 6 lines
qapi/audio.json new file +6
-0+## +# @AudiodevOssPerDirectionOptions +# +# Options of the oss backend that are used for both playback and recording. +# +# @dev: #optional path of the oss deviceWho picks the default, QEMU or OSS?
It defaults to "/dev/dsp".
Quoted 2 lines
For ALSA, you documented @dev to be "the name", here it's "path". Intentional difference?
Yes. For oss you have to provide a filesystem path of the audio device (like /dev/dsp), for alsa you provide an alsa specific name, like "default", "hw:1,0", "hdmi:CARD=NVidia,DEV=1", whatever.
Quoted 11 lines
qapi/audio.json line 80
Quoted 9 lines
qapi/audio.json new file +9
-0+# +# @try-poll: #optional attempt to use poll mode +# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssPerDirectionOptions', + 'data': { + '*dev': 'str', + '*try-poll': 'bool' } }Same as for ALSA. Keeping them separate is fine with me.
This is the same as alsa's try-poll. They're separate because only these two backend use this setting.
Quoted 14 lines
qapi/audio.json line 91
Quoted 12 lines
qapi/audio.json new file +11
-0+ +## +# @AudiodevOssOptions +# +# Options of the oss audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @mmap: #optional try using memory mapped accessWhat happens when the attempt fails?
It should fall back to non-mmapped access (should because when I checked, it was buggy, at least on linux with alsa emulated oss on pulseaudio alsa device...)
Quoted 1 line
Should this be called try-mmap?
Agree.
Quoted 7 lines
qapi/audio.json line 96
Quoted 5 lines
qapi/audio.json new file +5
-0+# +# @exclusive: #optional open device in exclusive mode (vmix won't work) +# +# @dsp-policy: #optional set the timing policy of the device, -1 to use fragment +# mode (option ignored on some platforms)What are the possible values besides -1?
It should be a number between 0 and 10 (according to this page: http://manuals.opensound.com/developer/SNDCTL_DSP_POLICY.html)
Quoted 16 lines
Quoted 16 lines
qapi/audio.json new file +15
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssOptions', + 'data': { + 'in': 'AudiodevOssPerDirectionOptions', + 'out': 'AudiodevOssPerDirectionOptions', + '*mmap': 'bool', + '*exclusive': 'bool', + '*dsp-policy': 'int' } } + +## +# @AudiodevPaOptions +# +# Options of the pa (PulseAudio) audio backend.
Quoted 8 lines
qapi/audio.json line 117
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# @server: #optional PulseAudio server address +# +# @sink: #optional sink device name +# +# @source: #optional source device nameWho picks the defaults, QEMU or PA?
PA
Quoted 15 lines
Quoted 15 lines
qapi/audio.json new file +15
-0+# +# 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
Quoted 8 lines
qapi/audio.json line 138
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevWavOptions', + 'data': { + '*path': 'str' } }Who picks the default?
It defaults to "qemu.wav"
Quoted 37 lines
Quoted 37 lines
qapi/audio.json new file +37
-0+ + +## +# @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
Quoted 8 lines
qapi/audio.json line 181
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# @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 settingsAre these guys used when @fixed-settings is off?
No.
Quoted 5 lines
qapi/audio.json line 183
Quoted 2 lines
qapi/audio.json new file +2
-0+# +# @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.)
Quoted 36 lines
Quoted 36 lines
qapi/audio.json new file +35
-0+# +# @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' } } + +## +# @Audiodev +# +# Captures the configuration of an audio backend. +# +# @id: identifier of the backend +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @timer-period: #optional timer period (in microseconds, 0: use lowest +# possible) +# +# @opts: audio backend specific options +# +# Since: 2.4 +## +{ 'struct': 'Audiodev', + 'data': {
Quoted 8 lines
qapi/audio.json line 223
Quoted 5 lines
qapi/audio.json new file +5
-0+ '*id': 'str', + 'in': 'AudiodevPerDirectionOptions', + 'out': 'AudiodevPerDirectionOptions', + '*timer-period': 'int', + 'opts': 'AudiodevBackendOptions' } }Have you considered making this a flat union, similar ro BlockdevOptions?
Not really. If you qapi masters out there think it's better, then I will convert it.
Quoted 2 lines
Don't get deceived by the number of my questions, this is solid work.
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
Quoted 122 lines · Kővágó Zoltán
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
Quoted 112 lines
Copying Eric for additional QAPI schema expertise.
My questions inline, pretty sure they show my ignorance.
Quoted 106 lines · Zoltán
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:
* useinandoutinstead ofADCandDAC, 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 <[email protected]>---
Changes from v1 patch:
* every time-related field now take usecs (and removed -usecs, -millis suffixes)
* fixed inconsisten optional marking, language issuesChanges 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 fieldsChanges 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*_retriesoptions from dsound. It's a kludge.
* movedbuffer_usecsandbuffer_countto 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.jsonMakefile +2
-2@@ -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)qapi-schema.json +3
-0@@ -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' }qapi/audio.json new file +17
-0@@ -0,0 +1,223 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó <[email protected]> +# +# 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': { } } +Quoted 8 lines
qapi/audio.json line 23
Quoted 6 lines
qapi/audio.json new file +6
-0+## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to useWho picks the default, QEMU or ALSA?
Quoted 1 line
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')
Quoted 7 lines
Quoted 5 lines
qapi/audio.json line 25
Quoted 3 lines
qapi/audio.json new file +2
-0+# +# @try-poll: #optional attempt to use poll modeWhat happens when the attempt fails?
It falls back to non polling (timer based) mode.
Okay, assuming that's the user interface we want.
Quoted 48 lines
Quoted 29 lines
Quoted 16 lines
qapi/audio.json new file +16
-0+# +# 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 streamqapi/audio.json line 51
Quoted 10 lines
qapi/audio.json new file +10
-0+# +# @threshold: #optional set the threshold (in frames) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { + 'in': 'AudiodevAlsaPerDirectionOptions', + 'out': 'AudiodevAlsaPerDirectionOptions', + '*threshold': 'int' } }Do we have an established term for a "direction"?
Quoted 4 lines
If not: the use with 'in' and 'out' tempts me to name the type AudiodevAlsaIOOptions.
Just rambling, use what you think is best.
I don't know, so far nobody rambled about my naming...
Quoted 11 lines
qapi/audio.json line 58
Quoted 8 lines
qapi/audio.json new file +7
-0+ +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @latency: #optional add extra latency to playback (in microseconds)We already use seconds, milliseconds and nanoseconds. You make the zoo complete.
Quoted 4 lines
Hmm. The audio backend previously used microseconds, milliseconds, Hertz, frames, samples and bytes as time measurement, now at least everything use microseconds. Milliseconds precision is not enough, while nanosecond precision doesn't really make sense imho.
I'm just poking fun at our inability to pick a time unit for QAPI/QMP. No objection to your use of microseconds.
Quoted 16 lines
Quoted 7 lines
Quoted 7 lines
qapi/audio.json new file +7
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { + '*latency': 'int' } } +Quoted 8 lines
qapi/audio.json line 71
Quoted 6 lines
qapi/audio.json new file +6
-0+## +# @AudiodevOssPerDirectionOptions +# +# Options of the oss backend that are used for both playback and recording. +# +# @dev: #optional path of the oss deviceWho picks the default, QEMU or OSS?
Quoted 8 lines
It defaults to "
/dev/dsp".Quoted 2 lines
For ALSA, you documented @dev to be "the name", here it's "path". Intentional difference?
Yes. For oss you have to provide a filesystem path of the audio device (like
/dev/dsp), for alsa you provide an alsa specific name, like "default", "hw:1,0", "hdmi:CARD=NVidia,DEV=1", whatever.
I don't like calling a filename a path, even though we already do in many places. Let's do:
# @dev: #optional file name of the oss device (default '/dev/dsp')
Quoted 29 lines
Quoted 11 lines
qapi/audio.json line 80
Quoted 9 lines
qapi/audio.json new file +9
-0+# +# @try-poll: #optional attempt to use poll mode +# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssPerDirectionOptions', + 'data': { + '*dev': 'str', + '*try-poll': 'bool' } }Same as for ALSA. Keeping them separate is fine with me.
This is the same as alsa's try-poll. They're separate because only these two backend use this setting.
Quoted 14 lines
qapi/audio.json line 91
Quoted 12 lines
qapi/audio.json new file +11
-0+ +## +# @AudiodevOssOptions +# +# Options of the oss audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @mmap: #optional try using memory mapped accessWhat happens when the attempt fails?
Quoted 3 lines
It should fall back to non-mmapped access (should because when I checked, it was buggy, at least on linux with alsa emulated oss on pulseaudio alsa device...)
Okay, assuming that's the user interface we want.
Quoted 12 lines
Quoted 1 line
Should this be called try-mmap?
Agree.
Quoted 8 lines
Quoted 6 lines
qapi/audio.json new file +4
-0+# +# @exclusive: #optional open device in exclusive mode (vmix won't work) +# +# @dsp-policy: #optional set the timing policy of the device, -1to use fragment
+# mode (option ignored on some platforms)What are the possible values besides -1?
Quoted 2 lines
It should be a number between 0 and 10 (according to this page:
http://manuals.opensound.com/developer/SNDCTL_DSP_POLICY.html)
Please cover that in your comment.
Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
qapi/audio.json new file +15
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssOptions', + 'data': { + 'in': 'AudiodevOssPerDirectionOptions', + 'out': 'AudiodevOssPerDirectionOptions', + '*mmap': 'bool', + '*exclusive': 'bool', + '*dsp-policy': 'int' } } + +## +# @AudiodevPaOptions +# +# Options of the pa (PulseAudio) audio backend.Quoted 8 lines
qapi/audio.json line 117
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# @server: #optional PulseAudio server address +# +# @sink: #optional sink device name +# +# @source: #optional source device nameWho picks the defaults, QEMU or PA?
Quoted 1 line
PA
Is there a way to explicitly ask for the PA default? Something like source=default?
Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
qapi/audio.json new file +15
-0+# +# 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 recordQuoted 8 lines
qapi/audio.json line 138
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevWavOptions', + 'data': { + '*path': 'str' } }Who picks the default?
Quoted 1 line
It defaults to "qemu.wav"
Make it
# @path: #optional path of the wav file to record (default 'qemu.wav')
Quoted 47 lines
Quoted 38 lines
Quoted 38 lines
qapi/audio.json new file +35
-0+ + +## +# @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 playbackand recording.
qapi/audio.json new file +2
-0+# +# @fixed-settings: #optional use fixed settings for host DAC/ADCQuoted 8 lines
qapi/audio.json line 181
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# @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 settingsAre these guys used when @fixed-settings is off?
Quoted 1 line
No.
If @fixed-settings, are the other three all required? If not, what are their defaults?
Quoted 54 lines
Quoted 5 lines
qapi/audio.json line 183
Quoted 2 lines
qapi/audio.json new file +2
-0+# +# @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.)
Quoted 36 lines
Quoted 36 lines
qapi/audio.json new file +35
-0+# +# @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' } } + +## +# @Audiodev +# +# Captures the configuration of an audio backend. +# +# @id: identifier of the backend +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @timer-period: #optional timer period (in microseconds, 0: use lowest +# possible) +# +# @opts: audio backend specific options +# +# Since: 2.4 +## +{ 'struct': 'Audiodev', + 'data': {Quoted 8 lines
qapi/audio.json line 223
Quoted 5 lines
qapi/audio.json new file +5
-0+ '*id': 'str', + 'in': 'AudiodevPerDirectionOptions', + 'out': 'AudiodevPerDirectionOptions', + '*timer-period': 'int', + 'opts': 'AudiodevBackendOptions' } }Have you considered making this a flat union, similar ro BlockdevOptions?
Quoted 2 lines
Not really. If you qapi masters out there think it's better, then I will convert it.
Related: discussion about flattening in review of PATCH 2.
Quoted 2 lines
Quoted 2 lines
Don't get deceived by the number of my questions, this is solid work.
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
2015-06-17 13:48 keltezéssel, Markus Armbruster írta:
Quoted 302 lines
Quoted 122 lines · Kővágó Zoltán
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
Quoted 112 lines
Copying Eric for additional QAPI schema expertise.
My questions inline, pretty sure they show my ignorance.
Quoted 106 lines · Zoltán
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:
* useinandoutinstead ofADCandDAC, 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 <[email protected]>---
Changes from v1 patch:
* every time-related field now take usecs (and removed -usecs, -millis suffixes)
* fixed inconsisten optional marking, language issuesChanges 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 fieldsChanges 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 safelygo away: https://lists.nongnu.org/archive/html/qemu-devel/2012-03/msg02427.html* removed verbose, debug options. Backends should use trace events instead.
* removed*_retriesoptions from dsound. It's a kludge.
* movedbuffer_usecsandbuffer_countto 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.jsonMakefile +2
-2@@ -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)qapi-schema.json +3
-0@@ -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' }qapi/audio.json new file +17
-0@@ -0,0 +1,223 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015 Zoltán Kővágó <[email protected]> +# +# 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': { } } +Quoted 8 lines
qapi/audio.json line 23
Quoted 6 lines
qapi/audio.json new file +6
-0+## +# @AudiodevAlsaPerDirectionOptions +# +# Options of the alsa backend that are used for both playback and recording. +# +# @dev: #optional the name of the alsa device to useWho picks the default, QEMU or ALSA?
Quoted 1 line
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')
Quoted 7 lines
Quoted 5 lines
qapi/audio.json line 25
Quoted 3 lines
qapi/audio.json new file +2
-0+# +# @try-poll: #optional attempt to use poll modeWhat happens when the attempt fails?
It falls back to non polling (timer based) mode.
Okay, assuming that's the user interface we want.
Quoted 48 lines
Quoted 29 lines
Quoted 16 lines
qapi/audio.json new file +16
-0+# +# 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 streamqapi/audio.json line 51
Quoted 10 lines
qapi/audio.json new file +10
-0+# +# @threshold: #optional set the threshold (in frames) when playback starts +# +# Since: 2.4 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { + 'in': 'AudiodevAlsaPerDirectionOptions', + 'out': 'AudiodevAlsaPerDirectionOptions', + '*threshold': 'int' } }Do we have an established term for a "direction"?
Quoted 4 lines
If not: the use with 'in' and 'out' tempts me to name the type AudiodevAlsaIOOptions.
Just rambling, use what you think is best.
I don't know, so far nobody rambled about my naming...
Quoted 11 lines
qapi/audio.json line 58
Quoted 8 lines
qapi/audio.json new file +7
-0+ +## +# @AudiodevDsoundOptions +# +# Options of the dsound audio backend. +# +# @latency: #optional add extra latency to playback (in microseconds)We already use seconds, milliseconds and nanoseconds. You make the zoo complete.
Quoted 4 lines
Hmm. The audio backend previously used microseconds, milliseconds, Hertz, frames, samples and bytes as time measurement, now at least everything use microseconds. Milliseconds precision is not enough, while nanosecond precision doesn't really make sense imho.
I'm just poking fun at our inability to pick a time unit for QAPI/QMP. No objection to your use of microseconds.
Quoted 16 lines
Quoted 7 lines
Quoted 7 lines
qapi/audio.json new file +7
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { + '*latency': 'int' } } +Quoted 8 lines
qapi/audio.json line 71
Quoted 6 lines
qapi/audio.json new file +6
-0+## +# @AudiodevOssPerDirectionOptions +# +# Options of the oss backend that are used for both playback and recording. +# +# @dev: #optional path of the oss deviceWho picks the default, QEMU or OSS?
Quoted 8 lines
It defaults to "
/dev/dsp".Quoted 2 lines
For ALSA, you documented @dev to be "the name", here it's "path". Intentional difference?
Yes. For oss you have to provide a filesystem path of the audio device (like
/dev/dsp), for alsa you provide an alsa specific name, like "default", "hw:1,0", "hdmi:CARD=NVidia,DEV=1", whatever.I don't like calling a filename a path, even though we already do in many places. Let's do:
# @dev: #optional file name of the oss device (default '
/dev/dsp')Quoted 29 lines
Quoted 11 lines
qapi/audio.json line 80
Quoted 9 lines
qapi/audio.json new file +9
-0+# +# @try-poll: #optional attempt to use poll mode +# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssPerDirectionOptions', + 'data': { + '*dev': 'str', + '*try-poll': 'bool' } }Same as for ALSA. Keeping them separate is fine with me.
This is the same as alsa's try-poll. They're separate because only these two backend use this setting.
Quoted 14 lines
qapi/audio.json line 91
Quoted 12 lines
qapi/audio.json new file +11
-0+ +## +# @AudiodevOssOptions +# +# Options of the oss audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @mmap: #optional try using memory mapped accessWhat happens when the attempt fails?
Quoted 3 lines
It should fall back to non-mmapped access (should because when I checked, it was buggy, at least on linux with alsa emulated oss on pulseaudio alsa device...)
Okay, assuming that's the user interface we want.
Quoted 12 lines
Quoted 1 line
Should this be called try-mmap?
Agree.
Quoted 8 lines
Quoted 6 lines
qapi/audio.json new file +4
-0+# +# @exclusive: #optional open device in exclusive mode (vmix won't work) +# +# @dsp-policy: #optional set the timing policy of the device, -1to use fragment
+# mode (option ignored on some platforms)What are the possible values besides -1?
Quoted 2 lines
It should be a number between 0 and 10 (according to this page:
http://manuals.opensound.com/developer/SNDCTL_DSP_POLICY.html)Please cover that in your comment.
Quoted 24 lines
Quoted 23 lines
Quoted 11 lines
qapi/audio.json new file +11
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevOssOptions', + 'data': { + 'in': 'AudiodevOssPerDirectionOptions', + 'out': 'AudiodevOssPerDirectionOptions', + '*mmap': 'bool', + '*exclusive': 'bool', + '*dsp-policy': 'int' } } +qapi/audio.json line 117
Quoted 10 lines
qapi/audio.json new file +10
-0+## +# @AudiodevPaOptions +# +# Options of the pa (PulseAudio) audio backend. +# +# @server: #optional PulseAudio server address +# +# @sink: #optional sink device name +# +# @source: #optional source device nameWho picks the defaults, QEMU or PA?
Quoted 4 lines
Quoted 1 line
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.)
Quoted 77 lines
Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
qapi/audio.json new file +15
-0+# +# 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 recordQuoted 8 lines
qapi/audio.json line 138
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevWavOptions', + 'data': { + '*path': 'str' } }Who picks the default?
Quoted 1 line
It defaults to "qemu.wav"
Make it
# @path: #optional path of the wav file to record (default 'qemu.wav')
Quoted 47 lines
Quoted 46 lines
Quoted 36 lines
qapi/audio.json new file +35
-0+ + +## +# @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 playbackand recording.
qapi/audio.json line 181
Quoted 8 lines
qapi/audio.json new file +8
-0+# +# @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 settingsAre these guys used when @fixed-settings is off?
Quoted 4 lines
Quoted 1 line
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. I guess I should also document it...
Quoted 61 lines
Quoted 54 lines
Quoted 5 lines
qapi/audio.json line 183
Quoted 2 lines
qapi/audio.json new file +2
-0+# +# @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.)
Quoted 36 lines
Quoted 36 lines
qapi/audio.json new file +35
-0+# +# @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' } } + +## +# @Audiodev +# +# Captures the configuration of an audio backend. +# +# @id: identifier of the backend +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @timer-period: #optional timer period (in microseconds, 0: use lowest +# possible) +# +# @opts: audio backend specific options +# +# Since: 2.4 +## +{ 'struct': 'Audiodev', + 'data': {Quoted 8 lines
qapi/audio.json line 223
Quoted 5 lines
qapi/audio.json new file +5
-0+ '*id': 'str', + 'in': 'AudiodevPerDirectionOptions', + 'out': 'AudiodevPerDirectionOptions', + '*timer-period': 'int', + 'opts': 'AudiodevBackendOptions' } }Have you considered making this a flat union, similar ro BlockdevOptions?
Quoted 2 lines
Not really. If you qapi masters out there think it's better, then I will convert it.
Related: discussion about flattening in review of PATCH 2.
Quoted 2 lines
Quoted 2 lines
Don't get deceived by the number of my questions, this is solid work.
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
Quoted 9 lines · Kővágó Zoltán
2015-06-17 13:48 keltezéssel, Markus Armbruster írta:
Quoted 8 lines
Quoted 6 lines · Kővágó Zoltán
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
Quoted 5 lines
Copying Eric for additional QAPI schema expertise.
My questions inline, pretty sure they show my ignorance.
"Kővágó, Zoltán" <[email protected]> writes:
[...]
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 4 lines
Quoted 4 lines
qapi/audio.json new file +4
-0+## +# @AudiodevPaOptions +# +# Options of the pa (PulseAudio) audio backend.Quoted 8 lines
qapi/audio.json line 117
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# @server: #optional PulseAudio server address +# +# @sink: #optional sink device name +# +# @source: #optional source device nameWho picks the defaults, QEMU or PA?
PA
Quoted 7 lines
Quoted 2 lines
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 :)
Quoted 77 lines
Quoted 77 lines
Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
qapi/audio.json new file +15
-0+# +# 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 recordQuoted 8 lines
qapi/audio.json line 138
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevWavOptions', + 'data': { + '*path': 'str' } }Who picks the default?
Quoted 1 line
It defaults to "qemu.wav"
Make it
# @path: #optional path of the wav file to record (default 'qemu.wav')
Quoted 47 lines
Quoted 46 lines
Quoted 36 lines
qapi/audio.json new file +35
-0+ + +## +# @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 playbackand recording.
qapi/audio.json line 181
Quoted 8 lines
qapi/audio.json new file +8
-0+# +# @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 settingsAre these guys used when @fixed-settings is off?
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
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?
What if I specify frequency, channels or format together with explicit
fixed-settings: false?
Quoted 2 lines
I
guess I should also document it...
Yes, please.
Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
Quoted 5 lines
qapi/audio.json line 183
Quoted 2 lines
qapi/audio.json new file +2
-0+# +# @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.)
Quoted 15 lines
Quoted 15 lines
qapi/audio.json new file +14
-0+# +# @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 1/6] qapi: qapi for audio backends
2015-06-17 15:37 keltezéssel, Markus Armbruster írta:
Quoted 126 lines
Quoted 9 lines · Kővágó Zoltán
2015-06-17 13:48 keltezéssel, Markus Armbruster írta:
Quoted 8 lines
Quoted 6 lines · Kővágó Zoltán
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
Quoted 5 lines
Copying Eric for additional QAPI schema expertise.
My questions inline, pretty sure they show my ignorance.
"Kővágó, Zoltán" <[email protected]> writes:
[...]
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 4 lines
Quoted 4 lines
qapi/audio.json new file +4
-0+## +# @AudiodevPaOptions +# +# Options of the pa (PulseAudio) audio backend.Quoted 8 lines
qapi/audio.json line 117
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# @server: #optional PulseAudio server address +# +# @sink: #optional sink device name +# +# @source: #optional source device nameWho picks the defaults, QEMU or PA?
PA
Quoted 7 lines
Quoted 2 lines
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 :)
Quoted 77 lines
Quoted 77 lines
Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
qapi/audio.json new file +15
-0+# +# 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 recordQuoted 8 lines
qapi/audio.json line 138
Quoted 6 lines
qapi/audio.json new file +6
-0+# +# Since: 2.4 +## +{ 'struct': 'AudiodevWavOptions', + 'data': { + '*path': 'str' } }Who picks the default?
Quoted 1 line
It defaults to "qemu.wav"
Make it
# @path: #optional path of the wav file to record (default 'qemu.wav')
Quoted 47 lines
Quoted 46 lines
Quoted 36 lines
qapi/audio.json new file +35
-0+ + +## +# @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 playbackand recording.
qapi/audio.json line 181
Quoted 8 lines
qapi/audio.json new file +8
-0+# +# @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 settingsAre these guys used when @fixed-settings is off?
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
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.
Quoted 8 lines
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.
Quoted 2 lines
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.
Quoted 32 lines
Quoted 3 lines
I
guess I should also document it...Yes, please.
Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
Quoted 5 lines
qapi/audio.json line 183
Quoted 2 lines
qapi/audio.json new file +2
-0+# +# @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.)
Quoted 15 lines
Quoted 15 lines
qapi/audio.json new file +14
-0+# +# @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 1/6] qapi: qapi for audio backends
Quoted 7 lines · Kővágó Zoltán
2015-06-17 15:37 keltezéssel, Markus Armbruster írta:
Quoted 6 lines
Quoted 4 lines · Kővágó Zoltán
2015-06-17 13:48 keltezéssel, Markus Armbruster írta:
Quoted 3 lines
Quoted 1 line · Kővágó Zoltán
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
[...]
Quoted 66 lines
Quoted 52 lines
Quoted 45 lines
Quoted 45 lines
Quoted 45 lines
Quoted 44 lines
Quoted 34 lines
(quoted diff) +33
-0+## +# @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 playbackand recording.
Review
Quoted 8 lines
(quoted diff) +8
-0+# +# @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 settingsAre these guys used when @fixed-settings is off?
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
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.
Quoted 8 lines
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.
Quoted 2 lines
What if I specify frequency, channels or format together with explicit
fixed-settings: false?
Quoted 8 lines
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.
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
2015-06-17 18:06 keltezéssel, Markus Armbruster írta:
Quoted 88 lines
Quoted 7 lines · Kővágó Zoltán
2015-06-17 15:37 keltezéssel, Markus Armbruster írta:
Quoted 6 lines
Quoted 4 lines · Kővágó Zoltán
2015-06-17 13:48 keltezéssel, Markus Armbruster írta:
Quoted 3 lines
Quoted 1 line · Kővágó Zoltán
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
[...]
Quoted 66 lines
Quoted 52 lines
Quoted 45 lines
Quoted 45 lines
Quoted 45 lines
Quoted 44 lines
Quoted 34 lines
(quoted diff) +33
-0+## +# @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 playbackand recording.
Review
Quoted 8 lines
(quoted diff) +8
-0+# +# @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 settingsAre these guys used when @fixed-settings is off?
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
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.
Quoted 8 lines
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.
Quoted 2 lines
What if I specify frequency, channels or format together with explicit
fixed-settings: false?Quoted 8 lines
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?
Quoted 7 lines
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 1/6] qapi: qapi for audio backends
Quoted 97 lines · Kővágó Zoltán
2015-06-17 18:06 keltezéssel, Markus Armbruster írta:
Quoted 88 lines
Quoted 7 lines · Kővágó Zoltán
2015-06-17 15:37 keltezéssel, Markus Armbruster írta:
Quoted 6 lines
Quoted 4 lines · Kővágó Zoltán
2015-06-17 13:48 keltezéssel, Markus Armbruster írta:
Quoted 3 lines
Quoted 1 line · Kővágó Zoltán
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
[...]
Quoted 66 lines
Quoted 52 lines
Quoted 45 lines
Quoted 45 lines
Quoted 45 lines
Quoted 44 lines
Quoted 34 lines
(quoted diff) +33
-0+## +# @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 playbackand recording.
Review
Quoted 8 lines
(quoted diff) +8
-0+# +# @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 settingsAre these guys used when @fixed-settings is off?
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
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.
Quoted 8 lines
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.
Quoted 2 lines
What if I specify frequency, channels or format together with explicit
fixed-settings: false?Quoted 8 lines
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?
Quoted 7 lines
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.
Quoted 7 lines
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.
When a sensible default value exists, making the parameter optional is usually a good idea.
We should refuse to start on non-sensical configuration, not silently substitute defaults or disable the affected component (here: audio backend).
I can't give you more specific guidance, because I'm an audio ignoramus :)
Re: [Qemu-devel] [PATCH v2 1/6] qapi: qapi for audio backends
In reply to Markus ArmbrusterQuoted 14 lines · Markus Armbruster
Quoted 12 lines · Kővágó Zoltán
2015-06-17 09:46 keltezéssel, Markus Armbruster írta:
Quoted 11 lines
Copying Eric for additional QAPI schema expertise.
Quoted 7 lines
qapi/audio.json new file +7
-0+{ 'struct': 'Audiodev', + 'data': { + '*id': 'str', + 'in': 'AudiodevPerDirectionOptions', + 'out': 'AudiodevPerDirectionOptions', + '*timer-period': 'int', + 'opts': 'AudiodevBackendOptions' } }
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Have you considered making this a flat union, similar ro BlockdevOptions?
Not really. If you qapi masters out there think it's better, then I will convert it.
Related: discussion about flattening in review of PATCH 2.
Indeed - I think a flat union makes for nicer command line structure, and fewer {} nesting in QMP structure. I still need to spend time on the overall thread, but wanted to chime in on this comment up front.
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
PATCH v2 2/6 qapi: support nested structs in OptsVisitor
In reply to Kővágó, ZoltánThe 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).
--- 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(-)
qapi/opts-visitor.c +115 -29
@@ -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(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 ; }
@@ -177,6 +195,8 @@ opts_end_struct(Visitor *v, Error **errp) }g_hash_table_destroy (ov->unprocessed_opts); ov->unprocessed_opts =NULL ; +g_hash_table_destroy (ov->opts); + ov->opts =NULL ;if (ov->fake_id_opt) {g_free (ov->fake_id_opt->name);g_free (ov->fake_id_opt->str);
@@ -185,16 +205,56 @@ opts_end_struct(Visitor *v, Error **errp) ov->fake_id_opt =NULL ; } +static void +sum_strlen (gpointer data,gpointer user_data) +{ +const char *str = data; +size_t *sum_len = user_data; + *sum_len +=strlen (str) +1 ; +} + +static void +append_str (gpointer data,gpointer user_data) +{ +strcat (user_data, data); +strcat (user_data,"." ); +} + +/* lookup a name, trying from the most qualified version (e.g. foo.bar.asd) to +* least qualified ones (i.e. foo.bar.asd overrides bar.asd or asd) */ 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, *key2; +size_t sum_len =strlen (name); - list =g_hash_table_lookup (ov->unprocessed_opts, 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); + + key2 = key; +while (*key2) { + list =g_hash_table_lookup (ov->opts, key2); +if (list) { +if (out_key) { + *out_key =g_strdup (key2); + } +break ; + } + +while (*key2 && *key2++ !='.' ) { + } + }if (!list) {error_set (errp,QERR_MISSING_PARAMETER , name); } + +g_free (key);return list; }
@@ -206,7 +266,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 ; }
@@ -242,11 +302,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;
@@ -272,22 +330,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->repeated_name); + ov->repeated_name =NULL ; + ov->list_mode =LM_NONE ; }static const QemuOpt * -lookup_scalar (const OptsVisitor *ov,const char *name,Error **errp) +lookup_scalar (const OptsVisitor *ov,const char *name,char ** out_key, +Error **errp) {if (ov->list_mode ==LM_NONE ) {GQueue *list;/* the last occurrence of any QemuOpt takes effect when queried by name */ - list =lookup_distinct (ov, name, errp); + list =lookup_distinct (ov, name, out_key, errp);return list ?g_queue_peek_tail (list) :NULL ; }assert (ov->list_mode ==LM_IN_PROGRESS ); +assert (out_key ==NULL || *out_key ==NULL );return g_queue_peek_head (ov->repeated_opts); }
@@ -309,13 +373,15 @@ opts_type_str(Visitor *v, char **obj, const char *name, Error **errp) {OptsVisitor *ov =DO_UPCAST (OptsVisitor, visitor, v);const QemuOpt *opt; +char *key =NULL ; - opt =lookup_scalar (ov, name, errp); + opt =lookup_scalar (ov, name, &key, errp);if (!opt) {return ; } *obj =g_strdup (opt->str ? opt->str :"" ); -processed (ov, name); +processed (ov, key); +g_free (key); }
@@ -325,8 +391,9 @@ opts_type_bool(Visitor *v, bool *obj, const char *name, Error **errp) {OptsVisitor *ov =DO_UPCAST (OptsVisitor, visitor, v);const QemuOpt *opt; +char *key =NULL ; - opt =lookup_scalar (ov, name, errp); + opt =lookup_scalar (ov, name, &key, errp);if (!opt) {return ; }
@@ -343,13 +410,15 @@ opts_type_bool(Visitor *v, bool *obj, const char *name, Error **errp) }else {error_set (errp,QERR_INVALID_PARAMETER_VALUE , opt->name,"on|yes|y|off|no|n" ); +g_free (key);return ; } }else { *obj = true; } -processed (ov, name); +processed (ov, key); +g_free (key); }
@@ -361,13 +430,14 @@ opts_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)const char *str;long long val;char *endptr; +char *key =NULL ;if (ov->list_mode ==LM_SIGNED_INTERVAL ) { *obj = ov->range_next.s;return ; } - opt =lookup_scalar (ov, name, errp); + opt =lookup_scalar (ov, name, &key, errp);if (!opt) {return ; }
@@ -381,11 +451,13 @@ opts_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)if (errno ==0 && endptr > str &&INT64_MIN <= val && val <=INT64_MAX ) {if (*endptr =='\0' ) { *obj = val; -processed (ov, name); +processed (ov, key); +g_free (key);return ; }if (*endptr =='-' && ov->list_mode ==LM_IN_PROGRESS ) {long long val2; +assert (key ==NULL ); str = endptr +1 ; val2 =strtoll (str, &endptr,0 );
@@ -406,6 +478,7 @@ opts_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)error_set (errp,QERR_INVALID_PARAMETER_VALUE , opt->name, (ov->list_mode ==LM_NONE ) ?"an int64 value" :"an int64 value or range" ); +g_free (key); }
@@ -417,13 +490,14 @@ opts_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)const char *str;unsigned long long val;char *endptr; +char *key =NULL ;if (ov->list_mode ==LM_UNSIGNED_INTERVAL ) { *obj = ov->range_next.u;return ; } - opt =lookup_scalar (ov, name, errp); + opt =lookup_scalar (ov, name, &key, errp);if (!opt) {return ; }
@@ -435,11 +509,13 @@ opts_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)if (parse_uint (str, &val, &endptr,0 ) ==0 && val <=UINT64_MAX ) {if (*endptr =='\0' ) { *obj = val; -processed (ov, name); +processed (ov, key); +g_free (key);return ; }if (*endptr =='-' && ov->list_mode ==LM_IN_PROGRESS ) {unsigned long long val2; +assert (key ==NULL ); str = endptr +1 ; if (parse_uint_full(str, &val2, 0) == 0 &&
@@ -458,6 +534,7 @@ opts_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)error_set (errp,QERR_INVALID_PARAMETER_VALUE , opt->name, (ov->list_mode ==LM_NONE ) ?"a uint64 value" :"a uint64 value or range" ); +g_free (key); }
@@ -468,8 +545,9 @@ opts_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)const QemuOpt *opt;int64_t val;char *endptr; +char *key =NULL ; - opt =lookup_scalar (ov, name, errp); + opt =lookup_scalar (ov, name, &key, errp);if (!opt) {return ; }
@@ -479,11 +557,13 @@ opts_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)if (val <0 || *endptr) {error_set (errp,QERR_INVALID_PARAMETER_VALUE , opt->name,"a size value representible as a non-negative int64" ); +g_free (key);return ; } *obj = val; -processed (ov, name); +processed (ov, key); +g_free (key); }
@@ -494,7 +574,7 @@ opts_optional(Visitor *v, bool *present, const char *name, Error **errp)/* we only support a single mandatory scalar field in a list node */ assert (ov->list_mode ==LM_NONE ); - *present = (lookup_distinct (ov, name,NULL ) !=NULL ); + *present = (lookup_distinct (ov, name,NULL ,NULL ) !=NULL ); }
@@ -505,6 +585,8 @@ opts_visitor_new(const QemuOpts *opts) ov =g_malloc0 (sizeof *ov); + ov->nested_names =g_queue_new (); + ov->visitor.start_struct = &opts_start_struct; ov->visitor.end_struct = &opts_end_struct;
@@ -545,6 +627,10 @@ opts_visitor_cleanup(OptsVisitor *ov)if (ov->unprocessed_opts !=NULL ) {g_hash_table_destroy (ov->unprocessed_opts); } +if (ov->opts !=NULL ) { +g_hash_table_destroy (ov->opts); + } +g_queue_free (ov->nested_names);g_free (ov->fake_id_opt);g_free (ov); }
tests/qapi-schema/qapi-schema-test.json +8 -1
@@ -81,6 +81,11 @@ { 'command': 'user_def_cmd3', 'data': {'a': 'int', '*b': 'int' }, 'returns': 'int' } +# For testing hierarchy support in opts-visitor +{ 'struct': 'UserDefOptionsSub', + 'data': { + '*nint': 'int' } } + # For testing integer range flattening in opts-visitor. The following schema # corresponds to the option format: #
@@ -94,7 +99,9 @@ '*u64' : [ 'uint64' ], '*u16' : [ 'uint16' ], '*i64x': 'int' , - '*u64x': 'uint64' } } + '*u64x': 'uint64' , + 'sub0': 'UserDefOptionsSub', + 'sub1': 'UserDefOptionsSub' } } # testing event { 'struct': 'EventStructOne',
tests/test-opts-visitor.c +34 -0
@@ -177,6 +177,34 @@ expect_u64_max(OptsVisitorFixture *f, gconstpointer test_data)g_assert (f->userdef->u64->value ==UINT64_MAX ); } +static void +expect_both (OptsVisitorFixture *f,gconstpointer test_data) +{ +expect_ok (f, test_data); +g_assert (f->userdef->sub0->has_nint); +g_assert (f->userdef->sub0->nint ==13 ); +g_assert (f->userdef->sub1->has_nint); +g_assert (f->userdef->sub1->nint ==13 ); +} + +static void +expect_sub0 (OptsVisitorFixture *f,gconstpointer test_data) +{ +expect_ok (f, test_data); +g_assert (f->userdef->sub0->has_nint); +g_assert (f->userdef->sub0->nint ==13 ); +g_assert (!f->userdef->sub1->has_nint); +} + +static void +expect_sub1 (OptsVisitorFixture *f,gconstpointer test_data) +{ +expect_ok (f, test_data); +g_assert (!f->userdef->sub0->has_nint); +g_assert (f->userdef->sub1->has_nint); +g_assert (f->userdef->sub1->nint ==13 ); +} +/* test cases */ int
@@ -270,6 +298,12 @@ main(int argc, char **argv)add_test ("/visitor/opts/i64/range/2big/full" , &expect_fail,"i64=-0x8000000000000000-0x7fffffffffffffff" ); +/* Test nested structs support */ +add_test ("/visitor/opts/nested/unqualified" , &expect_both,"nint=13" ); +add_test ("/visitor/opts/nested/both" , &expect_both, +"sub0.nint=13,sub1.nint=13" ); +add_test ("/visitor/opts/nested/sub0" , &expect_sub0,"sub0.nint=13" ); +add_test ("/visitor/opts/nested/sub1" , &expect_sub1,"sub1.nint=13" );g_test_run ();return 0 ; }
Signature · 1 line
2.4.3
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
Copying László because his fingerprints are on OptsVisitor.
Quoted 5 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like
in' andout' inAudiodev'), the current visitor can't cope with them (for example settingfrequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified).
Quoted 13 lines
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 tofoo.bar.something' if onlyfoo' has abar' 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.gfrequency=44100,in.frequency=8000') the longest matching (the most specific) path wins (so in this example, in's frequency would become 8000, becausein.frequency' is more specific thatfrequency', and out's frequency would become 44100, because onlyfrequency' matches it).
Can you explain why the complexity is needed, i.e. why we can't just require full paths always?
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
Quoted 23 lines · Markus Armbruster
Copying László because his fingerprints are on OptsVisitor.
Quoted 5 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like
in' andout' inAudiodev'), the current visitor can't cope with them (for example settingfrequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified).Quoted 13 lines
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 tofoo.bar.something' if onlyfoo' has abar' 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.gfrequency=44100,in.frequency=8000') the longest matching (the most specific) path wins (so in this example, in's frequency would become 8000, becausein.frequency' is more specific thatfrequency', and out's frequency would become 44100, because onlyfrequency' matches it).
Quoted 2 lines
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 ...
cheers,
Gerd
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
2015-06-17 10:41 keltezéssel, Gerd Hoffmann írta:
Quoted 27 lines · Markus Armbruster
Quoted 23 lines
Copying László because his fingerprints are on OptsVisitor.
Quoted 5 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named fields under different paths (like
in' andout' inAudiodev'), the current visitor can't cope with them (for example settingfrequency=44100' will set the in's frequency to 44100 and leave out's frequency unspecified).Quoted 13 lines
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 tofoo.bar.something' if onlyfoo' has abar' 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.gfrequency=44100,in.frequency=8000') the longest matching (the most specific) path wins (so in this example, in's frequency would become 8000, becausein.frequency' is more specific thatfrequency', and out's frequency would become 44100, because onlyfrequency' matches it).Quoted 2 lines
Can you explain why the complexity is needed, i.e. why we can't just require full paths always?
Quoted 7 lines
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 2/6] qapi: support nested structs in OptsVisitor
Quoted 47 lines · Kővágó Zoltán
2015-06-17 10:41 keltezéssel, Gerd Hoffmann írta:
Quoted 38 lines · Markus Armbruster
Quoted 34 lines
Copying László because his fingerprints are on OptsVisitor.
Quoted 21 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named
fields under different paths (likein' andout' 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 tofoo.bar.something' if onlyfoo' has a `bar'
field). This way
1) is just a special case of this when only the last component
is specified.Quoted 8 lines
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).Quoted 2 lines
Can you explain why the complexity is needed, i.e. why we can't just require full paths always?
Quoted 7 lines
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 ...
Quoted 4 lines
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.
I agree opts.data.in.try-poll would be an ugly user interface. But instead of hiding opts.data. with a convenience feature, I'd like us to investigate avoiding it altogether.
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
In reply to Kővágó ZoltánQuoted 11 lines · Kővágó Zoltán
Quoted 10 lines
Quoted 2 lines
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 ...
Quoted 4 lines
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.
Elsewhere in the thread, it was suggested that you use a flat union. That would simplify the full path to opts.in.try-poll, rather than opts.data.in.try-poll.
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
In reply to Gerd HoffmannCopying Kevin because similar issues exist in the block layer.
Quoted 13 lines · Gerd Hoffmann
Quoted 12 lines · Markus Armbruster
Copying László because his fingerprints are on OptsVisitor.
Quoted 8 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named
fields under different paths (likein' andout' 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).
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
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?
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
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 tofoo.bar.something' if onlyfoo' has a `bar'
field). This way
1) is just a special case of this when only the last component
is specified.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
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?
Quoted 4 lines
Quoted 2 lines
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.
Quoted 5 lines
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 2/6] qapi: support nested structs in OptsVisitor
2015-06-17 13:18 keltezéssel, Markus Armbruster írta:
Quoted 17 lines
Copying Kevin because similar issues exist in the block layer.
Quoted 13 lines · Gerd Hoffmann
Quoted 12 lines · Markus Armbruster
Copying László because his fingerprints are on OptsVisitor.
Quoted 8 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named
fields under different paths (likein' andout' 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).
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
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.)
Quoted 18 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
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 tofoo.bar.something' if onlyfoo' has a `bar'
field). This way
1) is just a special case of this when only the last component
is specified.Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
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).
Quoted 8 lines
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.)
Quoted 20 lines
Quoted 4 lines
Quoted 2 lines
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.
Quoted 5 lines
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 2/6] qapi: support nested structs in OptsVisitor
Quoted 24 lines · Kővágó Zoltán
2015-06-17 13:18 keltezéssel, Markus Armbruster írta:
Quoted 23 lines
Copying Kevin because similar issues exist in the block layer.
Quoted 18 lines · Gerd Hoffmann
Quoted 17 lines · Markus Armbruster
Copying László because his fingerprints are on OptsVisitor.
Quoted 13 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named
fields under different paths (likein' andout' 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).
Quoted 8 lines
Quoted 3 lines
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?
[...]
Re: [Qemu-devel] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
2015-06-17 15:41 keltezéssel, Markus Armbruster írta:
Quoted 35 lines
Quoted 24 lines · Kővágó Zoltán
2015-06-17 13:18 keltezéssel, Markus Armbruster írta:
Quoted 23 lines
Copying Kevin because similar issues exist in the block layer.
Quoted 18 lines · Gerd Hoffmann
Quoted 17 lines · Markus Armbruster
Copying László because his fingerprints are on OptsVisitor.
Quoted 13 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named
fields under different paths (likein' andout' 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).Quoted 8 lines
Quoted 3 lines
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.)
Quoted 5 lines
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] [PATCH v2 2/6] qapi: support nested structs in OptsVisitor
Quoted 36 lines · Kővágó Zoltán
2015-06-17 15:41 keltezéssel, Markus Armbruster írta:
Quoted 35 lines
Quoted 32 lines · Kővágó Zoltán
2015-06-17 13:18 keltezéssel, Markus Armbruster írta:
Quoted 23 lines
Copying Kevin because similar issues exist in the block layer.
Quoted 13 lines · Gerd Hoffmann
Quoted 12 lines · Markus Armbruster
Copying László because his fingerprints are on OptsVisitor.
Quoted 8 lines · Zoltán
The current OptsVisitor flattens the whole structure, if there are same named
fields under different paths (likein' andout' 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).Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
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).Quoted 3 lines
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.)
Quoted 8 lines
Quoted 5 lines
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.
Is it common to set both to the same value?
We could also default one to the other. Not sure that's actually a good idea.
Quoted 3 lines
But this
could also be the convenience feature that we not really need. I don't see any other downside of making it unambigous.
Good to know.
We've struggled with unforeseen aftereffects of cute convenience features too much, and by now I'm quite reluctant to support them without a really compelling reason.
PATCH v2 3/6 opts: do not print separator before first item in qemu_opts_print
In reply to Kővágó, ZoltánThis 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.
--- block.c | 2 +- util/qemu-option.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-)
block.c +1 -1
@@ -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 ("" ); }
util/qemu-option.c +4 -1
@@ -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; } }
Signature · 1 line
2.4.3
Re: [Qemu-devel] [PATCH v2 3/6] opts: do not print separator before first item in qemu_opts_print
Quoted 3 lines · Zoltán
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.
Suggest: This will let us print...
Quoted 1 line
Only
block.cdepended on the old behavior, but it was also updated.
I'd drop this sentence.
Quoted 43 lines
Signed-off-by Kővágó, Zoltán <[email protected]>--- block.c | 2 +- util/qemu-option.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-)block.c +1
-1@@ -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 ("" ); }util/qemu-option.c +3
-1@@ -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 ; }
util/qemu-option.c void qemu_opts_print(QemuOpts *opts, const char *sep) · line 762
Quoted 6 lines
util/qemu-option.c +1
-0@@ -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; } }
No idea what d_ means. Let's rename d_sep to separator.
With that rename:
Re: [Qemu-devel] [PATCH v2 3/6] opts: do not print separator before first item in qemu_opts_print
In reply to Kővágó, ZoltánAm 16.06.2015 um 14:49 hat Kővágó, Zoltán geschrieben:
Quoted 3 lines
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.
Note that if you really want to produce a valid command line, you would have to escape any commas in option values. The quotes arounds strings might not be wanted any more then either.
Quoted 3 lines
Only
block.cdepended on the old behavior, but it was also updated.Signed-off-by Kővágó, Zoltán <[email protected]>
Seems that no behaviour changes from a block layer perspective, so:
PATCH v2 4/6 qapi: AllocVisitor
In reply to Kővágó, ZoltánSimple visitor that recursively allocates structures with only optional variables. Unions are initialized to the first type specified. Other non optional types are not supported.
--- 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
include/qapi/alloc-visitor.h new file +18 -0
@@ -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
qapi/Makefile.objs +1 -0
@@ -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
qapi/alloc-visitor.c new file +62 -0
62 lines not on this page · raw message
Signature · 1 line
2.4.3
Re: [Qemu-devel] [PATCH v2 4/6] qapi: AllocVisitor
Quoted 3 lines · Zoltán
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.
Re: [Qemu-devel] [PATCH v2 4/6] qapi: AllocVisitor
2015-06-17 09:56 keltezéssel, Markus Armbruster írta:
Quoted 10 lines
Quoted 3 lines · Zoltán
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 4/6] qapi: AllocVisitor
Quoted 7 lines · Kővágó Zoltán
2015-06-17 09:56 keltezéssel, Markus Armbruster írta:
Quoted 6 lines
Quoted 3 lines · Zoltán
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.
Quoted 7 lines
Quoted 4 lines
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.
Glad I asked before reviewing the code :)
PATCH v2 5/6 audio: use qapi AudioFormat instead of audfmt_e
In reply to Kővágó, ZoltánI 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.
--- 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(-)
audio/alsaaudio.c +28 -25
@@ -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 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 ; } threshold = (conf->threshold * bytes_per_sec) /1000 ;
audio/audio.c +53 -44
230 lines not on this page · raw message
audio/audio.h +1 -10
@@ -29,15 +29,6 @@typedef void (*audio_callback_fn ) (void *opaque,int avail); -typedef enum { -AUD_FMT_U8 , -AUD_FMT_S8 , -AUD_FMT_U16 , -AUD_FMT_S16 , -AUD_FMT_U32 , -AUD_FMT_S32 -}audfmt_e ; -#ifdef HOST_WORDS_BIGENDIAN #define AUDIO_HOST_ENDIANNESS 1#else
@@ -47,7 +38,7 @@ typedef enum {struct audsettings {int freq;int nchannels; -audfmt_e fmt; +AudioFormat fmt;int endianness; };
audio/audio_win_int.c +9 -9
@@ -23,20 +23,20 @@ int waveformat_from_audio_settings (WAVEFORMATEX *wfx, wfx->cbSize =0 ;switch (as->fmt) { -case AUD_FMT_S8 : -case AUD_FMT_U8 : +case AUDIO_FORMAT_S8 : +case AUDIO_FORMAT_U8 : wfx->wBitsPerSample =8 ;break ; -case AUD_FMT_S16 : -case AUD_FMT_U16 : +case AUDIO_FORMAT_S16 : +case AUDIO_FORMAT_U16 : wfx->wBitsPerSample =16 ; wfx->nAvgBytesPerSec <<=1 ; wfx->nBlockAlign <<=1 ;break ; -case AUD_FMT_S32 : -case AUD_FMT_U32 : +case AUDIO_FORMAT_S32 : +case AUDIO_FORMAT_U32 : wfx->wBitsPerSample =32 ; wfx->nAvgBytesPerSec <<=2 ; wfx->nBlockAlign <<=2 ;
@@ -84,15 +84,15 @@ int waveformat_to_audio_settings (WAVEFORMATEX *wfx,switch (wfx->wBitsPerSample) {case 8 : - as->fmt =AUD_FMT_U8 ; + as->fmt =AUDIO_FORMAT_U8 ;break ;case 16 : - as->fmt =AUD_FMT_S16 ; + as->fmt =AUDIO_FORMAT_S16 ;break ;case 32 : - as->fmt =AUD_FMT_S32 ; + as->fmt =AUDIO_FORMAT_S32 ;break ;default :
audio/ossaudio.c +15 -15
@@ -72,7 +72,7 @@ typedef struct OSSVoiceIn {struct oss_params {int freq; -audfmt_e fmt; +AudioFormat fmt;int nchannels;int nfrags;int fragsize;
@@ -150,16 +150,16 @@ static int oss_write (SWVoiceOut *sw, void *buf, int len)return audio_pcm_sw_write (sw, buf, len); } -static int aud_to_ossfmt (audfmt_e fmt,int endianness) +static int aud_to_ossfmt (AudioFormat fmt,int endianness) {switch (fmt) { -case AUD_FMT_S8 : +case AUDIO_FORMAT_S8 :return AFMT_S8 ; -case AUD_FMT_U8 : +case AUDIO_FORMAT_U8 :return AFMT_U8 ; -case AUD_FMT_S16 : +case AUDIO_FORMAT_S16 :if (endianness) {return AFMT_S16_BE ; }
@@ -167,7 +167,7 @@ static int aud_to_ossfmt (audfmt_e fmt, int endianness)return AFMT_S16_LE ; } -case AUD_FMT_U16 : +case AUDIO_FORMAT_U16 :if (endianness) {return AFMT_U16_BE ; }
@@ -184,37 +184,37 @@ static int aud_to_ossfmt (audfmt_e fmt, int endianness) } } -static int oss_to_audfmt (int ossfmt,audfmt_e *fmt,int *endianness) +static int oss_to_audfmt (int ossfmt,AudioFormat *fmt,int *endianness) {switch (ossfmt) {case AFMT_S8 : *endianness =0 ; - *fmt =AUD_FMT_S8 ; + *fmt =AUDIO_FORMAT_S8 ;break ;case AFMT_U8 : *endianness =0 ; - *fmt =AUD_FMT_U8 ; + *fmt =AUDIO_FORMAT_U8 ;break ;case AFMT_S16_LE : *endianness =0 ; - *fmt =AUD_FMT_S16 ; + *fmt =AUDIO_FORMAT_S16 ;break ;case AFMT_U16_LE : *endianness =0 ; - *fmt =AUD_FMT_U16 ; + *fmt =AUDIO_FORMAT_U16 ;break ;case AFMT_S16_BE : *endianness =1 ; - *fmt =AUD_FMT_S16 ; + *fmt =AUDIO_FORMAT_S16 ;break ;case AFMT_U16_BE : *endianness =1 ; - *fmt =AUD_FMT_U16 ; + *fmt =AUDIO_FORMAT_U16 ;break ;default :
@@ -502,7 +502,7 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,int endianness;int err;int fd; -audfmt_e effective_fmt; +AudioFormat effective_fmt;struct audsettings obt_as;OSSConf *conf = drv_opaque;
@@ -671,7 +671,7 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)int endianness;int err;int fd; -audfmt_e effective_fmt; +AudioFormat effective_fmt;struct audsettings obt_as;OSSConf *conf = drv_opaque;
audio/paaudio.c +14 -14
@@ -384,21 +384,21 @@ static int qpa_read (SWVoiceIn *sw, void *buf, int len)return audio_pcm_sw_read (sw, buf, len); } -static pa_sample_format_t audfmt_to_pa (audfmt_e afmt,int endianness) +static pa_sample_format_t audfmt_to_pa (AudioFormat afmt,int endianness) {int format;switch (afmt) { -case AUD_FMT_S8 : -case AUD_FMT_U8 : +case AUDIO_FORMAT_S8 : +case AUDIO_FORMAT_U8 : format =PA_SAMPLE_U8 ;break ; -case AUD_FMT_S16 : -case AUD_FMT_U16 : +case AUDIO_FORMAT_S16 : +case AUDIO_FORMAT_U16 : format = endianness ?PA_SAMPLE_S16BE :PA_SAMPLE_S16LE ;break ; -case AUD_FMT_S32 : -case AUD_FMT_U32 : +case AUDIO_FORMAT_S32 : +case AUDIO_FORMAT_U32 : format = endianness ?PA_SAMPLE_S32BE :PA_SAMPLE_S32LE ;break ;default :
@@ -409,26 +409,26 @@ static pa_sample_format_t audfmt_to_pa (audfmt_e afmt, int endianness)return format; } -static audfmt_e pa_to_audfmt (pa_sample_format_t fmt,int *endianness) +static AudioFormat pa_to_audfmt (pa_sample_format_t fmt,int *endianness) {switch (fmt) {case PA_SAMPLE_U8 : -return AUD_FMT_U8 ; +return AUDIO_FORMAT_U8 ;case PA_SAMPLE_S16BE : *endianness =1 ; -return AUD_FMT_S16 ; +return AUDIO_FORMAT_S16 ;case PA_SAMPLE_S16LE : *endianness =0 ; -return AUD_FMT_S16 ; +return AUDIO_FORMAT_S16 ;case PA_SAMPLE_S32BE : *endianness =1 ; -return AUD_FMT_S32 ; +return AUDIO_FORMAT_S32 ;case PA_SAMPLE_S32LE : *endianness =0 ; -return AUD_FMT_S32 ; +return AUDIO_FORMAT_S32 ;default :dolog ("Internal logic error: Bad pa_sample_format %d\n" , fmt); -return AUD_FMT_U8 ; +return AUDIO_FORMAT_U8 ; } }
audio/sdlaudio.c +13 -13
@@ -115,19 +115,19 @@ static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)return sdl_post (s, forfn); } -static int aud_to_sdlfmt (audfmt_e fmt) +static int aud_to_sdlfmt (AudioFormat fmt) {switch (fmt) { -case AUD_FMT_S8 : +case AUDIO_FORMAT_S8 :return AUDIO_S8 ; -case AUD_FMT_U8 : +case AUDIO_FORMAT_U8 :return AUDIO_U8 ; -case AUD_FMT_S16 : +case AUDIO_FORMAT_S16 :return AUDIO_S16LSB ; -case AUD_FMT_U16 : +case AUDIO_FORMAT_U16 :return AUDIO_U16LSB ;default :
@@ -139,37 +139,37 @@ static int aud_to_sdlfmt (audfmt_e fmt) } } -static int sdl_to_audfmt (int sdlfmt,audfmt_e *fmt,int *endianness) +static int sdl_to_audfmt (int sdlfmt,AudioFormat *fmt,int *endianness) {switch (sdlfmt) {case AUDIO_S8 : *endianness =0 ; - *fmt =AUD_FMT_S8 ; + *fmt =AUDIO_FORMAT_S8 ;break ;case AUDIO_U8 : *endianness =0 ; - *fmt =AUD_FMT_U8 ; + *fmt =AUDIO_FORMAT_U8 ;break ;case AUDIO_S16LSB : *endianness =0 ; - *fmt =AUD_FMT_S16 ; + *fmt =AUDIO_FORMAT_S16 ;break ;case AUDIO_U16LSB : *endianness =0 ; - *fmt =AUD_FMT_U16 ; + *fmt =AUDIO_FORMAT_U16 ;break ;case AUDIO_S16MSB : *endianness =1 ; - *fmt =AUD_FMT_S16 ; + *fmt =AUDIO_FORMAT_S16 ;break ;case AUDIO_U16MSB : *endianness =1 ; - *fmt =AUD_FMT_U16 ; + *fmt =AUDIO_FORMAT_U16 ;break ;default :
@@ -341,7 +341,7 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,SDL_AudioSpec req, obt;int endianness;int err; -audfmt_e effective_fmt; +AudioFormat effective_fmt;struct audsettings obt_as; req.freq = as->freq;
audio/spiceaudio.c +2 -2
@@ -127,7 +127,7 @@ static int line_out_init(HWVoiceOut *hw, struct audsettings *as, settings.freq =SPICE_INTERFACE_PLAYBACK_FREQ ;#endif settings.nchannels =SPICE_INTERFACE_PLAYBACK_CHAN ; - settings.fmt =AUD_FMT_S16 ; + settings.fmt =AUDIO_FORMAT_S16 ; settings.endianness =AUDIO_HOST_ENDIANNESS ;audio_pcm_init_info (&hw->info, &settings);
@@ -255,7 +255,7 @@ static int line_in_init(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) settings.freq =SPICE_INTERFACE_RECORD_FREQ ;#endif settings.nchannels =SPICE_INTERFACE_RECORD_CHAN ; - settings.fmt =AUD_FMT_S16 ; + settings.fmt =AUDIO_FORMAT_S16 ; settings.endianness =AUDIO_HOST_ENDIANNESS ;audio_pcm_init_info (&hw->info, &settings);
audio/wavaudio.c +10 -7
@@ -116,20 +116,23 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, stereo = wav_as.nchannels ==2 ;switch (wav_as.fmt) { -case AUD_FMT_S8 : -case AUD_FMT_U8 : +case AUDIO_FORMAT_S8 : +case AUDIO_FORMAT_U8 : bits16 =0 ;break ; -case AUD_FMT_S16 : -case AUD_FMT_U16 : +case AUDIO_FORMAT_S16 : +case AUDIO_FORMAT_U16 : bits16 =1 ;break ; -case AUD_FMT_S32 : -case AUD_FMT_U32 : +case AUDIO_FORMAT_S32 : +case AUDIO_FORMAT_U32 :dolog ("WAVE files can not handle 32bit formats\n" );return -1 ; + +case AUDIO_FORMAT_MAX : +abort (); } hdr[34 ] = bits16 ?0x10 :0x08 ;
@@ -224,7 +227,7 @@ static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...)static WAVConf glob_conf = { .settings.freq =44100 , .settings.nchannels =2 , - .settings.fmt =AUD_FMT_S16 , + .settings.fmt =AUDIO_FORMAT_S16 , .wav_path ="qemu.wav" };
audio/wavcapture.c +1 -1
@@ -135,7 +135,7 @@ int wav_start_capture (CaptureState *s, const char *path, int freq, as.freq = freq; as.nchannels =1 << stereo; - as.fmt = bits16 ?AUD_FMT_S16 :AUD_FMT_U8 ; + as.fmt = bits16 ?AUDIO_FORMAT_S16 :AUDIO_FORMAT_U8 ; as.endianness =0 ; ops.notify = wav_notify;
hw/arm/omap2.c +1 -1
@@ -269,7 +269,7 @@ static void omap_eac_format_update(struct omap_eac_s *s)* does I2S specify it? */ /* All register writes are 16 bits so we we store 16-bit samples * in the buffers regardless of AGCFR[B8_16] value. */ - fmt.fmt =AUD_FMT_U16 ; + fmt.fmt =AUDIO_FORMAT_U16 ; s->codec.in_voice =AUD_open_in (&s->codec.card, s->codec.in_voice,"eac.codec.in" , s, omap_eac_in_cb, &fmt);
hw/audio/ac97.c +1 -1
@@ -360,7 +360,7 @@ static void open_voice (AC97LinkState *s, int index, int freq) as.freq = freq; as.nchannels =2 ; - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; as.endianness =0 ;if (freq >0 ) {
hw/audio/adlib.c +1 -1
@@ -323,7 +323,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) as.freq = s->freq; as.nchannels =SHIFT ; - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; as.endianness =AUDIO_HOST_ENDIANNESS ;AUD_register_card ("adlib" , &s->card);
hw/audio/cs4231a.c +3 -3
@@ -284,7 +284,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)switch ((val >>5 ) & ((s->dregs[MODE_And_ID] &MODE2 ) ?7 :3 )) {case 0 : - as.fmt =AUD_FMT_U8 ; + as.fmt =AUDIO_FORMAT_U8 ; s->shift = as.nchannels ==2 ;break ;
@@ -294,7 +294,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)case 3 : s->tab = ALawDecompressTable; x_law: - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; as.endianness =AUDIO_HOST_ENDIANNESS ; s->shift = as.nchannels ==2 ;break ;
@@ -302,7 +302,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)case 6 : as.endianness =1 ;case 2 : - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; s->shift = as.nchannels;break ;
hw/audio/es1370.c +2 -2
@@ -414,14 +414,14 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl) i, new_freq,1 << (new_fmt &1 ), - (new_fmt &2 ) ?AUD_FMT_S16 :AUD_FMT_U8 , + (new_fmt &2 ) ?AUDIO_FORMAT_S16 :AUDIO_FORMAT_U8 , d->shift);if (new_freq) {struct audsettings as; as.freq = new_freq; as.nchannels =1 << (new_fmt &1 ); - as.fmt = (new_fmt &2 ) ?AUD_FMT_S16 :AUD_FMT_U8 ; + as.fmt = (new_fmt &2 ) ?AUDIO_FORMAT_S16 :AUDIO_FORMAT_U8 ; as.endianness =0 ;if (i ==ADC_CHANNEL ) {
hw/audio/gus.c +1 -1
@@ -242,7 +242,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp) as.freq = s->freq; as.nchannels =2 ; - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; as.endianness =GUS_ENDIANNESS ; s->voice = AUD_open_out (
hw/audio/hda-codec.c +9 -9
@@ -97,9 +97,9 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as) }switch (format &AC_FMT_BITS_MASK ) { -case AC_FMT_BITS_8 : as->fmt =AUD_FMT_S8 ;break ; -case AC_FMT_BITS_16 : as->fmt =AUD_FMT_S16 ;break ; -case AC_FMT_BITS_32 : as->fmt =AUD_FMT_S32 ;break ; +case AC_FMT_BITS_8 : as->fmt =AUDIO_FORMAT_S8 ;break ; +case AC_FMT_BITS_16 : as->fmt =AUDIO_FORMAT_S16 ;break ; +case AC_FMT_BITS_32 : as->fmt =AUDIO_FORMAT_S32 ;break ; } as->nchannels = ((format &AC_FMT_CHAN_MASK ) >>AC_FMT_CHAN_SHIFT ) +1 ;
@@ -128,12 +128,12 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)/* -------------------------------------------------------------------------- */ static const char *fmt2name[] = { - [AUD_FMT_U8 ] ="PCM-U8" , - [AUD_FMT_S8 ] ="PCM-S8" , - [AUD_FMT_U16 ] ="PCM-U16" , - [AUD_FMT_S16 ] ="PCM-S16" , - [AUD_FMT_U32 ] ="PCM-U32" , - [AUD_FMT_S32 ] ="PCM-S32" , + [AUDIO_FORMAT_U8 ] ="PCM-U8" , + [AUDIO_FORMAT_S8 ] ="PCM-S8" , + [AUDIO_FORMAT_U16 ] ="PCM-U16" , + [AUDIO_FORMAT_S16 ] ="PCM-S16" , + [AUDIO_FORMAT_U32 ] ="PCM-U32" , + [AUDIO_FORMAT_S32 ] ="PCM-S32" , };typedef struct HDAAudioState HDAAudioState ;
hw/audio/lm4549.c +3 -3
@@ -185,7 +185,7 @@ void lm4549_write(lm4549_state *s,struct audsettings as; as.freq = value; as.nchannels =2 ; - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; as.endianness =0 ; s->voice = AUD_open_out(
@@ -255,7 +255,7 @@ static int lm4549_post_load(void *opaque, int version_id)struct audsettings as; as.freq = freq; as.nchannels =2 ; - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; as.endianness =0 ; s->voice = AUD_open_out(
@@ -292,7 +292,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque)/* Open a default voice */ as.freq =48000 ; as.nchannels =2 ; - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; as.endianness =0 ; s->voice = AUD_open_out(
hw/audio/milkymist-ac97.c +1 -1
@@ -297,7 +297,7 @@ static int milkymist_ac97_init(SysBusDevice *dev) as.freq =48000 ; as.nchannels =2 ; - as.fmt =AUD_FMT_S16 ; + as.fmt =AUDIO_FORMAT_S16 ; as.endianness =1 ; s->voice_in = AUD_open_in(&s->card, s->voice_in,
hw/audio/pcspk.c +1 -1
@@ -112,7 +112,7 @@ static void pcspk_callback(void *opaque, int free)static int pcspk_audio_init (ISABus *bus) {PCSpkState *s = pcspk_state; -struct audsettings as = {PCSPK_SAMPLE_RATE ,1 ,AUD_FMT_U8 ,0 }; +struct audsettings as = {PCSPK_SAMPLE_RATE ,1 ,AUDIO_FORMAT_U8 ,0 };AUD_register_card (s_spk, &s->card);
hw/audio/sb16.c +7 -7
@@ -66,7 +66,7 @@ typedef struct SB16State {int fmt_stereo;int fmt_signed;int fmt_bits; -audfmt_e fmt; +AudioFormat fmt;int dma_auto;int block_size;int fifo;
@@ -221,7 +221,7 @@ static void continue_dma8 (SB16State *s)static void dma_cmd8 (SB16State *s,int mask,int dma_len) { - s->fmt =AUD_FMT_U8 ; + s->fmt =AUDIO_FORMAT_U8 ; s->use_hdma =0 ; s->fmt_bits =8 ; s->fmt_signed =0 ;
@@ -316,18 +316,18 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)if (16 == s->fmt_bits) {if (s->fmt_signed) { - s->fmt =AUD_FMT_S16 ; + s->fmt =AUDIO_FORMAT_S16 ; }else { - s->fmt =AUD_FMT_U16 ; + s->fmt =AUDIO_FORMAT_U16 ; } }else {if (s->fmt_signed) { - s->fmt =AUD_FMT_S8 ; + s->fmt =AUDIO_FORMAT_S8 ; }else { - s->fmt =AUD_FMT_U8 ; + s->fmt =AUDIO_FORMAT_U8 ; } }
@@ -839,7 +839,7 @@ static void legacy_reset (SB16State *s) as.freq = s->freq; as.nchannels =1 ; - as.fmt =AUD_FMT_U8 ; + as.fmt =AUDIO_FORMAT_U8 ; as.endianness =0 ; s->voice = AUD_open_out (
hw/audio/wm8750.c +2 -2
@@ -201,7 +201,7 @@ static void wm8750_set_format(WM8750State *s) in_fmt.endianness =0 ; in_fmt.nchannels =2 ; in_fmt.freq = s->adc_hz; - in_fmt.fmt =AUD_FMT_S16 ; + in_fmt.fmt =AUDIO_FORMAT_S16 ; s->adc_voice[0 ] =AUD_open_in (&s->card, s->adc_voice[0 ],CODEC ".input1" , s, wm8750_audio_in_cb, &in_fmt);
@@ -214,7 +214,7 @@ static void wm8750_set_format(WM8750State *s) out_fmt.endianness =0 ; out_fmt.nchannels =2 ; out_fmt.freq = s->dac_hz; - out_fmt.fmt =AUD_FMT_S16 ; + out_fmt.fmt =AUDIO_FORMAT_S16 ; s->dac_voice[0 ] =AUD_open_out (&s->card, s->dac_voice[0 ],CODEC ".speaker" , s, wm8750_audio_out_cb, &out_fmt);
hw/input/tsc210x.c +1 -1
@@ -315,7 +315,7 @@ static void tsc2102_audio_output_update(TSC210xState *s) fmt.endianness =0 ; fmt.nchannels =2 ; fmt.freq = s->codec.tx_rate; - fmt.fmt =AUD_FMT_S16 ; + fmt.fmt =AUDIO_FORMAT_S16 ; s->dac_voice[0 ] =AUD_open_out (&s->card, s->dac_voice[0 ],"tsc2102.sink" , s, (void *) tsc210x_audio_out_cb, &fmt);
hw/usb/dev-audio.c +1 -1
@@ -646,7 +646,7 @@ static void usb_audio_realize(USBDevice *dev, Error **errp) s->out.vol[1 ] =240 ;/* 0 dB */ s->out.as.freq =USBAUDIO_SAMPLE_RATE ; s->out.as.nchannels =2 ; - s->out.as.fmt =AUD_FMT_S16 ; + s->out.as.fmt =AUDIO_FORMAT_S16 ; s->out.as.endianness =0 ;streambuf_init (&s->out.buf, s->buffer);
ui/vnc.c +7 -7
@@ -2379,12 +2379,12 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)if (len ==4 )return 10 ;switch (read_u8 (data,4 )) { -case 0 : vs->as.fmt =AUD_FMT_U8 ;break ; -case 1 : vs->as.fmt =AUD_FMT_S8 ;break ; -case 2 : vs->as.fmt =AUD_FMT_U16 ;break ; -case 3 : vs->as.fmt =AUD_FMT_S16 ;break ; -case 4 : vs->as.fmt =AUD_FMT_U32 ;break ; -case 5 : vs->as.fmt =AUD_FMT_S32 ;break ; +case 0 : vs->as.fmt =AUDIO_FORMAT_U8 ;break ; +case 1 : vs->as.fmt =AUDIO_FORMAT_S8 ;break ; +case 2 : vs->as.fmt =AUDIO_FORMAT_U16 ;break ; +case 3 : vs->as.fmt =AUDIO_FORMAT_S16 ;break ; +case 4 : vs->as.fmt =AUDIO_FORMAT_U32 ;break ; +case 5 : vs->as.fmt =AUDIO_FORMAT_S32 ;break ;default :VNC_DEBUG ("Invalid audio format %d\n" ,read_u8 (data,4 ));vnc_client_error (vs);
@@ -3065,7 +3065,7 @@ void vnc_init_state(VncState *vs) vs->as.freq =44100 ; vs->as.nchannels =2 ; - vs->as.fmt =AUD_FMT_S16 ; + vs->as.fmt =AUDIO_FORMAT_S16 ; vs->as.endianness =0 ;qemu_mutex_init (&vs->output_mutex);
Signature · 1 line
2.4.3
Re: [Qemu-devel] [PATCH v2 5/6] audio: use qapi AudioFormat instead of audfmt_e
Quoted 6 lines · Zoltán
I had to include an enum for audio sampling formats into qapi, but that meant duplicating the
audfmt_eenum. This patch replacesaudfmt_eand 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_MAXcaused problems.
[...]
Quoted 4 lines
audio/alsaaudio.c +0
-0
[...]
Quoted 16 lines
audio/alsaaudio.c +4
-4@@ -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 ;
audio/alsaaudio.c static int alsa_open (int in, struct alsa_params_req *req, · line 657
Quoted 10 lines
audio/alsaaudio.c +5
-2-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?
Quoted 48 lines
audio/alsaaudio.c +0
-0} threshold = (conf->threshold * bytes_per_sec) /1000 ;audio/audio.c +7
-7@@ -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" ;
audio/audio.c static char *audio_alloc_prefix (const char *s) · line 243
Quoted 10 lines
audio/audio.c +4
-2-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.
Quoted 6 lines
audio/audio.c +1
-0+abort (); }dolog ("Bogus audfmt %d returning S16\n" , fmt);return "S16" ; }
[...]
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:
Quoted 31 lines
Quoted 6 lines · Zoltán
I had to include an enum for audio sampling formats into qapi, but that meant duplicating the
audfmt_eenum. This patch replacesaudfmt_eand 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_MAXcaused problems.[...]
Quoted 4 lines
audio/alsaaudio.c +0
-0[...]
Quoted 17 lines
audio/alsaaudio.c +4
-4@@ -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 ;
Quoted 11 lines
audio/alsaaudio.c static int alsa_open (int in, struct alsa_params_req *req, · line 657
Quoted 9 lines
audio/alsaaudio.c +5
-2-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.
Quoted 53 lines
Quoted 53 lines
audio/alsaaudio.c +0
-0} threshold = (conf->threshold * bytes_per_sec) /1000 ;audio/audio.c +8
-8@@ -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" ;
Quoted 7 lines
audio/audio.c static char *audio_alloc_prefix (const char *s) · line 243
Quoted 5 lines
audio/audio.c +3
-1-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.
Quoted 8 lines
Quoted 6 lines
audio/audio.c +1
-0+abort (); }dolog ("Bogus audfmt %d returning S16\n" , fmt);return "S16" ; }[...]
Re: [Qemu-devel] [PATCH v2 5/6] audio: use qapi AudioFormat instead of audfmt_e
Quoted 44 lines · Kővágó Zoltán
2015-06-17 10:01 keltezéssel, Markus Armbruster írta:
Quoted 31 lines
Quoted 6 lines · Zoltán
I had to include an enum for audio sampling formats into qapi, but that meant duplicating the
audfmt_eenum. This patch replacesaudfmt_eand 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_MAXcaused problems.[...]
Quoted 4 lines
audio/alsaaudio.c +0
-0[...]
Quoted 17 lines
audio/alsaaudio.c +4
-4@@ -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 ;Quoted 11 lines
audio/alsaaudio.c static int alsa_open (int in, struct alsa_params_req *req, · line 657
Quoted 9 lines
audio/alsaaudio.c +5
-2-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?
Quoted 1 line
Not under normal circumstances, but gcc warns otherwise.
Okay, sounds like another case of "default: abort();" to me :)
[...]
Re: [Qemu-devel] [PATCH v2 5/6] audio: use qapi AudioFormat instead of audfmt_e
Quoted 13 lines · Markus Armbruster
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
audio/alsaaudio.c +5
-2@@ -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 : + +case AUDIO_FORMAT_MAX : +break ;
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Can this happen?
Not under normal circumstances, but gcc warns otherwise.
Okay, sounds like another case of "default:
abort();" to me :)
gcc has the annoying habit that it can warn you about missing enum labels in a switch statement, but ONLY if you do not use a 'default:' label. Warning about missing labels is nice if you plan to add more enum values down the road (then the compiler helpfully points out all the code spots that need to deal with the new value) but with the drawback that non-enum values bypass the switch completely. So if you anticipate this set growing, then s/break/abort()/ is all the more you need. On the other hand, if the set is pretty much fixed, then switching to default: covers more cases including non-enum values assigned into obt->fmt.
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
PATCH v2 6/6 audio: -audiodev command line option
In reply to Kővágó, ZoltánThis 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.
---
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
audio/Makefile.objs +1 -1
@@ -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
audio/alsaaudio.c +82 -202
459 lines not on this page · raw message
audio/audio.c +204 -543
896 lines not on this page · raw message
audio/audio.h +20 -3
@@ -24,7 +24,10 @@#ifndef QEMU_AUDIO_H #define QEMU_AUDIO_H +#include <stdarg.h> #include "config-host.h" +#include "qapi-types.h" +#include "qemu/option.h" #include "qemu/queue.h" typedef void (*audio_callback_fn ) (void *opaque,int avail);
@@ -35,12 +38,21 @@ typedef void (*audio_callback_fn) (void *opaque, int avail);#define AUDIO_HOST_ENDIANNESS 0#endif -struct audsettings { +typedef struct audsettings {int freq;int nchannels;AudioFormat fmt;int endianness; -}; +}audsettings ; + +audsettings audiodev_to_audsettings (AudiodevPerDirectionOptions *pdo); +int audioformat_bytes_per_sample (AudioFormat fmt); +int audio_buffer_frames (AudiodevPerDirectionOptions *pdo, +audsettings *as,int def_usecs); +int audio_buffer_samples (AudiodevPerDirectionOptions *pdo, +audsettings *as,int def_usecs); +int audio_buffer_bytes (AudiodevPerDirectionOptions *pdo, +audsettings *as,int def_usecs); typedef enum { AUD_CNOTIFY_ENABLE,
@@ -77,10 +89,11 @@ typedef struct QEMUAudioTimeStamp {uint64_t old_ts; } QEMUAudioTimeStamp; +extern QemuOptsList qemu_audiodev_opts; + void AUD_vlog (const char *cap, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); void AUD_log (const char *cap, const char *fmt, ...) GCC_FMT_ATTR(2, 3); -void AUD_help (void );void AUD_register_card (const char *name,QEMUSoundCard *card);void AUD_remove_card (QEMUSoundCard *card); CaptureVoiceOut *AUD_add_capture (
@@ -154,4 +167,8 @@ static inline void *advance (void *p, int incr)int wav_start_capture (CaptureState *s,const char *path,int freq,int bits,int nchannels); +void audio_set_options (void ); +void audio_handle_legacy_opts (void ); +void audio_legacy_help (void ); +#endif /* audio.h */
audio/audio_int.h +5 -2
@@ -143,8 +143,7 @@ struct SWVoiceIn {struct audio_driver {const char *name;const char *descr; -struct audio_option *options; -void *(*init) (void ); +void *(*init) (Audiodev *);void (*fini) (void *);struct audio_pcm_ops *pcm_ops;int can_be_default;
@@ -190,6 +189,7 @@ struct SWVoiceCap {struct AudioState {struct audio_driver *drv; +Audiodev *dev;void *drv_opaque;QEMUTimer *ts;
@@ -200,6 +200,7 @@ struct AudioState {int nb_hw_voices_out;int nb_hw_voices_in;int vm_running; +int64_t period_ticks; };extern struct audio_driver no_audio_driver;
@@ -213,6 +214,8 @@ extern struct audio_driver pa_audio_driver;extern struct audio_driver spice_audio_driver;extern const struct mixeng_volume nominal_volume; +extern struct audio_driver *drvtab[]; +void audio_pcm_init_info (struct audio_pcm_info *info,struct audsettings *as);void audio_pcm_info_clear_buf (struct audio_pcm_info *info,void *buf,int len);
audio/audio_legacy.c new file +328 -0
328 lines not on this page · raw message
audio/audio_template.h +9 -4
@@ -302,8 +302,10 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)static HW *glue (audio_pcm_hw_add_ ,TYPE ) (struct audsettings *as) {HW *hw; +AudioState *s = &glob_audio_state; +AudiodevPerDirectionOptions *pdo = s->dev->TYPE; -if (glue (conf.fixed_,TYPE ).enabled &&glue (conf.fixed_,TYPE ).greedy) { +if (pdo->fixed_settings) { hw =glue (audio_pcm_hw_add_new_,TYPE ) (as);if (hw) {return hw;
@@ -331,9 +333,11 @@ static SW *glue (audio_pcm_create_voice_pair_, TYPE) (SW *sw;HW *hw;struct audsettings hw_as; +AudioState *s = &glob_audio_state; +AudiodevPerDirectionOptions *pdo = s->dev->TYPE; -if (glue (conf.fixed_,TYPE ).enabled) { - hw_as =glue (conf.fixed_,TYPE ).settings; +if (pdo->fixed_settings) { + hw_as =audiodev_to_audsettings (pdo); }else { hw_as = *as;
@@ -398,6 +402,7 @@ SW *glue (AUD_open_, TYPE) ( ) {AudioState *s = &glob_audio_state; +AudiodevPerDirectionOptions *pdo = s->dev->TYPE;if (audio_bug (AUDIO_FUNC , !card || !name || !callback_fn || !as)) { dolog ("card=%p name=%p callback_fn=%p as=%p\n",
@@ -422,7 +427,7 @@ SW *glue (AUD_open_, TYPE) (return sw; } -if (!glue (conf.fixed_,TYPE ).enabled && sw) { +if (!pdo->fixed_settings && sw) {glue (AUD_close_,TYPE ) (card, sw); sw =NULL ; }
audio/coreaudio.c +11 -38
100 lines not on this page · raw message
audio/dsound_template.h +3 -3
@@ -167,17 +167,18 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,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;DSCBUFFERDESC bd;DSCBCAPS bc; +AudiodevPerDirectionOptions *pdo = s->dev->in;#else const char *typ ="DAC" ;DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;DSBUFFERDESC bd;DSBCAPS bc; +AudiodevPerDirectionOptions *pdo = s->dev->out;#endif if (!s->FIELD2) {
@@ -193,8 +194,8 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,memset (&bd,0 ,sizeof (bd)); bd.dwSize =sizeof (bd); bd.lpwfxFormat = &wfx; + bd.dwBufferBytes =audio_buffer_bytes (pdo, as,92880 );#ifdef DSBTYPE_IN - bd.dwBufferBytes = conf->bufsize_in; hr = IDirectSoundCapture_CreateCaptureBuffer ( s->dsound_capture, &bd,
@@ -203,7 +204,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, );#else bd.dwFlags =DSBCAPS_STICKYFOCUS |DSBCAPS_GETCURRENTPOSITION2 ; - bd.dwBufferBytes = conf->bufsize_out; hr = IDirectSound_CreateSoundBuffer ( s->dsound, &bd,
audio/dsoundaudio.c +17 -43
123 lines not on this page · raw message
audio/noaudio.c +1 -2
@@ -134,7 +134,7 @@ static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)return 0 ; } -static void *no_audio_init (void ) +static void *no_audio_init (Audiodev *dev) {return &no_audio_init; }
@@ -161,7 +161,6 @@ static struct audio_pcm_ops no_pcm_ops = {struct audio_driver no_audio_driver = { .name ="none" , .descr ="Timer based audio emulation" , - .options =NULL , .init = no_audio_init, .fini = no_audio_fini, .pcm_ops = &no_pcm_ops,
audio/ossaudio.c +44 -111
302 lines not on this page · raw message
audio/paaudio.c +29 -52
184 lines not on this page · raw message
audio/sdlaudio.c +5 -19
@@ -44,18 +44,13 @@ typedef struct SDLVoiceOut {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;bool driver_created; +Audiodev *dev; } glob_sdl;typedef struct SDLAudioState SDLAudioState ;
@@ -347,7 +342,7 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as, req.freq = as->freq; req.format =aud_to_sdlfmt (as->fmt); req.channels = as->nchannels; - req.samples = conf.nb_samples; + req.samples =audio_buffer_samples (s->dev->out, as,11610 ); req.callback = sdl_callback; req.userdata = sdl;
@@ -391,7 +386,7 @@ static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...)return 0 ; } -static void *sdl_audio_init (void ) +static void *sdl_audio_init (Audiodev *dev) {SDLAudioState *s = &glob_sdl;if (s->driver_created) {
@@ -420,6 +415,7 @@ static void *sdl_audio_init (void) } s->driver_created = true; + s->dev = dev;return s; }
@@ -431,18 +427,9 @@ static void sdl_audio_fini (void *opaque)SDL_DestroyMutex (s->mutex);SDL_QuitSubSystem (SDL_INIT_AUDIO ); s->driver_created = false; + s->dev =NULL ; } -static struct audio_option sdl_options[] = { - { - .name ="SAMPLES" , - .tag =AUD_OPT_INT , - .valp = &conf.nb_samples, - .descr ="Size of SDL buffer in samples" - }, - {/* End of list */ } -}; -static struct audio_pcm_ops sdl_pcm_ops = { .init_out = sdl_init_out, .fini_out = sdl_fini_out,
@@ -454,7 +441,6 @@ static struct audio_pcm_ops sdl_pcm_ops = {struct audio_driver sdl_audio_driver = { .name ="sdl" , .descr ="SDL http://www.libsdl.org" , - .options = sdl_options, .init = sdl_audio_init, .fini = sdl_audio_fini, .pcm_ops = &sdl_pcm_ops,
audio/spiceaudio.c +1 -6
@@ -74,7 +74,7 @@ static const SpiceRecordInterface record_sif = { .base.minor_version = SPICE_INTERFACE_RECORD_MINOR, }; -static void *spice_audio_init (void ) +static void *spice_audio_init (Audiodev *dev) {if (!using_spice) {return NULL ;
@@ -370,10 +370,6 @@ static int line_in_ctl (HWVoiceIn *hw, int cmd, ...)return 0 ; } -static struct audio_option audio_options[] = { - {/* end of list */ }, -}; -static struct audio_pcm_ops audio_callbacks = { .init_out = line_out_init, .fini_out = line_out_fini,
@@ -391,7 +387,6 @@ static struct audio_pcm_ops audio_callbacks = {struct audio_driver spice_audio_driver = { .name ="spice" , .descr ="spice audio driver" , - .options = audio_options, .init = spice_audio_init, .fini = spice_audio_fini, .pcm_ops = &audio_callbacks,
audio/wavaudio.c +11 -50
107 lines not on this page · raw message
qemu-options.hx +215 -3
229 lines not on this page · raw message
vl.c +8 -1
@@ -2873,6 +2873,7 @@ int main(int argc, char **argv, char **envp)qemu_add_opts (&qemu_trace_opts);
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.4.3
Part of the diff is not shown here. View the raw message.
Re: [Qemu-devel] [PATCH v2 6/6] audio: -audiodev command line option
Quoted 4 lines · Zoltán
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.
Quoted 5 lines
Audio drivers now get an Audiodev * as config paramters, instead of the global
audio_optionstructs. There is some code inaudio/audio_legacy.cthat 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.
Quoted 2 lines
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?
How should the command line look like when multiple audio backends are supported?
Do we have a clear backward-compatible path from here to there?
[...]
Quoted 2 lines
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 6/6] audio: -audiodev command line option
2015-06-17 10:13 keltezéssel, Markus Armbruster írta:
Quoted 17 lines
Quoted 4 lines · Zoltán
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.
Quoted 5 lines
Audio drivers now get an Audiodev * as config paramters, instead of the global
audio_optionstructs. There is some code inaudio/audio_legacy.cthat 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).
Quoted 8 lines
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.
Quoted 2 lines
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.
Quoted 2 lines
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.
Quoted 2 lines
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).
Quoted 9 lines
[...]
Quoted 2 lines
18 files changed, 994 insertions(+), 1083 deletions(-)create mode 100644
audio/audio_legacy.cVery nice delta, but the size is a bit intimidating :)
[...]
Re: [Qemu-devel] [PATCH v2 6/6] audio: -audiodev command line option
Quoted 26 lines · Kővágó Zoltán
2015-06-17 10:13 keltezéssel, Markus Armbruster írta:
Quoted 25 lines
Quoted 5 lines · Zoltán
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.
Quoted 8 lines
Audio drivers now get an Audiodev * as config paramters, instead of the global
audio_optionstructs. There is some code inaudio/audio_legacy.cthat 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.
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
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.
Quoted 10 lines
Quoted 2 lines
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?
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.
Quoted 8 lines
Quoted 1 line
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?
Quoted 5 lines
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?
[...]
Re: [Qemu-devel] [PATCH v2 6/6] audio: -audiodev command line option
2015-06-17 14:27 keltezéssel, Markus Armbruster írta:
Quoted 51 lines
Quoted 26 lines · Kővágó Zoltán
2015-06-17 10:13 keltezéssel, Markus Armbruster írta:
Quoted 25 lines
Quoted 5 lines · Zoltán
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.
Quoted 8 lines
Audio drivers now get an Audiodev * as config paramters, instead of the global
audio_optionstructs. There is some code inaudio/audio_legacy.cthat 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.
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
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.
Quoted 10 lines
Quoted 2 lines
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.
Quoted 2 lines
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.)
Quoted 4 lines
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.
Quoted 11 lines
Quoted 9 lines
Quoted 2 lines
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".
Quoted 17 lines
Quoted 5 lines
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.
Quoted 7 lines
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 6/6] audio: -audiodev command line option
Quoted 53 lines · Kővágó Zoltán
2015-06-17 14:27 keltezéssel, Markus Armbruster írta:
Quoted 52 lines
Quoted 27 lines · Kővágó Zoltán
2015-06-17 10:13 keltezéssel, Markus Armbruster írta:
Quoted 26 lines
Quoted 5 lines · Zoltán
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.
Quoted 9 lines
Audio drivers now get an Audiodev * as config paramters, instead of the global
audio_optionstructs. There is some code inaudio/audio_legacy.cthat 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.
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
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.
Quoted 10 lines
Quoted 2 lines
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.
Quoted 5 lines
Quoted 2 lines
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.)
Understood.
Quoted 7 lines
Quoted 4 lines
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.
Let's make it mandatory for now. We can always change mandatory to optional, but not the other way round.
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 1 line
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).
Quoted 4 lines
Quoted 1 line
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".
Works for me.
Quoted 25 lines
Quoted 17 lines
Quoted 5 lines
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.
Quoted 7 lines
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?
Quoted 10 lines
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.
If we didn't have to do backwards compatibility, we'd make audiodev mandatory, wouldn't we?
Here's how I'd add back-compat to that baseline. audiodev becomes optional, but omitting it is deprecated. If you do, you implicitly use the legacy backend that takes its configuration from the environment. The legacy backend gets created when a frontend is using it.
If you think you got a better way to do it, the person to convince is Gerd.
I'll try to find time to experiment with flattening your QAPI schema, perhaps we can make things a bit simpler.
I'm glad you're taking care of turning our bizarro audio UI into something that actually fits in with the rest. Much appreciated!
Re: [Qemu-devel] [PATCH v2 6/6] audio: -audiodev command line option
Hi,
Quoted 7 lines
Here's how I'd add back-compat to that baseline. audiodev becomes optional, but omitting it is deprecated. If you do, you implicitly use the legacy backend that takes its configuration from the environment. The legacy backend gets created when a frontend is using it.
If you think you got a better way to do it, the person to convince is Gerd.
Approach makes sense to me. Either the old config scheme is active, for compatibility, or the new one. Allowing to mix old+new (use -audiodev, but don't specify the name to -device soundcard,audiodev=) is not needed.
cheers,
Gerd