From nobody Sun Feb 8 16:11:27 2026 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1699362040243731.1896545756524; Tue, 7 Nov 2023 05:00:40 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 8744E1A6F; Tue, 7 Nov 2023 08:00:38 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id CD70B1A1A; Tue, 7 Nov 2023 07:55:45 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id B34A019E3; Tue, 7 Nov 2023 07:55:32 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 2BA3C193F for ; Tue, 7 Nov 2023 07:55:31 -0500 (EST) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-209-bSwY3JobPf-lDWHIR9_Yow-1; Tue, 07 Nov 2023 07:55:29 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E3577101A53B for ; Tue, 7 Nov 2023 12:55:28 +0000 (UTC) Received: from maggie.brq.redhat.com (unknown [10.43.3.102]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8D00219E93 for ; Tue, 7 Nov 2023 12:55:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.4 X-MC-Unique: bSwY3JobPf-lDWHIR9_Yow-1 From: Michal Privoznik To: devel@lists.libvirt.org Subject: [PATCH 2/3] qemu: Generate cmd line for pipewire audio backend Date: Tue, 7 Nov 2023 13:55:23 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Message-ID-Hash: 7KSHCEBQ6E3DID7D2FL5VSSQ4UWMBW2I X-Message-ID-Hash: 7KSHCEBQ6E3DID7D2FL5VSSQ4UWMBW2I X-MailFrom: mprivozn@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="utf-8"; x-default="true" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1699362041499100001 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, 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. Resolves: https://gitlab.com/libvirt/libvirt/-/issues/560 Signed-off-by: Michal Privoznik Reviewed-by: Peter Krempa --- 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 | 14 +++++ .../audio-many-backends.x86_64-latest.xml | 1 + 8 files changed, 187 insertions(+) create mode 100644 tests/qemuxml2argvdata/audio-pipewire-best.x86_64-lates= t.args create mode 100644 tests/qemuxml2argvdata/audio-pipewire-full.x86_64-lates= t.args create mode 100644 tests/qemuxml2argvdata/audio-pipewire-minimal.x86_64-la= test.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 173639277c..a7bb999528 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7833,6 +7833,60 @@ qemuBuildAudioSDLProps(virDomainAudioIOSDL *def, } =20 =20 +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[] =3D { "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 =3D 0; i < G_N_ELEMENTS(envVars); i++) { + const char *value =3D getenv(envVars[i]); + + if (!value) + continue; + + virCommandAddEnvPair(cmd, envVars[i], value); + break; + } +} + + static int qemuBuildAudioCommandLineArg(virCommand *cmd, virDomainAudioDef *def) @@ -7939,6 +7993,13 @@ qemuBuildAudioCommandLineArg(virCommand *cmd, break; =20 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 4c6c925ccd..0bdc75689f 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=3Dtest \ XDG_DATA_HOME=3D/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ XDG_CACHE_HOME=3D/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ XDG_CONFIG_HOME=3D/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +PIPEWIRE_RUNTIME_DIR=3D/run/user/1000 \ /usr/bin/qemu-system-x86_64 \ -name guest=3DQEMUGuest1,debug-threads=3Don \ -S \ @@ -32,6 +33,7 @@ XDG_CONFIG_HOME=3D/var/lib/libvirt/qemu/domain--1-QEMUGue= st1/.config \ -audiodev '{"id":"audio1","driver":"none"}' \ -audiodev '{"id":"audio2","driver":"alsa"}' \ -audiodev '{"id":"audio3","driver":"pa"}' \ +-audiodev '{"id":"audio4","driver":"pipewire"}' \ -vnc 127.0.0.1:0,audiodev=3Daudio2 \ -device '{"driver":"cirrus-vga","id":"video0","bus":"pci.0","addr":"0x2"}'= \ -device '{"driver":"AC97","id":"sound0","audiodev":"audio1","bus":"pci.0",= "addr":"0x3"}' \ diff --git a/tests/qemuxml2argvdata/audio-many-backends.xml b/tests/qemuxml= 2argvdata/audio-many-backends.xml index c681784526..1659723f91 100644 --- a/tests/qemuxml2argvdata/audio-many-backends.xml +++ b/tests/qemuxml2argvdata/audio-many-backends.xml @@ -51,6 +51,7 @@