On Tue, Nov 07, 2023 at 13:55:22 +0100, Michal Privoznik wrote:
QEMU gained support for PipeWire audio backend (see QEMU commit
of v8.0.0-403-gc2d3d1c294). Its configuration knobs are basically
the same as pulseaudio's, except for PA's server name. Therefore,
a lot of code is copied over from pulseadio and fixed by
s/Pulse/Pipewire/ or s/pulseaudio/pipewire/.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
[...]
+PipeWire audio backend
+^^^^^^^^^^^^^^^^^^^^^^
+
+The ``pipewire`` audio backend delegates to a PipeWire daemon audio input and
+output.
+
+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="pipewire">
+ <input name="fish" streamName="food"
latency="100"/>
+ <output name="fish" streamName="food"
latency="200"/>
+ </audio>
+
+:since:`Since 9.4.0, qemu`
This is a bit stale ;)
+static int
+virDomainAudioPipewireAudioParse(virDomainAudioIOPipewireAudio *def,
+ xmlNodePtr node)
+{
+ def->name = virXMLPropString(node, "name");
+ def->streamName = virXMLPropString(node, "streamName");
+
+ if (virXMLPropUInt(node, "latency", 10, VIR_XML_PROP_NONE,
+ &def->latency) < 0)
You probably want VIR_XML_PROP_NONZERO, as ...
+ return -1;
+
+ return 0;
+}
[...]
+static void
+virDomainAudioPipewireAudioFormat(virDomainAudioIOPipewireAudio *def,
+ virBuffer *buf)
+{
+ virBufferEscapeString(buf, " name='%s'", def->name);
+ virBufferEscapeString(buf, " streamName='%s'",
def->streamName);
+ if (def->latency)
... 0 is considered as default.
+ virBufferAsprintf(buf, " latency='%u'",
def->latency);
+
+}
[...]
@@ -29267,6 +29321,16 @@
virDomainAudioIOSDLIsEqual(virDomainAudioIOSDL *this,
}
+static bool
+virDomainAudioIOPipewireAudioIsEqual(virDomainAudioIOPipewireAudio *this,
+ virDomainAudioIOPipewireAudio *that)
+{
+ return STREQ_NULLABLE(this->name, that->name) &&
+ STREQ_NULLABLE(this->streamName, that->streamName) &&
+ this->latency == that->latency;
'this' and 'that' share too much of a prefix to be easily visually
distinguishible .... but ...
+}
+
+
static bool
virDomainAudioBackendIsEqual(virDomainAudioDef *this,
virDomainAudioDef *that)
.... it seems to be prior art, unfortunately.
@@ -29327,6 +29391,12 @@
virDomainAudioBackendIsEqual(virDomainAudioDef *this,
case VIR_DOMAIN_AUDIO_TYPE_FILE:
return STREQ_NULLABLE(this->backend.file.path, that->backend.file.path);
+ case VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE:
+ return
virDomainAudioIOPipewireAudioIsEqual(&this->backend.pipewire.input,
+ &that->backend.pipewire.input)
&&
+ virDomainAudioIOPipewireAudioIsEqual(&this->backend.pipewire.output,
+ &that->backend.pipewire.output);
The alignment here is rather funky. Did the mailing list mess this up?
+
case VIR_DOMAIN_AUDIO_TYPE_DBUS:
case VIR_DOMAIN_AUDIO_TYPE_LAST:
default:
With the default of the latency properly handled:
Reviewed-by: Peter Krempa <pkrempa(a)redhat.com>