This pulls in the remaining QEMU audio backend specific settings to the
XML schema.
<audio id="1" type="alsa">
<input dev="/dev/dsp0"/>
<output dev="/dev/dsp1"/>
</audio>
<audio id="1" type="coreaudio">
<input bufferCount="50"/>
<output bufferCount="42"/>
</audio>
<audio id="1" type="file" path="audio.wav"/>
<audio id="1" type="jack">
<input serverName="fish" clientName="food"
connectPorts="yum"/>
<output serverName="fish" clientName="food"
connectPorts="yum"/>
</audio>
<audio id="1" type="oss" tryMMap="yes"
exclusive="yes" dspPolicy="3">
<input dev="/dev/dsp0" bufferCount="50"
tryPoll="yes"/>
<output dev="/dev/dsp1" bufferCount="30"
tryPoll="no"/>
</audio>
<audio id="1" type="pulseaudio"
serverName="acme.example.org">
<input name="fish" streamName="food"
latency="100"/>
<output name="fish" streamName="food"
latency="200"/>
</audio>
<audio type='sdl' id='1' driver='pulseaudio'>
<input bufferCount='40'/>
<output bufferCount='40'/>
</audio>
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
docs/formatdomain.rst | 140 +++++++++++++++++-
docs/schemas/domaincommon.rng | 75 ++++++++++
src/conf/domain_conf.c | 271 +++++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 57 +++++++
4 files changed, 538 insertions(+), 5 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index d773341c66..2b1d045a70 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -6924,6 +6924,21 @@ ALSA audio backend
The 'alsa' audio type uses the ALSA 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.
+
+::
+
+ <audio id="1" type="alsa">
+ <input dev="/dev/dsp0"/>
+ <output dev="/dev/dsp1"/>
+ </audio>
+
:since:`Since 7.2.0, qemu`
Coreaudio audio backend
@@ -6932,6 +6947,21 @@ Coreaudio audio backend
The 'coreaudio' audio backend delegates to a CoreAudio host audio framework
for input and output on macOS.
+The following additional attributes are permitted on the ``<input>``
+and ``<output>`` elements
+
+* ``bufferCount``
+
+ The number of buffers. It is recommended to set the ``bufferLength``
+ attribute at the same time.
+
+::
+
+ <audio id="1" type="coreaudio">
+ <input bufferCount="50"/>
+ <output bufferCount="42"/>
+ </audio>
+
:since:`Since 7.2.0, qemu`
Jack audio backend
@@ -6940,6 +6970,34 @@ Jack audio backend
The 'jack' audio backend delegates to a Jack daemon for audio input
and output.
+The following additional attributes are permitted on the ``<input>``
+and ``<output>`` elements
+
+* ``serverName``
+
+ Select the Jack server instance to connect to.
+
+* ``clientName``
+
+ The client name to identify as. The server may modify this to
+ ensure uniqueness unless ``exactName`` is enabled
+
+* ``connectPorts``
+
+ A regular expression of Jack client port names to monitor and
+ connect to.
+
+* ``exactName``
+
+ Use the exact ``clientName`` requested
+
+::
+
+ <audio id="1" type="jack">
+ <input serverName="fish" clientName="food"
connectPorts="system:capture_[13]" exactName="yes"/>
+ <output serverName="fish" clientName="food"
connectPorts="system:playback_[13]" exactName="yes"/>
+ </audio>
+
:since:`Since 7.2.0, qemu`
OSS audio backend
@@ -6947,6 +7005,23 @@ OSS audio backend
The 'oss' audio type uses the OSS host audio device framework.
+The following additional attributes are permitted on the ``<audio>``
+element
+
+* ``tryMMap``
+
+ Attempt to use mmap for data transfer
+
+* ``exclusive``
+
+ Enforce exclusive access to the host device
+
+* ``dspPolicy``
+
+ Set the timing policy of the device, values between -1 and 10.
+ Smaller numbers result in lower latency but higher CPU usage.
+ A negatve value requests use of fragment mode.
+
The following additional attributes are permitted on the ``<input>``
and ``<output>`` elements
@@ -6955,11 +7030,20 @@ and ``<output>`` elements
Path to the host device node to connect the backend to. A hypervisor
specific default applies if not specified.
+* ``bufferCount``
+
+ The number of buffers. It is recommended to set the ``bufferLength``
+ attribute at the same time.
+
+* ``tryPoll``
+
+ Attempt to use polling mode
+
::
- <audio type='oss' id='1'>
- <input dev='/dev/dsp0'/>
- <output dev='/dev/dsp0'/>
+ <audio type='oss' id='1' tryMMap='yes'
exclusive='yes' dspPolicy='4'>
+ <input dev='/dev/dsp0' bufferCount='40'
tryPoll='yes'/>
+ <output dev='/dev/dsp0' bufferCount='40'
tryPoll='yes'/>
</audio>
:since:`Since 6.7.0, bhyve; Since 7.2.0, qemu`
@@ -6970,6 +7054,35 @@ PulseAudio audio backend
The 'pulseaudio' audio backend delegates to a PulseAudio daemon audio input
and output.
+The following additional attributes are permitted on the ``<audio>``
+element
+
+* ``serverName``
+
+ Hostname of the PulseAudio server
+
+The following additional attributes are permitted on the ``<input>``
+and ``<output>`` elements
+
+* ``name``
+
+ The sink/source name to use
+
+* ``streamName``
+
+ The name to identify the stream associated with the VM
+
+* ``latency``
+
+ Desired latency for the server to target in microseconds
+
+::
+
+ <audio id="1" type="pulseaudio"
serverName="acme.example.org">
+ <input name="fish" streamName="food"
latency="100"/>
+ <output name="fish" streamName="food"
latency="200"/>
+ </audio>
+
:since:`Since 7.2.0, qemu`
SDL audio backend
@@ -6986,9 +7099,20 @@ element
SDL audio driver. The ``name`` attribute specifies SDL driver name,
one of 'esd', 'alsa', 'arts', 'pulseaudio'.
+The following additional attributes are permitted on the ``<input>``
+and ``<output>`` elements
+
+* ``bufferCount``
+
+ The number of buffers. It is recommended to set the ``bufferLength``
+ attribute at the same time.
+
::
- <audio type='sdl' id='1' driver='pulseaudio'/>
+ <audio type='sdl' id='1' driver='pulseaudio'>
+ <input bufferCount='40'/>
+ <output bufferCount='40'/>
+ </audio>
:since:`Since 7.2.0, qemu`
@@ -7000,6 +7124,10 @@ 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.
+::
+
+ <audio type='spice' id='1'/>
+
:since:`Since 7.2.0, qemu`
File audio backend
@@ -7009,6 +7137,10 @@ 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.
+::
+
+ <audio id="1" type="file" path="audio.wav"/>
+
:since:`Since 7.2.0, qemu`
:anchor:`<a id="elementsWatchdog"/>`
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 82fc74ca00..84a4910203 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4603,6 +4603,26 @@
<define name="audiojack">
<ref name="audiocommonattr"/>
+ <optional>
+ <attribute name="serverName">
+ <data type="string"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="clientName">
+ <data type="string"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="connectPorts">
+ <data type="string"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="exactName">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<ref name="audiocommonchild"/>
</define>
@@ -4613,16 +4633,46 @@
<ref name="filePath"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="bufferCount">
+ <ref name="uint32"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="tryPoll">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<ref name="audiocommonchild"/>
</define>
<define name="audiopulseaudio">
<ref name="audiocommonattr"/>
+ <optional>
+ <attribute name="name">
+ <data type="string"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="streamName">
+ <data type="string"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="latency">
+ <ref name="uint32"/>
+ </attribute>
+ </optional>
<ref name="audiocommonchild"/>
</define>
<define name="audiosdl">
<ref name="audiocommonattr"/>
+ <optional>
+ <attribute name="bufferCount">
+ <ref name="uint32"/>
+ </attribute>
+ </optional>
<ref name="audiocommonchild"/>
</define>
@@ -4716,6 +4766,21 @@
<value>oss</value>
</choice>
</attribute>
+ <optional>
+ <attribute name="tryMMap">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="exclusive">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="dspPolicy">
+ <data type="int"/>
+ </attribute>
+ </optional>
<interleave>
<optional>
<element name="input">
@@ -4733,6 +4798,11 @@
<attribute name="type">
<value>pulseaudio</value>
</attribute>
+ <optional>
+ <attribute name="serverName">
+ <data type="string"/>
+ </attribute>
+ </optional>
<interleave>
<optional>
<element name="input">
@@ -4794,6 +4864,11 @@
<attribute name="type">
<value>file</value>
</attribute>
+ <optional>
+ <attribute name="path">
+ <ref name="filePath"/>
+ </attribute>
+ </optional>
<interleave>
<optional>
<element name="input">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5936f5937f..71bd2d06db 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2918,12 +2918,33 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def)
g_free(def);
}
+static void
+virDomainAudioIOALSAFree(virDomainAudioIOALSA *def)
+{
+ g_free(def->dev);
+}
+
+static void
+virDomainAudioIOJackFree(virDomainAudioIOJack *def)
+{
+ g_free(def->serverName);
+ g_free(def->clientName);
+ g_free(def->connectPorts);
+}
+
static void
virDomainAudioIOOSSFree(virDomainAudioIOOSS *def)
{
g_free(def->dev);
}
+static void
+virDomainAudioIOPulseAudioFree(virDomainAudioIOPulseAudio *def)
+{
+ g_free(def->name);
+ g_free(def->streamName);
+}
+
void
virDomainAudioDefFree(virDomainAudioDefPtr def)
{
@@ -2935,12 +2956,16 @@ virDomainAudioDefFree(virDomainAudioDefPtr def)
break;
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
+ virDomainAudioIOALSAFree(&def->backend.alsa.input);
+ virDomainAudioIOALSAFree(&def->backend.alsa.output);
break;
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
break;
case VIR_DOMAIN_AUDIO_TYPE_JACK:
+ virDomainAudioIOJackFree(&def->backend.jack.input);
+ virDomainAudioIOJackFree(&def->backend.jack.output);
break;
case VIR_DOMAIN_AUDIO_TYPE_OSS:
@@ -2949,6 +2974,9 @@ virDomainAudioDefFree(virDomainAudioDefPtr def)
break;
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
+ virDomainAudioIOPulseAudioFree(&def->backend.pulseaudio.input);
+ virDomainAudioIOPulseAudioFree(&def->backend.pulseaudio.output);
+ g_free(def->backend.pulseaudio.serverName);
break;
case VIR_DOMAIN_AUDIO_TYPE_SDL:
@@ -2958,6 +2986,7 @@ virDomainAudioDefFree(virDomainAudioDefPtr def)
break;
case VIR_DOMAIN_AUDIO_TYPE_FILE:
+ g_free(def->backend.file.path);
break;
case VIR_DOMAIN_AUDIO_TYPE_LAST:
@@ -14036,12 +14065,118 @@ virDomainAudioCommonParse(virDomainAudioIOCommon *def,
}
+static void
+virDomainAudioALSAParse(virDomainAudioIOALSA *def,
+ xmlNodePtr node)
+{
+ def->dev = virXMLPropString(node, "dev");
+}
+
+
+static int
+virDomainAudioCoreAudioParse(virDomainAudioIOCoreAudio *def,
+ xmlNodePtr node)
+{
+ g_autofree char *bufferCount = virXMLPropString(node, "bufferCount");
+
+ if (bufferCount &&
+ virStrToLong_ui(bufferCount, NULL, 10,
+ &def->bufferCount) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("cannot parse 'bufferCount' value
'%s'"), bufferCount);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+virDomainAudioJackParse(virDomainAudioIOJack *def,
+ xmlNodePtr node)
+{
+ g_autofree char *exactName = virXMLPropString(node, "exactName");
+
+ def->serverName = virXMLPropString(node, "serverName");
+ def->clientName = virXMLPropString(node, "clientName");
+ def->connectPorts = virXMLPropString(node, "connectPorts");
+
+ if (exactName &&
+ ((def->exactName =
+ virTristateBoolTypeFromString(exactName)) <= 0)) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown 'exactName' value '%s'"),
exactName);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
virDomainAudioOSSParse(virDomainAudioIOOSS *def,
xmlNodePtr node)
{
+ g_autofree char *tryPoll = virXMLPropString(node, "tryPoll");
+ g_autofree char *bufferCount = virXMLPropString(node, "bufferCount");
+
def->dev = virXMLPropString(node, "dev");
+ if (tryPoll &&
+ ((def->tryPoll =
+ virTristateBoolTypeFromString(tryPoll)) <= 0)) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown 'tryPoll' value '%s'"),
tryPoll);
+ return -1;
+ }
+
+ if (bufferCount &&
+ virStrToLong_ui(bufferCount, NULL, 10,
+ &def->bufferCount) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("cannot parse 'bufferCount' value
'%s'"), bufferCount);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+virDomainAudioPulseAudioParse(virDomainAudioIOPulseAudio *def,
+ xmlNodePtr node)
+{
+ g_autofree char *latency = virXMLPropString(node, "latency");
+
+ def->name = virXMLPropString(node, "name");
+ def->streamName = virXMLPropString(node, "streamName");
+
+ if (latency &&
+ virStrToLong_ui(latency, NULL, 10,
+ &def->latency) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("cannot parse 'latency' value '%s'"),
latency);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+virDomainAudioSDLParse(virDomainAudioIOSDL *def,
+ xmlNodePtr node)
+{
+ g_autofree char *bufferCount = virXMLPropString(node, "bufferCount");
+
+ if (bufferCount &&
+ virStrToLong_ui(bufferCount, NULL, 10,
+ &def->bufferCount) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("cannot parse 'bufferCount' value
'%s'"), bufferCount);
+ return -1;
+ }
+
return 0;
}
@@ -14099,22 +14234,69 @@ virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt
G_GNUC_UNUSED,
break;
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
+ if (inputNode)
+ virDomainAudioALSAParse(&def->backend.alsa.input, inputNode);
+ if (outputNode)
+ virDomainAudioALSAParse(&def->backend.alsa.output, outputNode);
break;
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
+ if (inputNode)
+ virDomainAudioCoreAudioParse(&def->backend.coreaudio.input,
inputNode);
+ if (outputNode)
+ virDomainAudioCoreAudioParse(&def->backend.coreaudio.output,
outputNode);
break;
case VIR_DOMAIN_AUDIO_TYPE_JACK:
+ if (inputNode)
+ virDomainAudioJackParse(&def->backend.jack.input, inputNode);
+ if (outputNode)
+ virDomainAudioJackParse(&def->backend.jack.output, outputNode);
break;
- case VIR_DOMAIN_AUDIO_TYPE_OSS:
+ case VIR_DOMAIN_AUDIO_TYPE_OSS: {
+ g_autofree char *tryMMap = virXMLPropString(node, "tryMMap");
+ g_autofree char *exclusive = virXMLPropString(node, "exclusive");
+ g_autofree char *dspPolicy = virXMLPropString(node, "dspPolicy");
+
+ if (tryMMap && ((def->backend.oss.tryMMap =
+ virTristateBoolTypeFromString(tryMMap)) <= 0)) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown 'tryMMap' value '%s'"),
tryMMap);
+ goto error;
+ }
+
+ if (exclusive && ((def->backend.oss.exclusive =
+ virTristateBoolTypeFromString(exclusive)) <= 0)) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown 'exclusive' value '%s'"),
exclusive);
+ goto error;
+ }
+
+ if (dspPolicy) {
+ if (virStrToLong_i(dspPolicy, NULL, 10,
+ &def->backend.oss.dspPolicy) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("cannot parse 'dspPolicy' value
'%s'"), dspPolicy);
+ goto error;
+ }
+ def->backend.oss.dspPolicySet = true;
+ }
+
if (inputNode)
virDomainAudioOSSParse(&def->backend.oss.input, inputNode);
if (outputNode)
virDomainAudioOSSParse(&def->backend.oss.output, outputNode);
break;
+ }
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
+ def->backend.pulseaudio.serverName = virXMLPropString(node,
"serverName");
+
+ if (inputNode)
+ virDomainAudioPulseAudioParse(&def->backend.pulseaudio.input,
inputNode);
+ if (outputNode)
+ virDomainAudioPulseAudioParse(&def->backend.pulseaudio.output,
outputNode);
break;
case VIR_DOMAIN_AUDIO_TYPE_SDL: {
@@ -14126,6 +14308,11 @@ virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt
G_GNUC_UNUSED,
_("unknown SDL driver '%s'"), driver);
goto error;
}
+
+ if (inputNode)
+ virDomainAudioSDLParse(&def->backend.sdl.input, inputNode);
+ if (outputNode)
+ virDomainAudioSDLParse(&def->backend.sdl.output, outputNode);
break;
}
@@ -14133,6 +14320,7 @@ virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt
G_GNUC_UNUSED,
break;
case VIR_DOMAIN_AUDIO_TYPE_FILE:
+ def->backend.file.path = virXMLPropString(node, "path");
break;
case VIR_DOMAIN_AUDIO_TYPE_LAST:
@@ -26656,11 +26844,68 @@ virDomainAudioCommonFormat(virDomainAudioIOCommon *def,
}
}
+
+static void
+virDomainAudioALSAFormat(virDomainAudioIOALSA *def,
+ virBufferPtr buf)
+{
+ virBufferEscapeString(buf, " dev='%s'", def->dev);
+}
+
+
+static void
+virDomainAudioCoreAudioFormat(virDomainAudioIOCoreAudio *def,
+ virBufferPtr buf)
+{
+ if (def->bufferCount)
+ virBufferAsprintf(buf, " bufferCount='%u'",
def->bufferCount);
+}
+
+
+static void
+virDomainAudioJackFormat(virDomainAudioIOJack *def,
+ virBufferPtr buf)
+{
+ virBufferEscapeString(buf, " serverName='%s'",
def->serverName);
+ virBufferEscapeString(buf, " clientName='%s'",
def->clientName);
+ virBufferEscapeString(buf, " connectPorts='%s'",
def->connectPorts);
+ if (def->exactName)
+ virBufferAsprintf(buf, " exactName='%s'",
+ virTristateBoolTypeToString(def->exactName));
+}
+
+
static void
virDomainAudioOSSFormat(virDomainAudioIOOSS *def,
virBufferPtr buf)
{
virBufferEscapeString(buf, " dev='%s'", def->dev);
+ if (def->bufferCount)
+ virBufferAsprintf(buf, " bufferCount='%u'",
def->bufferCount);
+ if (def->tryPoll)
+ virBufferAsprintf(buf, " tryPoll='%s'",
+ virTristateBoolTypeToString(def->tryPoll));
+}
+
+
+static void
+virDomainAudioPulseAudioFormat(virDomainAudioIOPulseAudio *def,
+ virBufferPtr buf)
+{
+ virBufferEscapeString(buf, " name='%s'", def->name);
+ virBufferEscapeString(buf, " streamName='%s'",
def->streamName);
+ if (def->latency)
+ virBufferAsprintf(buf, " latency='%u'", def->latency);
+
+}
+
+
+static void
+virDomainAudioSDLFormat(virDomainAudioIOSDL *def,
+ virBufferPtr buf)
+{
+ if (def->bufferCount)
+ virBufferAsprintf(buf, " bufferCount='%u'",
def->bufferCount);
}
@@ -26686,20 +26931,40 @@ virDomainAudioDefFormat(virBufferPtr buf,
break;
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
+ virDomainAudioALSAFormat(&def->backend.alsa.input, &inputBuf);
+ virDomainAudioALSAFormat(&def->backend.alsa.output, &outputBuf);
break;
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
+ virDomainAudioCoreAudioFormat(&def->backend.coreaudio.input,
&inputBuf);
+ virDomainAudioCoreAudioFormat(&def->backend.coreaudio.output,
&outputBuf);
break;
case VIR_DOMAIN_AUDIO_TYPE_JACK:
+ virDomainAudioJackFormat(&def->backend.jack.input, &inputBuf);
+ virDomainAudioJackFormat(&def->backend.jack.output, &outputBuf);
break;
case VIR_DOMAIN_AUDIO_TYPE_OSS:
+ if (def->backend.oss.tryMMap)
+ virBufferAsprintf(buf, " tryMMap='%s'",
+ virTristateBoolTypeToString(def->backend.oss.tryMMap));
+ if (def->backend.oss.exclusive)
+ virBufferAsprintf(buf, " exclusive='%s'",
+
virTristateBoolTypeToString(def->backend.oss.exclusive));
+ if (def->backend.oss.dspPolicySet)
+ virBufferAsprintf(buf, " dspPolicy='%d'",
def->backend.oss.dspPolicy);
+
virDomainAudioOSSFormat(&def->backend.oss.input, &inputBuf);
virDomainAudioOSSFormat(&def->backend.oss.output, &outputBuf);
break;
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
+ virBufferEscapeString(buf, " serverName='%s'",
+ def->backend.pulseaudio.serverName);
+
+ virDomainAudioPulseAudioFormat(&def->backend.pulseaudio.input,
&inputBuf);
+ virDomainAudioPulseAudioFormat(&def->backend.pulseaudio.output,
&outputBuf);
break;
case VIR_DOMAIN_AUDIO_TYPE_SDL:
@@ -26707,12 +26972,16 @@ virDomainAudioDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " driver='%s'",
virDomainAudioSDLDriverTypeToString(
def->backend.sdl.driver));
+
+ virDomainAudioSDLFormat(&def->backend.sdl.input, &inputBuf);
+ virDomainAudioSDLFormat(&def->backend.sdl.output, &outputBuf);
break;
case VIR_DOMAIN_AUDIO_TYPE_SPICE:
break;
case VIR_DOMAIN_AUDIO_TYPE_FILE:
+ virBufferEscapeString(buf, " path='%s'",
def->backend.file.path);
break;
case VIR_DOMAIN_AUDIO_TYPE_LAST:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4ccadbaf37..2a174a60cf 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1493,10 +1493,41 @@ struct _virDomainAudioIOCommon {
unsigned int bufferLength; /* milliseconds */
};
+typedef struct _virDomainAudioIOALSA virDomainAudioIOALSA;
+struct _virDomainAudioIOALSA {
+ char *dev;
+};
+
+typedef struct _virDomainAudioIOCoreAudio virDomainAudioIOCoreAudio;
+struct _virDomainAudioIOCoreAudio {
+ unsigned int bufferCount;
+};
+
+typedef struct _virDomainAudioIOJack virDomainAudioIOJack;
+struct _virDomainAudioIOJack {
+ char *serverName;
+ char *clientName;
+ char *connectPorts;
+ virTristateBool exactName;
+};
typedef struct _virDomainAudioIOOSS virDomainAudioIOOSS;
struct _virDomainAudioIOOSS {
char *dev;
+ unsigned int bufferCount;
+ virTristateBool tryPoll;
+};
+
+typedef struct _virDomainAudioIOPulseAudio virDomainAudioIOPulseAudio;
+struct _virDomainAudioIOPulseAudio {
+ char *name;
+ char *streamName;
+ unsigned int latency;
+};
+
+typedef struct _virDomainAudioIOSDL virDomainAudioIOSDL;
+struct _virDomainAudioIOSDL {
+ unsigned int bufferCount;
};
struct _virDomainAudioDef {
@@ -1507,13 +1538,39 @@ struct _virDomainAudioDef {
virDomainAudioIOCommon input;
virDomainAudioIOCommon output;
union {
+ struct {
+ virDomainAudioIOALSA input;
+ virDomainAudioIOALSA output;
+ } alsa;
+ struct {
+ virDomainAudioIOCoreAudio input;
+ virDomainAudioIOCoreAudio output;
+ } coreaudio;
+ struct {
+ virDomainAudioIOJack input;
+ virDomainAudioIOJack output;
+ } jack;
struct {
virDomainAudioIOOSS input;
virDomainAudioIOOSS output;
+ virTristateBool tryMMap;
+ virTristateBool exclusive;
+ bool dspPolicySet;
+ int dspPolicy;
} oss;
struct {
+ virDomainAudioIOPulseAudio input;
+ virDomainAudioIOPulseAudio output;
+ char *serverName;
+ } pulseaudio;
+ struct {
+ virDomainAudioIOSDL input;
+ virDomainAudioIOSDL output;
int driver; /* virDomainAudioSDLDriver */
} sdl;
+ struct {
+ char *path;
+ } file;
} backend;
};
--
2.29.2