~~~~~~~~~~~~~
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"/>`
<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">
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, audio->type);
+ return -1;
}
}
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,
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;
}
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);
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;
}
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");
};
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;
typedef virDomainAudioIOOSS *virDomainAudioIOOSSPtr;
struct _virDomainAudioIOOSS {
virDomainAudioIOOSS input;
virDomainAudioIOOSS output;
} oss;
+ struct {
+ int driver; /* virDomainAudioSDLDriver */
+ } sdl;
} backend;
};
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);