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@xxxxxxxxxx> --- 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