[PATCH 2/3] qemu: Generate cmd line for pipewire audio backend

Martin Kletzander mkletzan at redhat.com
Tue May 16 09:52:32 UTC 2023


On Thu, May 11, 2023 at 02:14:51PM +0200, Michal Privoznik wrote:
>This is mostly straightforward, except for a teensy-weensy
>detail: usually, there's no system wide daemon running, no system
>wide available socket that anybody could connect to. PipeWire
>uses a per user daemon approach instead. But this in turn means,

I spent some time thinking about this even after I said "just give it
runtime dir" and now I'm wondering, is this not similar to the dbus
daemon?  When we launch it with a constructed config file for graphics
type='dbus' we could also launch pipewire deamon with our config file
and let qemu connect to that daemon.  I'm not sure what the audio
permissions would look like, but it seems like a less messy approach.

>that the socket location floats between various locations and is
>derived from various environment variables (just like the actual
>socket name) and thus we must pass the variables to QEMU.
>
>Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>---
> src/qemu/qemu_command.c                       | 61 +++++++++++++++++++
> .../audio-many-backends.x86_64-latest.args    |  2 +
> .../qemuxml2argvdata/audio-many-backends.xml  |  1 +
> .../audio-pipewire-best.x86_64-latest.args    | 36 +++++++++++
> .../audio-pipewire-full.x86_64-latest.args    | 36 +++++++++++
> .../audio-pipewire-minimal.x86_64-latest.args | 36 +++++++++++
> tests/qemuxml2argvtest.c                      | 12 ++++
> 7 files changed, 184 insertions(+)
> create mode 100644 tests/qemuxml2argvdata/audio-pipewire-best.x86_64-latest.args
> create mode 100644 tests/qemuxml2argvdata/audio-pipewire-full.x86_64-latest.args
> create mode 100644 tests/qemuxml2argvdata/audio-pipewire-minimal.x86_64-latest.args
>
>diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
>index 3a08cac870..b31f4db6b1 100644
>--- a/src/qemu/qemu_command.c
>+++ b/src/qemu/qemu_command.c
>@@ -7783,6 +7783,60 @@ qemuBuildAudioSDLProps(virDomainAudioIOSDL *def,
> }
>
>
>+static int
>+qemuBuildAudioPipewireAudioProps(virDomainAudioIOPipewireAudio *def,
>+                                 virJSONValue **props)
>+{
>+    return virJSONValueObjectAdd(props,
>+                                 "S:name", def->name,
>+                                 "S:stream-name", def->streamName,
>+                                 "p:latency", def->latency,
>+                                 NULL);
>+}
>+
>+
>+static void
>+qemuBuildAudioPipewireAudioEnv(virCommand *cmd)
>+{
>+    const char *envVars[] = { "PIPEWIRE_RUNTIME_DIR", "XDG_RUNTIME_DIR",
>+                              "USERPROFILE" };
>+    size_t i;
>+
>+    /* PipeWire needs access to its daemon socket. The socket name is
>+     * configurable (core.name in pipewire.conf, or PIPEWIRE_CORE and
>+     * PIPEWIRE_REMOTE env vars). If the socket name is not an absolute
>+     * path, then the socket is looked for in the following directories
>+     * (in order):
>+     *
>+     * - PIPEWIRE_RUNTIME_DIR
>+     * - XDG_RUNTIME_DIR
>+     * - USERPROFILE
>+     *
>+     * This order is defined in get_runtime_dir() from
>+     * src/modules/module-protocol-native/local-socket.c from PipeWire's
>+     * codebase.
>+     *
>+     * Now, PIPEWIRE_CORE and/or PIPEWIRE_REMOTE should be passed
>+     * whenever present in the environment. But for the other three
>+     * (socket location dirs), we can add just the first existing one
>+     * (basically mimic get_runtime_dir() logic).
>+     */
>+
>+    virCommandAddEnvPass(cmd, "PIPEWIRE_CORE");
>+    virCommandAddEnvPass(cmd, "PIPEWIRE_REMOTE");
>+
>+    for (i = 0; i < G_N_ELEMENTS(envVars); i++) {
>+        const char *value = getenv(envVars[i]);
>+
>+        if (!value)
>+            continue;
>+
>+        virCommandAddEnvPair(cmd, envVars[i], value);
>+        break;
>+    }
>+}
>+
>+
> static int
> qemuBuildAudioCommandLineArg(virCommand *cmd,
>                              virDomainAudioDef *def)
>@@ -7889,6 +7943,13 @@ qemuBuildAudioCommandLineArg(virCommand *cmd,
>         break;
>
>     case VIR_DOMAIN_AUDIO_TYPE_PIPEWIRE:
>+        if (qemuBuildAudioPipewireAudioProps(&def->backend.pipewire.input, &in) < 0 ||
>+            qemuBuildAudioPipewireAudioProps(&def->backend.pipewire.output, &out) < 0)
>+            return -1;
>+
>+        qemuBuildAudioPipewireAudioEnv(cmd);
>+        break;
>+
>     case VIR_DOMAIN_AUDIO_TYPE_LAST:
>     default:
>         virReportEnumRangeError(virDomainAudioType, def->type);
>diff --git a/tests/qemuxml2argvdata/audio-many-backends.x86_64-latest.args b/tests/qemuxml2argvdata/audio-many-backends.x86_64-latest.args
>index 9caf591daf..13dd55054e 100644
>--- a/tests/qemuxml2argvdata/audio-many-backends.x86_64-latest.args
>+++ b/tests/qemuxml2argvdata/audio-many-backends.x86_64-latest.args
>@@ -6,6 +6,7 @@ LOGNAME=test \
> XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \
> XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \
> XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
>+XDG_RUNTIME_DIR=/bad-test-used-env-xdg-runtime-dir \

This should fail the test suite IIRC.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20230516/57cc3947/attachment.sig>


More information about the libvir-list mailing list