[PATCH v2 1/3] conf: Introduce pipewire audio backend

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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/.

There's one ley difference to PA though: pipewire daemon is
usually on per user basis (just like our qemu:///session).
Therefore, introduce this 'runtimeDir' attribute, which allows
specifying path to pipewire daemon socket (useful for
qemu:///system for instance).

Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx>
---
 docs/formatdomain.rst                         | 46 +++++++++++-
 src/conf/domain_conf.c                        | 73 +++++++++++++++++++
 src/conf/domain_conf.h                        | 13 ++++
 src/conf/schemas/domaincommon.rng             | 42 +++++++++++
 src/qemu/qemu_command.c                       |  2 +
 src/qemu/qemu_validate.c                      |  1 +
 .../qemuxml2argvdata/audio-pipewire-best.xml  | 43 +++++++++++
 .../qemuxml2argvdata/audio-pipewire-full.xml  | 43 +++++++++++
 .../audio-pipewire-minimal.xml                | 36 +++++++++
 .../audio-pipewire-best.x86_64-latest.xml     | 46 ++++++++++++
 .../audio-pipewire-full.x86_64-latest.xml     | 46 ++++++++++++
 .../audio-pipewire-minimal.x86_64-latest.xml  | 39 ++++++++++
 tests/qemuxml2xmltest.c                       |  3 +
 13 files changed, 431 insertions(+), 2 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/audio-pipewire-best.xml
 create mode 100644 tests/qemuxml2argvdata/audio-pipewire-full.xml
 create mode 100644 tests/qemuxml2argvdata/audio-pipewire-minimal.xml
 create mode 100644 tests/qemuxml2xmloutdata/audio-pipewire-best.x86_64-latest.xml
 create mode 100644 tests/qemuxml2xmloutdata/audio-pipewire-full.x86_64-latest.xml
 create mode 100644 tests/qemuxml2xmloutdata/audio-pipewire-minimal.x86_64-latest.xml

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 459815d2b5..310d2bc427 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -7368,7 +7368,8 @@ to the guest sound device.
 ``type``
    The required ``type`` attribute specifies audio backend type.
    Currently, the supported values are ``none``, ``alsa``, ``coreaudio``,
-   ``dbus``, ``jack``, ``oss``, ``pulseaudio``, ``sdl``, ``spice``, ``file``.
+   ``dbus``, ``jack``, ``oss``, ``pipewire``, ``pulseaudio``, ``sdl``,
+   ``spice``, ``file``.
 
 ``id``
    Integer id of the audio device. Must be greater than 0.
@@ -7452,7 +7453,7 @@ following environment variables:
 * ``QEMU_AUDIO_DRV``
 
   Valid values are ``pa``, ``none``, ``alsa``, ``coreaudio``, ``jack``, ``oss``,
-  ``sdl``, ``spice`` or ``wav``.
+  ``pipewire``, ``sdl``, ``spice`` or ``wav``.
 
 None audio backend
 ^^^^^^^^^^^^^^^^^^
@@ -7601,6 +7602,47 @@ and ``<output>`` elements
 
 :since:`Since 6.7.0, bhyve; Since 7.2.0, qemu`
 
+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>
+
+Optionally, path to pipewire daemon socket (aka ``PIPEWIRE_RUNTIME_DIR``) can
+be specified via ``runtimeDir`` attribute. This is useful when a domain under
+``qemu:///system`` wants to use session pipewire daemon, or vice versa.
+
+::
+
+   <audio id="1" type="pipewire" runtimeDir='/run/user/1000'>
+     <input name="fish" streamName="food" latency="100"/>
+     <output name="fish" streamName="food" latency="200"/>
+   </audio>
+
+:since:`Since 9.10.0, qemu`
+
 PulseAudio audio backend
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f7d7244738..22ad43e1d7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -791,6 +791,7 @@ VIR_ENUM_IMPL(virDomainAudioType,
               "spice",
               "file",
               "dbus",
+              "pipewire",
 );
 
 VIR_ENUM_IMPL(virDomainAudioSDLDriver,
@@ -3230,6 +3231,13 @@ virDomainAudioIOPulseAudioFree(virDomainAudioIOPulseAudio *def)
     g_free(def->streamName);
 }
 
+static void
+virDomainAudioIOPipewireAudioFree(virDomainAudioIOPipewireAudio *def)
+{
+    g_free(def->name);
+    g_free(def->streamName);
+}
+
 void
 virDomainAudioDefFree(virDomainAudioDef *def)
 {
@@ -3274,6 +3282,12 @@ virDomainAudioDefFree(virDomainAudioDef *def)
         g_free(def->backend.file.path);
         break;
 
+    case VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE:
+        virDomainAudioIOPipewireAudioFree(&def->backend.pipewire.input);
+        virDomainAudioIOPipewireAudioFree(&def->backend.pipewire.output);
+        g_free(def->backend.pipewire.runtimeDir);
+        break;
+
     case VIR_DOMAIN_AUDIO_TYPE_DBUS:
     case VIR_DOMAIN_AUDIO_TYPE_LAST:
         break;
@@ -11920,6 +11934,21 @@ virDomainAudioSDLParse(virDomainAudioIOSDL *def,
 }
 
 
+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_NONZERO,
+                       &def->latency) < 0)
+        return -1;
+
+    return 0;
+}
+
+
 static virDomainAudioDef *
 virDomainAudioDefParseXML(virDomainXMLOption *xmlopt G_GNUC_UNUSED,
                           xmlNodePtr node,
@@ -12050,6 +12079,16 @@ virDomainAudioDefParseXML(virDomainXMLOption *xmlopt G_GNUC_UNUSED,
     case VIR_DOMAIN_AUDIO_TYPE_DBUS:
         break;
 
+    case VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE:
+        if (inputNode &&
+            virDomainAudioPipewireAudioParse(&def->backend.pipewire.input, inputNode) < 0)
+            goto error;
+        if (outputNode &&
+            virDomainAudioPipewireAudioParse(&def->backend.pipewire.output, outputNode) < 0)
+            goto error;
+        def->backend.pipewire.runtimeDir = virXMLPropString(node, "runtimeDir");
+        break;
+
     case VIR_DOMAIN_AUDIO_TYPE_LAST:
     default:
         virReportEnumRangeError(virDomainAudioType, def->type);
@@ -24839,6 +24878,18 @@ virDomainAudioSDLFormat(virDomainAudioIOSDL *def,
 }
 
 
+static void
+virDomainAudioPipewireAudioFormat(virDomainAudioIOPipewireAudio *def,
+                                  virBuffer *buf)
+{
+    virBufferEscapeString(buf, " name='%s'", def->name);
+    virBufferEscapeString(buf, " streamName='%s'", def->streamName);
+    if (def->latency)
+        virBufferAsprintf(buf, " latency='%u'", def->latency);
+
+}
+
+
 static int
 virDomainAudioDefFormat(virBuffer *buf,
                         virDomainAudioDef *def)
@@ -24921,6 +24972,12 @@ virDomainAudioDefFormat(virBuffer *buf,
     case VIR_DOMAIN_AUDIO_TYPE_DBUS:
         break;
 
+    case VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE:
+        virDomainAudioPipewireAudioFormat(&def->backend.pipewire.input, &inputBuf);
+        virDomainAudioPipewireAudioFormat(&def->backend.pipewire.output, &outputBuf);
+        virBufferEscapeString(&attrBuf, " runtimeDir='%s'", def->backend.pipewire.runtimeDir);
+        break;
+
     case VIR_DOMAIN_AUDIO_TYPE_LAST:
     default:
         virReportEnumRangeError(virDomainAudioType, def->type);
@@ -29273,6 +29330,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;
+}
+
+
 static bool
 virDomainAudioBackendIsEqual(virDomainAudioDef *this,
                              virDomainAudioDef *that)
@@ -29333,6 +29400,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);
+
     case VIR_DOMAIN_AUDIO_TYPE_DBUS:
     case VIR_DOMAIN_AUDIO_TYPE_LAST:
     default:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7c0e017038..ed07859bc5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1579,6 +1579,7 @@ typedef enum {
     VIR_DOMAIN_AUDIO_TYPE_SPICE,
     VIR_DOMAIN_AUDIO_TYPE_FILE,
     VIR_DOMAIN_AUDIO_TYPE_DBUS,
+    VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE,
 
     VIR_DOMAIN_AUDIO_TYPE_LAST
 } virDomainAudioType;
@@ -1654,6 +1655,13 @@ struct _virDomainAudioIOSDL {
     unsigned int bufferCount;
 };
 
+typedef struct _virDomainAudioIOPipewireAudio virDomainAudioIOPipewireAudio;
+struct _virDomainAudioIOPipewireAudio {
+    char *name;
+    char *streamName;
+    unsigned int latency;
+};
+
 struct _virDomainAudioDef {
     virDomainAudioType type;
 
@@ -1697,6 +1705,11 @@ struct _virDomainAudioDef {
         struct {
             char *path;
         } file;
+        struct {
+            virDomainAudioIOPipewireAudio input;
+            virDomainAudioIOPipewireAudio output;
+            char *runtimeDir;
+        } pipewire;
     } backend;
 };
 
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index a26986b5ce..b98a2ae602 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -5186,6 +5186,26 @@
     <ref name="audiocommonchild"/>
   </define>
 
+  <define name="audiopipewire">
+    <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="audiopulseaudio">
     <ref name="audiocommonattr"/>
     <optional>
@@ -5361,6 +5381,28 @@
             </optional>
           </interleave>
         </group>
+        <group>
+          <attribute name="type">
+            <value>pipewire</value>
+          </attribute>
+          <interleave>
+            <optional>
+              <element name="input">
+                <ref name="audiopipewire"/>
+              </element>
+            </optional>
+            <optional>
+              <element name="output">
+                <ref name="audiopipewire"/>
+              </element>
+            </optional>
+            <optional>
+              <attribute name="runtimeDir">
+                <ref name="filePath"/>
+              </attribute>
+            </optional>
+          </interleave>
+        </group>
         <group>
           <attribute name="type">
             <value>pulseaudio</value>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2674dd6959..173639277c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -142,6 +142,7 @@ qemuAudioDriverTypeToString(virDomainAudioType type)
         case VIR_DOMAIN_AUDIO_TYPE_SDL:
         case VIR_DOMAIN_AUDIO_TYPE_SPICE:
         case VIR_DOMAIN_AUDIO_TYPE_DBUS:
+        case VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE:
         case VIR_DOMAIN_AUDIO_TYPE_LAST:
             break;
     }
