The current <audio> element only allows an "OSS" audio backend, as this is all that BHyve needed. This is now extended to cover most QEMU audio backends. These backends all have a variety of attributes they support, but this initial impl does the bare minimum, relying on built-in defaults for everything. The only QEMU backend omitted is "dsound" since the libvirt QEMU driver is not built on Windows platforms. The SDL audio driver names are based on the SDL 2.0 drivers. It is not intended to support SDL 1.2 drivers. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- docs/formatdomain.rst | 113 +++++++++++++++++++++++++++++----- docs/schemas/domaincommon.rng | 88 +++++++++++++++++++++----- src/bhyve/bhyve_command.c | 13 +++- src/conf/domain_conf.c | 109 +++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 22 +++++++ 5 files changed, 312 insertions(+), 33 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index e23bcc3e5a..0d1bdcb338 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -6822,32 +6822,117 @@ Audio devices ~~~~~~~~~~~~~ A virtual audio device corresponds to a host audio backend that is mapped -to the guest sound device. :since:`Since 6.7.0, bhyve only` +to the guest sound device. ``type`` The required ``type`` attribute specifies audio backend type. - Currently, the only supported value is 'oss'. + Currently, the supported values are 'none', 'alsa', 'coreaudio', + 'jack', 'oss', 'pulseaudio', 'sdl', 'spice', 'file'. ``id`` Integer id of the audio device. Must be greater than 0. -The 'oss' audio type supports additional configuration: +None audio backend +^^^^^^^^^^^^^^^^^^ + +The 'none' audio backend is a dummy backend that does not connect to +any host audio framework. It still allows a remote desktop server +like VNC to send and receive audio though. This is the default backend +when VNC graphics are enabled in QEMU. + +:since:`Since 7.2.0, qemu` + +ALSA audio backend +^^^^^^^^^^^^^^^^^^ + +The 'alsa' audio type uses the ALSA host audio device framework. + +:since:`Since 7.2.0, qemu` + +Coreaudio audio backend +^^^^^^^^^^^^^^^^^^^^^^^ + +The 'coreaudio' audio backend delegates to a CoreAudio host audio framework +for input and output on macOS. + +:since:`Since 7.2.0, qemu` + +Jack audio backend +^^^^^^^^^^^^^^^^^^ + +The 'jack' audio backend delegates to a Jack daemon for audio input +and output. + +:since:`Since 7.2.0, qemu` + +OSS audio backend +^^^^^^^^^^^^^^^^^ + +The 'oss' audio type uses the OSS host audio device framework. + +The following additional attributes are permitted on the ``<input>`` +and ``<output>`` elements + +* ``dev`` + + Path to the host device node to connect the backend to. A hypervisor + specific default applies if not specified. :: - ... - <devices> - <audio type='oss' id='1'> - <input dev='/dev/dsp0'/> - <output dev='/dev/dsp0'/> - </audio> - </devices> + <audio type='oss' id='1'> + <input dev='/dev/dsp0'/> + <output dev='/dev/dsp0'/> + </audio> -``input`` - Input device. The required ``dev`` attribute specifies device path. +:since:`Since 6.7.0, bhyve; Since 7.2.0, qemu` + +PulseAudio audio backend +^^^^^^^^^^^^^^^^^^^^^^^^ + +The 'pulseaudio' audio backend delegates to a PulseAudio daemon audio input +and output. + +:since:`Since 7.2.0, qemu` + +SDL audio backend +^^^^^^^^^^^^^^^^^ + +The 'sdl' audio backend delegates to the SDL library for audio input +and output. + +The following additional attributes are permitted on the ``<audio>`` +element + +* ``driver`` + + SDL audio driver. The ``name`` attribute specifies SDL driver name, + one of 'esd', 'alsa', 'arts', 'pulseaudio'. + +:: + + <audio type='sdl' id='1' driver='pulseaudio'/> + +:since:`Since 7.2.0, qemu` + +Spice audio backend +^^^^^^^^^^^^^^^^^^^ + +The 'spice' audio backend is similar to the 'none' backend in that +it does not connect to any host audio framework. It exclusively +allows a SPICE server to send and receive audio. This is the default +backend when SPICE graphics are enabled in QEMU. + +:since:`Since 7.2.0, qemu` + +File audio backend +^^^^^^^^^^^^^^^^^^ + +The 'file' audio backend is an output only driver which records +audio to a file. The file format is implementation defined, and +defaults to 'WAV' with QEMU. -``output`` - Output device. The required ``dev`` attribute specifies device path. +:since:`Since 7.2.0, qemu` :anchor:`<a id="elementsWatchdog"/>` diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index efa1806a3a..d27de58b42 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4527,23 +4527,77 @@ <attribute name="id"> <ref name="uint8"/> </attribute> - <attribute name="type"> - <choice> - <value>oss</value> - </choice> - </attribute> - <interleave> - <optional> - <element name="input"> - <ref name="audiooss"/> - </element> - </optional> - <optional> - <element name="output"> - <ref name="audiooss"/> - </element> - </optional> - </interleave> + <choice> + <group> + <attribute name="type"> + <value>none</value> + </attribute> + </group> + <group> + <attribute name="type"> + <value>alsa</value> + </attribute> + </group> + <group> + <attribute name="type"> + <value>coreaudio</value> + </attribute> + </group> + <group> + <attribute name="type"> + <value>jack</value> + </attribute> + </group> + <group> + <attribute name="type"> + <choice> + <value>oss</value> + </choice> + </attribute> + <interleave> + <optional> + <element name="input"> + <ref name="audiooss"/> + </element> + </optional> + <optional> + <element name="output"> + <ref name="audiooss"/> + </element> + </optional> + </interleave> + </group> + <group> + <attribute name="type"> + <value>pulseaudio</value> + </attribute> + </group> + <group> + <attribute name="type"> + <value>sdl</value> + </attribute> + <optional> + <attribute name="driver"> + <choice> + <value>esd</value> + <value>alsa</value> + <value>arts</value> + <value>pulseaudio</value> + </choice> + </attribute> + </optional> + </group> + <group> + <attribute name="type"> + <value>spice</value> + </attribute> + </group> + <group> + <attribute name="type"> + <value>file</value> + </attribute> + </group> + </choice> </element> </define> <define name="watchdog"> diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index e60a6bd393..b03a1f26b7 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -524,11 +524,22 @@ bhyveBuildSoundArgStr(const virDomainDef *def G_GNUC_UNUSED, break; - case VIR_DOMAIN_AUDIO_TYPE_LAST: + case VIR_DOMAIN_AUDIO_TYPE_NONE: + case VIR_DOMAIN_AUDIO_TYPE_ALSA: + case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO: + case VIR_DOMAIN_AUDIO_TYPE_JACK: + case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO: + case VIR_DOMAIN_AUDIO_TYPE_SDL: + case VIR_DOMAIN_AUDIO_TYPE_SPICE: + case VIR_DOMAIN_AUDIO_TYPE_FILE: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported audio backend '%s'"), virDomainAudioTypeTypeToString(audio->type)); return -1; + case VIR_DOMAIN_AUDIO_TYPE_LAST: + default: + virReportEnumRangeError(virDomainAudioType, def->type); + return -1; } } diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d5969c79a0..b2a232a8d0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -736,7 +736,24 @@ VIR_ENUM_IMPL(virDomainSoundModel, VIR_ENUM_IMPL(virDomainAudioType, VIR_DOMAIN_AUDIO_TYPE_LAST, + "none", + "alsa", + "coreaudio", + "jack", "oss", + "pulseaudio", + "sdl", + "spice", + "file", +); + +VIR_ENUM_IMPL(virDomainAudioSDLDriver, + VIR_DOMAIN_AUDIO_SDL_DRIVER_LAST, + "", + "esd", + "alsa", + "arts", + "pulseaudio", ); VIR_ENUM_IMPL(virDomainKeyWrapCipherName, @@ -2902,11 +2919,35 @@ virDomainAudioDefFree(virDomainAudioDefPtr def) return; switch ((virDomainAudioType) def->type) { + case VIR_DOMAIN_AUDIO_TYPE_NONE: + break; + + case VIR_DOMAIN_AUDIO_TYPE_ALSA: + break; + + case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO: + break; + + case VIR_DOMAIN_AUDIO_TYPE_JACK: + break; + case VIR_DOMAIN_AUDIO_TYPE_OSS: virDomainAudioIOOSSFree(&def->backend.oss.input); virDomainAudioIOOSSFree(&def->backend.oss.output); break; + case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO: + break; + + case VIR_DOMAIN_AUDIO_TYPE_SDL: + break; + + case VIR_DOMAIN_AUDIO_TYPE_SPICE: + break; + + case VIR_DOMAIN_AUDIO_TYPE_FILE: + break; + case VIR_DOMAIN_AUDIO_TYPE_LAST: break; } @@ -13924,6 +13965,18 @@ virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt G_GNUC_UNUSED, outputNode = virXPathNode("./output", ctxt); switch ((virDomainAudioType) def->type) { + case VIR_DOMAIN_AUDIO_TYPE_NONE: + break; + + case VIR_DOMAIN_AUDIO_TYPE_ALSA: + break; + + case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO: + break; + + case VIR_DOMAIN_AUDIO_TYPE_JACK: + break; + case VIR_DOMAIN_AUDIO_TYPE_OSS: if (inputNode) virDomainAudioOSSParse(&def->backend.oss.input, inputNode); @@ -13931,7 +13984,28 @@ virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt G_GNUC_UNUSED, virDomainAudioOSSParse(&def->backend.oss.output, outputNode); break; + case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO: + break; + + case VIR_DOMAIN_AUDIO_TYPE_SDL: { + g_autofree char *driver = virXMLPropString(node, "driver"); + if (driver && + (def->backend.sdl.driver = + virDomainAudioSDLDriverTypeFromString(driver)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown SDL driver '%s'"), driver); + goto error; + } + break; + } + + case VIR_DOMAIN_AUDIO_TYPE_SPICE: + case VIR_DOMAIN_AUDIO_TYPE_FILE: + break; + case VIR_DOMAIN_AUDIO_TYPE_LAST: + default: + virReportEnumRangeError(virDomainAudioType, def->type); break; } @@ -26434,11 +26508,44 @@ virDomainAudioDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "<audio id='%d' type='%s'", def->id, type); - switch (def->type) { + switch ((virDomainAudioType)def->type) { + case VIR_DOMAIN_AUDIO_TYPE_NONE: + break; + + case VIR_DOMAIN_AUDIO_TYPE_ALSA: + break; + + case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO: + break; + + case VIR_DOMAIN_AUDIO_TYPE_JACK: + break; + case VIR_DOMAIN_AUDIO_TYPE_OSS: virDomainAudioOSSFormat(&def->backend.oss.input, &inputBuf); virDomainAudioOSSFormat(&def->backend.oss.output, &outputBuf); break; + + case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO: + break; + + case VIR_DOMAIN_AUDIO_TYPE_SDL: + if (def->backend.sdl.driver) + virBufferAsprintf(buf, " driver='%s'", + virDomainAudioSDLDriverTypeToString( + def->backend.sdl.driver)); + break; + + case VIR_DOMAIN_AUDIO_TYPE_SPICE: + break; + + case VIR_DOMAIN_AUDIO_TYPE_FILE: + break; + + case VIR_DOMAIN_AUDIO_TYPE_LAST: + default: + virReportEnumRangeError(virDomainAudioType, def->type); + return -1; } virDomainAudioCommonFormat(&childBuf, &inputBuf, "input"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 977dd48cc3..cebbe3de0b 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1446,11 +1446,29 @@ struct _virDomainSoundDef { }; typedef enum { + VIR_DOMAIN_AUDIO_TYPE_NONE, + VIR_DOMAIN_AUDIO_TYPE_ALSA, + VIR_DOMAIN_AUDIO_TYPE_COREAUDIO, + VIR_DOMAIN_AUDIO_TYPE_JACK, VIR_DOMAIN_AUDIO_TYPE_OSS, + VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO, + VIR_DOMAIN_AUDIO_TYPE_SDL, + VIR_DOMAIN_AUDIO_TYPE_SPICE, + VIR_DOMAIN_AUDIO_TYPE_FILE, VIR_DOMAIN_AUDIO_TYPE_LAST } virDomainAudioType; +typedef enum { + VIR_DOMAIN_AUDIO_SDL_DRIVER_DEFAULT, + VIR_DOMAIN_AUDIO_SDL_DRIVER_ESD, + VIR_DOMAIN_AUDIO_SDL_DRIVER_ALSA, + VIR_DOMAIN_AUDIO_SDL_DRIVER_ARTS, + VIR_DOMAIN_AUDIO_SDL_DRIVER_PULSEAUDIO, + + VIR_DOMAIN_AUDIO_SDL_DRIVER_LAST +} virDomainAudioSDLDriver; + typedef struct _virDomainAudioIOOSS virDomainAudioIOOSS; struct _virDomainAudioIOOSS { char *dev; @@ -1466,6 +1484,9 @@ struct _virDomainAudioDef { virDomainAudioIOOSS input; virDomainAudioIOOSS output; } oss; + struct { + int driver; /* virDomainAudioSDLDriver */ + } sdl; } backend; }; @@ -3694,6 +3715,7 @@ VIR_ENUM_DECL(virDomainChrSpicevmc); VIR_ENUM_DECL(virDomainSoundCodec); VIR_ENUM_DECL(virDomainSoundModel); VIR_ENUM_DECL(virDomainAudioType); +VIR_ENUM_DECL(virDomainAudioSDLDriver); VIR_ENUM_DECL(virDomainKeyWrapCipherName); VIR_ENUM_DECL(virDomainMemballoonModel); VIR_ENUM_DECL(virDomainSmbiosMode); -- 2.29.2