When there are multiple <audio> backends specified, it is possible to
assign a specific one to the VNC server using
<graphics type='vnc'...>
<audio id='1'/>
</graphics>
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
docs/formatdomain.rst | 22 ++++++++++++++++++----
docs/schemas/domaincommon.rng | 11 ++++++++++-
src/conf/domain_conf.c | 32 ++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 1 +
4 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 0d1bdcb338..eccd89921b 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -5795,6 +5795,19 @@ interaction with the admin.
graphics type ``egl-headless`` (see below) which will instruct QEMU to
open and use drm nodes for OpenGL rendering.
+ A VNC server could be optionally mapped to the specific host audio
+ backend using the ``<audio>`` sub-element:
+
+ ::
+
+ <graphics type='vnc' ...>
+ <audio id='1'>
+ </graphics>
+
+ Where ``1`` is an id of the `audio device <#elementsAudio>`__. If no
+ ID is specified, then the default audio backend will be used.
+ :since:`Since 7.2.0, qemu`.
+
``spice`` :since:`Since 0.8.6`
Starts a SPICE server. The ``port`` attribute specifies the TCP port
number (with -1 as legacy syntax indicating that it should be
@@ -6800,8 +6813,8 @@ Valid values are:
Each ``sound`` element has an optional sub-element ``<address>`` which can tie
the device to a particular PCI slot, `documented above <#elementsAddress>`__.
-:since:`Since 6.7.0`, a sound device could be optionally mapped to the specific
-host audio backend using the ``<audio>`` sub-element:
+A sound device could be optionally mapped to the specific host audio
+backend using the ``<audio>`` sub-element:
::
@@ -6813,8 +6826,9 @@ host audio backend using the ``<audio>`` sub-element:
</devices>
...
-Where ``1`` is an id of the `audio device <#elementsAudio>`__.
-This is supported for bhyve only.
+Where ``1`` is an id of the `audio device <#elementsAudio>`__. If no
+ID is specified, then the default audio backend will be used.
+:since:`Since 6.7.0, bhyve; Since 7.2.0, qemu`.
:anchor:`<a id="elementsAudio"/>`
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index d27de58b42..330a600539 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3692,7 +3692,16 @@
<value>keep</value>
</attribute>
</optional>
- <ref name="listenElements"/>
+ <interleave>
+ <optional>
+ <element name="audio">
+ <attribute name="id">
+ <ref name="uint8"/>
+ </attribute>
+ </element>
+ </optional>
+ <ref name="listenElements"/>
+ </interleave>
</group>
<group>
<attribute name="type">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b2a232a8d0..c3a21b4c78 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13204,6 +13204,8 @@ virDomainGraphicsDefParseXMLVNC(virDomainGraphicsDefPtr def,
g_autofree char *websocketGenerated = virXMLPropString(node,
"websocketGenerated");
g_autofree char *sharePolicy = virXMLPropString(node, "sharePolicy");
g_autofree char *autoport = virXMLPropString(node, "autoport");
+ xmlNodePtr audioNode;
+ VIR_XPATH_NODE_AUTORESTORE(ctxt)
if (virDomainGraphicsListensParseXML(def, node, ctxt, flags) < 0)
return -1;
@@ -13262,6 +13264,24 @@ virDomainGraphicsDefParseXMLVNC(virDomainGraphicsDefPtr def,
def->data.vnc.keymap = virXMLPropString(node, "keymap");
+ ctxt->node = node;
+ audioNode = virXPathNode("./audio", ctxt);
+ if (audioNode) {
+ g_autofree char *tmp = NULL;
+ tmp = virXMLPropString(audioNode, "id");
+ if (!tmp) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing audio 'id' attribute"));
+ return -1;
+ }
+ if (virStrToLong_ui(tmp, NULL, 10, &def->data.vnc.audioId) < 0 ||
+ def->data.vnc.audioId == 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid audio 'id' value '%s'"),
tmp);
+ return -1;
+ }
+ }
+
if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth,
def->type) < 0)
return -1;
@@ -27529,6 +27549,18 @@ virDomainGraphicsDefFormat(virBufferPtr buf,
virDomainSpiceGLDefFormat(buf, def);
}
+ if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ if (!children) {
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 2);
+ children = true;
+ }
+
+ if (def->data.vnc.audioId > 0)
+ virBufferAsprintf(buf, "<audio id='%d'/>\n",
+ def->data.vnc.audioId);
+ }
+
if (children) {
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</graphics>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index cebbe3de0b..a3432f7e8a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1738,6 +1738,7 @@ struct _virDomainGraphicsDef {
char *keymap;
virDomainGraphicsAuthDef auth;
int sharePolicy;
+ unsigned int audioId;
} vnc;
struct {
char *display;
--
2.29.2