@@ -7937,6 +7938,7 @@ qemuBuildAudioCommandLineArg(virCommand *cmd,
     case VIR_DOMAIN_AUDIO_TYPE_DBUS:
         break;
 
+    case VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE:
     case VIR_DOMAIN_AUDIO_TYPE_LAST:
     default:
         virReportEnumRangeError(virDomainAudioType, def->type);
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 2afd7e128a..e475ad035e 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4403,6 +4403,7 @@ qemuValidateDomainDeviceDefAudio(virDomainAudioDef *audio,
     case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
     case VIR_DOMAIN_AUDIO_TYPE_SDL:
     case VIR_DOMAIN_AUDIO_TYPE_FILE:
+    case VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE:
         break;
 
     case VIR_DOMAIN_AUDIO_TYPE_SPICE:
diff --git a/tests/qemuxml2argvdata/audio-pipewire-best.xml b/tests/qemuxml2argvdata/audio-pipewire-best.xml
new file mode 100644
index 0000000000..487f280c9b
--- /dev/null
+++ b/tests/qemuxml2argvdata/audio-pipewire-best.xml
@@ -0,0 +1,43 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='pipewire' timerPeriod='50' runtimeDir='/run/user/1000'>
+      <input mixingEngine='yes' fixedSettings='yes' voices='1' bufferLength='200' name='fish'>
+        <settings frequency='44100' channels='2' format='s16'/>
+      </input>
+      <output mixingEngine='yes' fixedSettings='yes' voices='2' bufferLength='200' name='fish'>
+        <settings frequency='22050' channels='4' format='f32'/>
+      </output>
+    </audio>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/audio-pipewire-full.xml b/tests/qemuxml2argvdata/audio-pipewire-full.xml
new file mode 100644
index 0000000000..e0df5a04d9
--- /dev/null
+++ b/tests/qemuxml2argvdata/audio-pipewire-full.xml
@@ -0,0 +1,43 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='pipewire' timerPeriod='50' runtimeDir='/run/user/1000'>
+      <input mixingEngine='yes' fixedSettings='yes' voices='1' bufferLength='100' name='fish' streamName='food' latency='100'>
+        <settings frequency='44100' channels='2' format='s16'/>
+      </input>
+      <output mixingEngine='yes' fixedSettings='yes' voices='2' bufferLength='200' name='fish' streamName='food' latency='200'>
+        <settings frequency='22050' channels='4' format='f32'/>
+      </output>
+    </audio>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/audio-pipewire-minimal.xml b/tests/qemuxml2argvdata/audio-pipewire-minimal.xml
new file mode 100644
index 0000000000..2085225722
--- /dev/null
+++ b/tests/qemuxml2argvdata/audio-pipewire-minimal.xml
@@ -0,0 +1,36 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='pipewire'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/audio-pipewire-best.x86_64-latest.xml b/tests/qemuxml2xmloutdata/audio-pipewire-best.x86_64-latest.xml
new file mode 100644
index 0000000000..c73a9abb0e
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/audio-pipewire-best.x86_64-latest.xml
@@ -0,0 +1,46 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+  </os>
+  <cpu mode='custom' match='exact' check='none'>
+    <model fallback='forbid'>qemu64</model>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0' model='piix3-uhci'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='pipewire' timerPeriod='50' runtimeDir='/run/user/1000'>
+      <input mixingEngine='yes' fixedSettings='yes' voices='1' bufferLength='200' name='fish'>
+        <settings frequency='44100' channels='2' format='s16'/>
+      </input>
+      <output mixingEngine='yes' fixedSettings='yes' voices='2' bufferLength='200' name='fish'>
+        <settings frequency='22050' channels='4' format='f32'/>
+      </output>
+    </audio>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/audio-pipewire-full.x86_64-latest.xml b/tests/qemuxml2xmloutdata/audio-pipewire-full.x86_64-latest.xml
new file mode 100644
index 0000000000..0b06d614c0
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/audio-pipewire-full.x86_64-latest.xml
@@ -0,0 +1,46 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+  </os>
+  <cpu mode='custom' match='exact' check='none'>
+    <model fallback='forbid'>qemu64</model>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0' model='piix3-uhci'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='pipewire' timerPeriod='50' runtimeDir='/run/user/1000'>
+      <input mixingEngine='yes' fixedSettings='yes' voices='1' bufferLength='100' name='fish' streamName='food' latency='100'>
+        <settings frequency='44100' channels='2' format='s16'/>
+      </input>
+      <output mixingEngine='yes' fixedSettings='yes' voices='2' bufferLength='200' name='fish' streamName='food' latency='200'>
+        <settings frequency='22050' channels='4' format='f32'/>
+      </output>
+    </audio>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/audio-pipewire-minimal.x86_64-latest.xml b/tests/qemuxml2xmloutdata/audio-pipewire-minimal.x86_64-latest.xml
new file mode 100644
index 0000000000..7fc0a65a68
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/audio-pipewire-minimal.x86_64-latest.xml
@@ -0,0 +1,39 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='cdrom'/>
+  </os>
+  <cpu mode='custom' match='exact' check='none'>
+    <model fallback='forbid'>qemu64</model>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0' model='piix3-uhci'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='pipewire'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 72f976358f..1010b68ebc 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -957,6 +957,7 @@ mymain(void)
     DO_TEST_CAPS_LATEST("audio-coreaudio-minimal");
     DO_TEST_CAPS_LATEST("audio-oss-minimal");
     DO_TEST_CAPS_LATEST("audio-pulseaudio-minimal");
+    DO_TEST_CAPS_LATEST("audio-pipewire-minimal");
     DO_TEST_CAPS_LATEST("audio-sdl-minimal");
     DO_TEST_CAPS_LATEST("audio-spice-minimal");
     DO_TEST_CAPS_LATEST("audio-file-minimal");
@@ -967,6 +968,7 @@ mymain(void)
     DO_TEST_CAPS_LATEST("audio-coreaudio-best");
     DO_TEST_CAPS_LATEST("audio-oss-best");
     DO_TEST_CAPS_LATEST("audio-pulseaudio-best");
+    DO_TEST_CAPS_LATEST("audio-pipewire-best");
     DO_TEST_CAPS_LATEST("audio-sdl-best");
     DO_TEST_CAPS_LATEST("audio-spice-best");
     DO_TEST_CAPS_LATEST("audio-file-best");
@@ -978,6 +980,7 @@ mymain(void)
     DO_TEST_CAPS_LATEST("audio-jack-full");
     DO_TEST_CAPS_LATEST("audio-oss-full");
     DO_TEST_CAPS_LATEST("audio-pulseaudio-full");
+    DO_TEST_CAPS_LATEST("audio-pipewire-full");
     DO_TEST_CAPS_LATEST("audio-sdl-full");
     DO_TEST_CAPS_LATEST("audio-spice-full");
     DO_TEST_CAPS_LATEST("audio-file-full");
-- 
2.41.0
_______________________________________________
Devel mailing list -- devel@xxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux