From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588261; cv=none; d=zohomail.com; s=zohoarc; b=JcIZpdQ4DI0+3n3V44LFrmPzZFjQNigHsn/Wm6iE6tYMizBKOkJbAm2WINUlZD+IE7kncb9SHLuZLicT/we2pNzULNwFp/KxdGqdLWhrMEQkH8lTSMyeX3dQg/FzA6GyNfhVtiUZAWBgLUfPWlmFtjWaIDEf8BuKWp6/DtE1Qjs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588261; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=cTK98tro9wmYGZ1MH4F+lDO9TW79M2ScIbCtTuhv8hA=; b=SM84TH8nqrPj9YFs0EhXDkJNOxYG7xiKjYiceBN03GZvU+m7pDQmwNNyZWNcZ+M/ArNZ5FTktuQwL/iU4iCxUJOmhuNMa9npgWmRIg60dBB9jnwOy+Q3i5Au9IiyZLYD4GR6lyvxlapogoD8qPIqKKYDLIdMMlKYddaF9UV5hUA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588261794822.5729174282021; Mon, 1 Dec 2025 03:24:21 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ20O-0008U0-55; Mon, 01 Dec 2025 06:23:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20F-0008Qz-1a for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:23:35 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20D-0006V6-51 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:23:34 -0500 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-641-8oC3YkLsPsyynibW5Mn4uA-1; Mon, 01 Dec 2025 06:23:25 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 09D2518002C2; Mon, 1 Dec 2025 11:23:23 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DA438180047F; Mon, 1 Dec 2025 11:23:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588212; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cTK98tro9wmYGZ1MH4F+lDO9TW79M2ScIbCtTuhv8hA=; b=YSZ5S90JC/+nr/50+jCrS6povzjEs4yqH51Vxt77Mx1l8H6ShcXkSQSHuLwUfP2bN8uo0t L+GXXYcJt+1QQN551qDIwuaziN3O+tUjhH2z5Til87Acjht5oF+SsK+2Oh5Qs0tXZPxuYg ilYEG+12S/Ei79RkBt3+Jn4bjz0Kbr0= X-MC-Unique: 8oC3YkLsPsyynibW5Mn4uA-1 X-Mimecast-MFC-AGG-ID: 8oC3YkLsPsyynibW5Mn4uA_1764588203 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 01/24] rust: patch thiserror to work with meson Date: Mon, 1 Dec 2025 15:22:42 +0400 Message-ID: <20251201112309.4163921-2-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588263554019200 From: Marc-Andr=C3=A9 Lureau Some dependencies introduced in the following patches require thiserror. Since 2.0.17, it "Use differently named __private module per patch release", using build.rs time generated code. This is not handled by meson. Signed-off-by: Marc-Andr=C3=A9 Lureau --- .../packagefiles/syn-2-rs/meson/meson.build | 3 +++ .../packagefiles/thiserror-2.0.17-include.patch | 14 ++++++++++++++ .../thiserror-impl-2.0.17-include.patch | 13 +++++++++++++ subprojects/syn-2-rs.wrap | 11 ++++++----- subprojects/thiserror-2-rs.wrap | 10 ++++++++++ subprojects/thiserror-impl-2-rs.wrap | 10 ++++++++++ 6 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 subprojects/packagefiles/syn-2-rs/meson/meson.build create mode 100644 subprojects/packagefiles/thiserror-2.0.17-include.patch create mode 100644 subprojects/packagefiles/thiserror-impl-2.0.17-include.= patch create mode 100644 subprojects/thiserror-2-rs.wrap create mode 100644 subprojects/thiserror-impl-2-rs.wrap diff --git a/subprojects/packagefiles/syn-2-rs/meson/meson.build b/subproje= cts/packagefiles/syn-2-rs/meson/meson.build new file mode 100644 index 0000000000..02439c2b58 --- /dev/null +++ b/subprojects/packagefiles/syn-2-rs/meson/meson.build @@ -0,0 +1,3 @@ +extra_args +=3D [ + '--cfg', 'feature=3D"full"', +] diff --git a/subprojects/packagefiles/thiserror-2.0.17-include.patch b/subp= rojects/packagefiles/thiserror-2.0.17-include.patch new file mode 100644 index 0000000000..a061aeea57 --- /dev/null +++ b/subprojects/packagefiles/thiserror-2.0.17-include.patch @@ -0,0 +1,14 @@ +diff --git a/src/lib.rs b/src/lib.rs +index 155272d..7683f4c 100644 +--- a/src/lib.rs ++++ b/src/lib.rs +@@ -288,4 +288,8 @@ pub use thiserror_impl::*; +=20 + mod private; +=20 +-include!(concat!(env!("OUT_DIR"), "/private.rs")); ++#[doc(hidden)] ++pub mod __private_MESON { ++ #[doc(hidden)] ++ pub use crate::private::*; ++} diff --git a/subprojects/packagefiles/thiserror-impl-2.0.17-include.patch b= /subprojects/packagefiles/thiserror-impl-2.0.17-include.patch new file mode 100644 index 0000000000..372862dffa --- /dev/null +++ b/subprojects/packagefiles/thiserror-impl-2.0.17-include.patch @@ -0,0 +1,13 @@ +diff --git a/impl/src/lib.rs b/impl/src/lib.rs +index 25890f2..1559a41 100644 +--- a/src/lib.rs ++++ b/src/lib.rs +@@ -48,7 +48,7 @@ struct private; + impl ToTokens for private { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + tokens.append(Ident::new( +- concat!("__private", env!("CARGO_PKG_VERSION_PATCH")), ++ concat!("__private", "_MESON"), + Span::call_site(), + )); + } diff --git a/subprojects/syn-2-rs.wrap b/subprojects/syn-2-rs.wrap index 8ec7fd0052..82675e8723 100644 --- a/subprojects/syn-2-rs.wrap +++ b/subprojects/syn-2-rs.wrap @@ -1,9 +1,10 @@ [wrap-file] -directory =3D syn-2.0.104 -source_url =3D https://crates.io/api/v1/crates/syn/2.0.104/download -source_filename =3D syn-2.0.104.0.tar.gz -source_hash =3D 17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b= 435a40 +directory =3D syn-2.0.110 +source_url =3D https://crates.io/api/v1/crates/syn/2.0.110/download +source_filename =3D syn-2.0.110.tar.gz +source_hash =3D a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b= 280aea method =3D cargo +patch_directory =3D syn-2-rs =20 # bump this version number on every change to meson.build or the patches: -# v3 +# v4 diff --git a/subprojects/thiserror-2-rs.wrap b/subprojects/thiserror-2-rs.w= rap new file mode 100644 index 0000000000..432d99d937 --- /dev/null +++ b/subprojects/thiserror-2-rs.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory =3D thiserror-2.0.17 +source_url =3D https://crates.io/api/v1/crates/thiserror/2.0.17/download +source_filename =3D thiserror-2.0.17.tar.gz +source_hash =3D f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a305161= 8f4fc8 +method =3D cargo +diff_files =3D thiserror-2.0.17-include.patch + +# bump this version number on every change to meson.build or the patches: +# v2 diff --git a/subprojects/thiserror-impl-2-rs.wrap b/subprojects/thiserror-i= mpl-2-rs.wrap new file mode 100644 index 0000000000..f0eb263607 --- /dev/null +++ b/subprojects/thiserror-impl-2-rs.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory =3D thiserror-impl-2.0.17 +source_url =3D https://crates.io/api/v1/crates/thiserror-impl/2.0.17/downl= oad +source_filename =3D thiserror-impl-2.0.17.tar.gz +source_hash =3D 3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a5= 17c913 +method =3D cargo +diff_files =3D thiserror-impl-2.0.17-include.patch + +# bump this version number on every change to meson.build or the patches: +# v2 --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588261; cv=none; d=zohomail.com; s=zohoarc; b=QEjC0Rjlz/wHPbcUfHhK+MiX1lA0yLG7HvkLCn0DQ7FR9TBac940DzqS+KImHQ3SDU/uJmBx2kOd+PZcwq/p2Z7EgF1IQxP/FdGv3wS9CmcnWRZWg8l/yzzVC5bJ4VES4VYRkem5+DScDy4vIYNs+q8kVzkuRhQz3XC4RcTEaPs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588261; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=3kYSTSuwqhKH9Sm+PFHYKfCorVGrfWqK5KxrHlVSMac=; b=U8mslHfsdM0ebjZ4i0tNNxQTkfMySq2ZfqFpsUfEpxmj8UyG2LhDU+hHoGR0DWXFzGRzVrxxhbkcVz18HH2c37RLgHd9SI0W7ZtE1w+oVxphk2g72abB9St2y74NbXKq/pjd+g7k9BWfC30K9yXiL4uahqr9nnyDAGZvH0uCzNg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588261678314.2843958254392; Mon, 1 Dec 2025 03:24:21 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ20b-00005H-4f; Mon, 01 Dec 2025 06:24:03 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20J-0008SG-9W for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:23:40 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20H-0006Vf-Mx for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:23:39 -0500 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-311-0_rzaTGSOc6vRU6lOowJrg-1; Mon, 01 Dec 2025 06:23:31 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C134718001FE; Mon, 1 Dec 2025 11:23:29 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C130530001A4; Mon, 1 Dec 2025 11:23:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588217; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3kYSTSuwqhKH9Sm+PFHYKfCorVGrfWqK5KxrHlVSMac=; b=XMs4vpQh4SrNweEjJkQZGCHM9/ImWI3udnX+UdbN0AEdXWqLG4G7++ljOBYG/d2jpsLwyB M24cOeOeLyF5Nq+HKz1CK8NuHwqEdOg10SBm3MqWAn+gh76houi5oAmAO7CD26+IzRvzbq XG6qPVsEGSV+cb14DhNHaykW7tg14M0= X-MC-Unique: 0_rzaTGSOc6vRU6lOowJrg-1 X-Mimecast-MFC-AGG-ID: 0_rzaTGSOc6vRU6lOowJrg_1764588210 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 02/24] audio: remove obsolete/obscure functions Date: Mon, 1 Dec 2025 15:22:43 +0400 Message-ID: <20251201112309.4163921-3-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588264996019200 From: Marc-Andr=C3=A9 Lureau AUD_init_time_stamp_{in,out} and AUD_get_elapsed_usec_{in,out} are only used by the adlib device. The result isn't actually being used since ADLIB_KILL_TIMERS was set some 20y ago. Let's drop this dead code now. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_template.h | 34 ---------------------------------- include/qemu/audio.h | 6 ------ hw/audio/adlib.c | 18 +----------------- 3 files changed, 1 insertion(+), 57 deletions(-) diff --git a/audio/audio_template.h b/audio/audio_template.h index 7a8c431f2d..1ab3c47fd7 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -569,40 +569,6 @@ bool glue(AUD_is_active_, TYPE)(SW *sw) return sw ? sw->active : 0; } =20 -void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts) -{ - if (!sw) { - return; - } - - ts->old_ts =3D sw->hw->ts_helper; -} - -uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *t= s) -{ - uint64_t delta, cur_ts, old_ts; - - if (!sw) { - return 0; - } - - cur_ts =3D sw->hw->ts_helper; - old_ts =3D ts->old_ts; - /* dolog ("cur %" PRId64 " old %" PRId64 "\n", cur_ts, old_ts); */ - - if (cur_ts >=3D old_ts) { - delta =3D cur_ts - old_ts; - } else { - delta =3D UINT64_MAX - old_ts + cur_ts; - } - - if (!delta) { - return 0; - } - - return muldiv64 (delta, sw->hw->info.freq, 1000000); -} - #undef TYPE #undef HW #undef SW diff --git a/include/qemu/audio.h b/include/qemu/audio.h index c56af895d6..2562710bec 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -71,9 +71,6 @@ int AUD_get_buffer_size_out (SWVoiceOut *sw); void AUD_set_active_out(SWVoiceOut *sw, bool on); bool AUD_is_active_out(SWVoiceOut *sw); =20 -void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); -uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); - #define AUDIO_MAX_CHANNELS 16 typedef struct Volume { bool mute; @@ -112,9 +109,6 @@ size_t AUD_read (SWVoiceIn *sw, void *pcm_buf, size_t s= ize); void AUD_set_active_in(SWVoiceIn *sw, bool on); bool AUD_is_active_in(SWVoiceIn *sw); =20 -void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); -uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); - void audio_cleanup(void); =20 typedef struct st_sample st_sample; diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 19d3a5f128..2a2fe7d04f 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -34,8 +34,6 @@ =20 #define DEBUG 0 =20 -#define ADLIB_KILL_TIMERS 1 - #define ADLIB_DESC "Yamaha YM3812 (OPL2)" =20 #if DEBUG @@ -71,7 +69,6 @@ struct AdlibState { uint64_t dexp[2]; SWVoiceOut *voice; int left, pos, samples; - QEMUAudioTimeStamp ats; FM_OPL *opl; PortioList port_list; }; @@ -88,19 +85,7 @@ static void adlib_kill_timers (AdlibState *s) =20 for (i =3D 0; i < 2; ++i) { if (s->ticking[i]) { - uint64_t delta; - - delta =3D AUD_get_elapsed_usec_out (s->voice, &s->ats); - ldebug ( - "delta =3D %f dexp =3D %f expired =3D> %d", - delta / 1000000.0, - s->dexp[i] / 1000000.0, - delta >=3D s->dexp[i] - ); - if (ADLIB_KILL_TIMERS || delta >=3D s->dexp[i]) { - adlib_stop_opl_timer (s, i); - AUD_init_time_stamp_out (s->voice, &s->ats); - } + adlib_stop_opl_timer(s, i); } } } @@ -149,7 +134,6 @@ static void timer_handler (void *opaque, int c, double = interval_Sec) #endif =20 s->dexp[n] =3D interval_Sec * 1000000.0; - AUD_init_time_stamp_out (s->voice, &s->ats); } =20 static int write_audio (AdlibState *s, int samples) --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588281; cv=none; d=zohomail.com; s=zohoarc; b=fb9egqjK2G0DCzwPSarzbA7vDuKLfoIV+c9iDz7Ro9VdVHfpCbHr5nhqN9nAV6OY6YlPuVXGWqgI2JyUcsKzy6NF93grKp/9pTWjL9Z7MffmrrwDJD2ZJvZQ3wQbP5r0yeYmcSMIsspbU5jFmzugNwQwbdKworPBZfKKWepCDfw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588281; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+0ReVlWAGq/byZzHvgrljOfsskjahcJZfgv9MIK+QHE=; b=ZZ7hFyT/rkj8DVq7CNUwnYzaax74umx7KGRnFv0i8loQSpnof5Nqp0grXISEHCBgQHZsFd8GyilVewRvx89kv+EgplPCxNzz8bcW3qTme7dejUFgEZpcsxgaCx4TE22yX3jxeRCS35VquBVEPOWkjlbWj9QC9zc9+nymslB80BA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588281220266.42657603661837; Mon, 1 Dec 2025 03:24:41 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ20w-0000Ab-EM; Mon, 01 Dec 2025 06:24:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20j-00008X-KN for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:06 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20M-0006W0-JD for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:23:43 -0500 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-335-HzKLxrWhN8iTJr-Des36Iw-1; Mon, 01 Dec 2025 06:23:37 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 317BC1800342; Mon, 1 Dec 2025 11:23:36 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BDE50180047F; Mon, 1 Dec 2025 11:23:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588220; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+0ReVlWAGq/byZzHvgrljOfsskjahcJZfgv9MIK+QHE=; b=L+dfvYApSE6oTf6c5SHWuMtXo41xCu3TwvQnjMAeIP1y58juVTGHpxRaDMA1gByZUwF0Ln LuF4McryGc+eKZ0W4C9qw1SbdwXXf7xoYBVojXrmcbbCKKf8cd565L7fmyybUHxP3TyCPH H2ET3yk42u4TUoXD0JOKkiRMYqLKJwo= X-MC-Unique: HzKLxrWhN8iTJr-Des36Iw-1 X-Mimecast-MFC-AGG-ID: HzKLxrWhN8iTJr-Des36Iw_1764588216 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 03/24] audio/dbus: make "dbus" the default backend when using -display dbus Date: Mon, 1 Dec 2025 15:22:44 +0400 Message-ID: <20251201112309.4163921-4-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588284181019200 From: Marc-Andr=C3=A9 Lureau Set "using_dbus_display" during early_dbus_init(), so that we can try to create the "dbus" audio backend by default from audio_prio_list. This makes dbus audio work by default when using an audio device, without having to setup and wire up the -audiodev manually. The added FIXME is addressed in the following commits. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio.c | 3 +++ audio/dbusaudio.c | 8 +++++++- ui/dbus.c | 17 +++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 86e674410a..0f992a775c 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -57,6 +57,9 @@ that we generate the list. */ const char *audio_prio_list[] =3D { +#ifdef CONFIG_GIO + "dbus", +#endif "spice", CONFIG_AUDIO_DRIVERS "none", diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index d729a810aa..1fe7c4ed64 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -32,6 +32,7 @@ #endif =20 #include "ui/dbus.h" +#include "ui/dbus-display.h" #include "ui/dbus-display1.h" =20 #define AUDIO_CAP "dbus" @@ -408,8 +409,13 @@ dbus_enable_in(HWVoiceIn *hw, bool enable) static void * dbus_audio_init(Audiodev *dev, Error **errp) { - DBusAudio *da =3D g_new0(DBusAudio, 1); + DBusAudio *da; =20 + if (!qemu_using_dbus_display(errp)) { + return NULL; + } + + da =3D g_new0(DBusAudio, 1); da->dev =3D dev; da->out_listeners =3D g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); diff --git a/ui/dbus.c b/ui/dbus.c index d2dff33258..45fb3c1aa3 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -35,6 +35,7 @@ #include "ui/egl-context.h" #endif #include "qemu/audio.h" +#include "audio/audio_int.h" /* FIXME: use QOM dynamic cast instead of drv= ->name */ #include "qapi/error.h" #include "trace.h" =20 @@ -218,12 +219,20 @@ dbus_display_complete(UserCreatable *uc, Error **errp) return; } =20 + AudioBackend *audio_be =3D audio_get_default_audio_be(NULL); + if (audio_be && !g_str_equal(audio_be->drv->name, "dbus")) { + audio_be =3D NULL; + } if (dd->audiodev && *dd->audiodev) { - AudioBackend *audio_be =3D audio_be_by_name(dd->audiodev, errp); - if (!audio_be || !audio_be_set_dbus_server(audio_be, dd->server, d= d->p2p, errp)) { + audio_be =3D audio_be_by_name(dd->audiodev, errp); + if (!audio_be) { return; } } + if (audio_be && !audio_be_set_dbus_server(audio_be, dd->server, dd->p2= p, errp)) { + return; + } + =20 consoles =3D g_array_new(FALSE, FALSE, sizeof(guint32)); for (idx =3D 0;; idx++) { @@ -475,6 +484,8 @@ early_dbus_init(DisplayOptions *opts) #endif } =20 + using_dbus_display =3D 1; + type_register_static(&dbus_vc_type_info); } =20 @@ -488,8 +499,6 @@ dbus_init(DisplayState *ds, DisplayOptions *opts) exit(1); } =20 - using_dbus_display =3D 1; - object_new_with_props(TYPE_DBUS_DISPLAY, object_get_objects_root(), "dbus-display", &error_fatal, --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588346; cv=none; d=zohomail.com; s=zohoarc; b=bMP2g6afHW9Gs1P7P/Y47KEtGbDt0JajidhV7xA7n1MH9avTrj2PvXJ/anWIZ2Yuvua7bTR3i/8aeFdMyPRNL0nDU5RY6mDCp/3r0kbcIppVuwETut+nyWxuJkyjPNjQonBMChPhD2ap/ydBzOI0TCqeQQ2iLh49hvmfl2QMY64= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588346; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BdolHlVnmu7KnI0YqB7qDrd2PfIRoX4+6aPnKjKYbik=; b=PTHW/ws0yzYwo9pz9T/GiE+/lHKqCCN7A8C/eUrwhWSPPAQLmAPshn0TlBiqFKRGn87R24l6QcX7txdGnvCOH0TeL0S5SSdOAtpuPZ229YpqKcZfAMB0KWWAeHkaYJQCcfNfWt06k9jYqA051wqpiAG0yb8ppvWkQD+vhRsF3ZA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588346519878.8095550051844; Mon, 1 Dec 2025 03:25:46 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ217-0000nT-3d; Mon, 01 Dec 2025 06:24:29 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20s-0000AZ-Gr for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:16 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20p-0006X5-Kc for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:14 -0500 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-103-kmBQoPLxPkilcDixn-hURA-1; Mon, 01 Dec 2025 06:23:43 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9B51E1955E7A; Mon, 1 Dec 2025 11:23:41 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8A68F30001A4; Mon, 1 Dec 2025 11:23:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588238; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BdolHlVnmu7KnI0YqB7qDrd2PfIRoX4+6aPnKjKYbik=; b=H+yXG8Z1gtZ6WpdszPBC+o4XSSIky9FUCPkmifDlUPq8hGyVxY7xK3fZ1QluzaJ8xRqzyb j0Th9Gm/HSWmrKZREC6LJdLffEKnFN2T/XrwT41aYOdSYKImd5P+ogz+nETEkVrUtTuttr cq0DqOU8qiAACcr9tfuMAxCV3c+8tqs= X-MC-Unique: kmBQoPLxPkilcDixn-hURA-1 X-Mimecast-MFC-AGG-ID: kmBQoPLxPkilcDixn-hURA_1764588222 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 04/24] qemu-options.hx: clarify default audio backend selection Date: Mon, 1 Dec 2025 15:22:45 +0400 Message-ID: <20251201112309.4163921-5-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588347514019200 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- qemu-options.hx | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index fca2b7bc74..4aa6c8829c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -894,11 +894,16 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, QEMU_ARCH_ALL) SRST ``-audiodev [driver=3D]driver,id=3Did[,prop[=3Dvalue][,...]]`` - Adds a new audio backend driver identified by id. There are global - and driver specific properties. Some values can be set differently - for input and output, they're marked with ``in|out.``. You can set - the input's property with ``in.prop`` and the output's property with - ``out.prop``. For example: + Adds a new audio backend driver identified by id. + + If no audio backend is specified, QEMU will attempt to load a + default one. The selected -display option may influence which backend + is used. + + There are global and driver specific properties. Some values can be + set differently for input and output, they're marked with ``in|out.``. + You can set the input's property with ``in.prop`` and the output's + property with ``out.prop``. For example: =20 :: =20 @@ -2170,8 +2175,9 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, , QEMU_ARCH_ALL) SRST ``-display type`` - Select type of display to use. Use ``-display help`` to list the avail= able - display types. Valid values for type are + Select type of display to use. It affects the default audio backend se= lection. + + Use ``-display help`` to list the available display types. Valid value= s for type are =20 ``spice-app[,gl=3Don|off]`` Start QEMU as a Spice server and launch the default Spice client --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588272; cv=none; d=zohomail.com; s=zohoarc; b=cMkiB9F5S34OSpkOoLQCUCcxiSakwef59lMHdH59TQ6NATd0RgBklB3jL49uWC/2oRToWeVgsdVb1oh7IGCyIniuVdTyUKHkDcWUHNPFNLQ/iCx1Lu7W0eXIktABu+7WnlpgtkyAMEa6oCa3agfO9MWt+wdQI3UVQbGqNq3j0Ds= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588272; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=u22Z74ggQFnSD0lEFLOdNYJgF5urxADWPdEIvOhtE34=; b=Cn9jhzDUIYacjDvMy1YiH+0VLgoBYTws0IzG86US/1lfkHdjjStlbOEvpwPEJnHrT3mIVQFmM07Xut6qFBy0VH67NzqPRicadXpuyiHxr5YGB9pUi8XukHiM9W8dzVp3n8lk4lDG+bEgZwv9SZ/8fAHR2JpaZkan42lxtHCaiJY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 176458827247292.50045651206517; Mon, 1 Dec 2025 03:24:32 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ211-0000RO-EC; Mon, 01 Dec 2025 06:24:23 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20s-0000AO-7T for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:14 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20h-0006We-K9 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:13 -0500 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-88-X-YKr5zDN4CXgqdunIHC_g-1; Mon, 01 Dec 2025 06:23:50 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9336D195608E; Mon, 1 Dec 2025 11:23:48 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 372471800451; Mon, 1 Dec 2025 11:23:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588231; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=u22Z74ggQFnSD0lEFLOdNYJgF5urxADWPdEIvOhtE34=; b=M6st/Nlqrx6ljF/VLghu1QC5COJAdP1ArfMUNqitjbc1wDIDx48jhDtDeGBrZsXvnqWETW URdhbw16LVGuxEKvImuz6ckx6HYV9h8tOAxxw4RhVbc/ogP7T3gjh8LkgCd0n3wAgL7r9V O9FgvYwj/vKGGlvBaPeuJs4IEgEbkrI= X-MC-Unique: X-YKr5zDN4CXgqdunIHC_g-1 X-Mimecast-MFC-AGG-ID: X-YKr5zDN4CXgqdunIHC_g_1764588228 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 05/24] audio: introduce AudioDriver Date: Mon, 1 Dec 2025 15:22:46 +0400 Message-ID: <20251201112309.4163921-6-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588274067019201 From: Marc-Andr=C3=A9 Lureau Introduce a sub-class for current "audio_driver" based implementations. Future AudioBackend implementations can do without it. Next cleanup will actually remove "audio_driver" struct altogether and make the subclass proper QOM objects. Public APIs still rely on backend being an AudioDriver. They will assert() if not. This will be addressed later to allow other backends. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_int.h | 25 +++++--- audio/audio_template.h | 18 +++--- include/qemu/audio.h | 17 +++++- audio/alsaaudio.c | 2 +- audio/audio.c | 126 +++++++++++++++++++++++++++++++---------- audio/dbusaudio.c | 8 +-- audio/ossaudio.c | 4 +- ui/dbus.c | 3 +- 8 files changed, 142 insertions(+), 61 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index b2b8002477..e1f962875f 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -61,7 +61,7 @@ struct audio_pcm_info { int swap_endianness; }; =20 -typedef struct AudioBackend AudioBackend; +typedef struct AudioDriver AudioDriver; typedef struct SWVoiceCap SWVoiceCap; =20 typedef struct STSampleBuffer { @@ -70,7 +70,7 @@ typedef struct STSampleBuffer { } STSampleBuffer; =20 typedef struct HWVoiceOut { - AudioBackend *s; + AudioDriver *s; bool enabled; int poll_mode; bool pending_disable; @@ -91,7 +91,7 @@ typedef struct HWVoiceOut { } HWVoiceOut; =20 typedef struct HWVoiceIn { - AudioBackend *s; + AudioDriver *s; bool enabled; int poll_mode; struct audio_pcm_info info; @@ -112,7 +112,7 @@ typedef struct HWVoiceIn { } HWVoiceIn; =20 struct SWVoiceOut { - AudioBackend *s; + AudioDriver *s; struct audio_pcm_info info; t_sample *conv; STSampleBuffer resample_buf; @@ -128,7 +128,7 @@ struct SWVoiceOut { }; =20 struct SWVoiceIn { - AudioBackend *s; + AudioDriver *s; bool active; struct audio_pcm_info info; void *rate; @@ -241,8 +241,12 @@ struct SWVoiceCap { QLIST_ENTRY (SWVoiceCap) entries; }; =20 -typedef struct AudioBackend { - Object parent; +struct AudioDriverClass { + AudioBackendClass parent_class; +}; + +struct AudioDriver { + AudioBackend parent_obj; =20 struct audio_driver *drv; Audiodev *dev; @@ -260,7 +264,7 @@ typedef struct AudioBackend { bool timer_running; uint64_t timer_last; VMChangeStateEntry *vmse; -} AudioBackend; +}; =20 extern const struct mixeng_volume nominal_volume; =20 @@ -273,7 +277,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *i= nfo, void *buf, int len); =20 int audio_bug (const char *funcname, int cond); =20 -void audio_run(AudioBackend *s, const char *msg); +void audio_run(AudioDriver *s, const char *msg); =20 const char *audio_application_name(void); =20 @@ -326,4 +330,7 @@ void audio_create_pdos(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev); =20 +#define TYPE_AUDIO_DRIVER "audio-driver" +OBJECT_DECLARE_TYPE(AudioDriver, AudioDriverClass, AUDIO_DRIVER) + #endif /* QEMU_AUDIO_INT_H */ diff --git a/audio/audio_template.h b/audio/audio_template.h index 1ab3c47fd7..925a878f6d 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -36,7 +36,7 @@ #define HWBUF hw->conv_buf #endif =20 -static void glue(audio_init_nb_voices_, TYPE)(AudioBackend *s, +static void glue(audio_init_nb_voices_, TYPE)(AudioDriver *s, struct audio_driver *drv, in= t min_voices) { int max_voices =3D glue (drv->max_voices_, TYPE); @@ -221,7 +221,7 @@ static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw) static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp) { HW *hw =3D *hwp; - AudioBackend *s =3D hw->s; + AudioDriver *s =3D hw->s; =20 if (!hw->sw_head.lh_first) { #ifdef DAC @@ -236,12 +236,12 @@ static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp) } } =20 -static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioBackend *s, HW *hw) +static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioDriver *s, HW *hw) { return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first; } =20 -static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioBackend *s, HW = *hw) +static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioDriver *s, HW *= hw) { while ((hw =3D glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) { if (hw->enabled) { @@ -251,7 +251,7 @@ static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(A= udioBackend *s, HW *hw) return NULL; } =20 -static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioBackend *s, HW *hw, +static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioDriver *s, HW *hw, struct audsettings *as) { while ((hw =3D glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) { @@ -262,7 +262,7 @@ static HW *glue(audio_pcm_hw_find_specific_, TYPE)(Audi= oBackend *s, HW *hw, return NULL; } =20 -static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioBackend *s, +static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioDriver *s, struct audsettings *as) { HW *hw; @@ -398,7 +398,7 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)= (Audiodev *dev) abort(); } =20 -static HW *glue(audio_pcm_hw_add_, TYPE)(AudioBackend *s, struct audsettin= gs *as) +static HW *glue(audio_pcm_hw_add_, TYPE)(AudioDriver *s, struct audsetting= s *as) { HW *hw; AudiodevPerDirectionOptions *pdo =3D glue(audio_get_pdo_, TYPE)(s->dev= ); @@ -424,7 +424,7 @@ static HW *glue(audio_pcm_hw_add_, TYPE)(AudioBackend *= s, struct audsettings *as } =20 static SW *glue(audio_pcm_create_voice_pair_, TYPE)( - AudioBackend *s, + AudioDriver *s, const char *sw_name, struct audsettings *as ) @@ -494,7 +494,7 @@ SW *glue (AUD_open_, TYPE) ( struct audsettings *as ) { - AudioBackend *s =3D be; + AudioDriver *s =3D AUDIO_DRIVER(be); AudiodevPerDirectionOptions *pdo; =20 if (audio_bug(__func__, !be || !name || !callback_fn || !as)) { diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 2562710bec..f83f8326ab 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -44,11 +44,21 @@ typedef struct audsettings { typedef struct SWVoiceOut SWVoiceOut; typedef struct SWVoiceIn SWVoiceIn; =20 -struct AudioBackendClass { +typedef struct AudioBackend { + Object parent_obj; +} AudioBackend; + +typedef struct AudioBackendClass { ObjectClass parent_class; -}; =20 -typedef struct AudioBackend AudioBackend; + const char *(*get_id)(AudioBackend *be); +#ifdef CONFIG_GIO + bool (*set_dbus_server)(AudioBackend *be, + GDBusObjectManagerServer *manager, + bool p2p, + Error **errp); +#endif +} AudioBackendClass; =20 typedef struct QEMUAudioTimeStamp { uint64_t old_ts; @@ -129,6 +139,7 @@ AudioBackend *audio_be_by_name(const char *name, Error = **errp); AudioBackend *audio_get_default_audio_be(Error **errp); const char *audio_be_get_id(AudioBackend *be); #ifdef CONFIG_GIO +bool audio_be_can_set_dbus_server(AudioBackend *be); bool audio_be_set_dbus_server(AudioBackend *be, GDBusObjectManagerServer *server, bool p2p, diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 7d7da576dc..278c74c5de 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -41,7 +41,7 @@ struct pollhlp { struct pollfd *pfds; int count; int mask; - AudioBackend *s; + AudioDriver *s; }; =20 typedef struct ALSAVoiceOut { diff --git a/audio/audio.c b/audio/audio.c index 0f992a775c..4a43761528 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -36,6 +36,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include "qemu/help_option.h" +#include "qom/object.h" #include "system/system.h" #include "system/replay.h" #include "system/runstate.h" @@ -383,7 +384,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *i= nfo, void *buf, int len) /* * Capture */ -static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioBackend *s, +static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioDriver *s, struct audsettings= *as) { CaptureVoiceOut *cap; @@ -463,7 +464,7 @@ static void audio_detach_capture (HWVoiceOut *hw) =20 static int audio_attach_capture (HWVoiceOut *hw) { - AudioBackend *s =3D hw->s; + AudioDriver *s =3D hw->s; CaptureVoiceOut *cap; =20 audio_detach_capture (hw); @@ -801,7 +802,7 @@ static void audio_pcm_print_info (const char *cap, stru= ct audio_pcm_info *info) /* * Timer */ -static int audio_is_timer_needed(AudioBackend *s) +static int audio_is_timer_needed(AudioDriver *s) { HWVoiceIn *hwi =3D NULL; HWVoiceOut *hwo =3D NULL; @@ -819,7 +820,7 @@ static int audio_is_timer_needed(AudioBackend *s) return 0; } =20 -static void audio_reset_timer(AudioBackend *s) +static void audio_reset_timer(AudioDriver *s) { if (audio_is_timer_needed(s)) { timer_mod_anticipate_ns(s->ts, @@ -841,7 +842,7 @@ static void audio_reset_timer(AudioBackend *s) static void audio_timer (void *opaque) { int64_t now, diff; - AudioBackend *s =3D opaque; + AudioDriver *s =3D opaque; =20 now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); diff =3D now - s->timer_last; @@ -924,7 +925,7 @@ void AUD_set_active_out(SWVoiceOut *sw, bool on) =20 hw =3D sw->hw; if (sw->active !=3D on) { - AudioBackend *s =3D sw->s; + AudioDriver *s =3D sw->s; SWVoiceOut *temp_sw; SWVoiceCap *sc; =20 @@ -972,7 +973,7 @@ void AUD_set_active_in(SWVoiceIn *sw, bool on) =20 hw =3D sw->hw; if (sw->active !=3D on) { - AudioBackend *s =3D sw->s; + AudioDriver *s =3D sw->s; SWVoiceIn *temp_sw; =20 if (on) { @@ -1140,7 +1141,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, si= ze_t live) return clipped; } =20 -static void audio_run_out(AudioBackend *s) +static void audio_run_out(AudioDriver *s) { HWVoiceOut *hw =3D NULL; SWVoiceOut *sw; @@ -1294,7 +1295,7 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size= _t samples) return conv; } =20 -static void audio_run_in(AudioBackend *s) +static void audio_run_in(AudioDriver *s) { HWVoiceIn *hw =3D NULL; =20 @@ -1342,7 +1343,7 @@ static void audio_run_in(AudioBackend *s) } } =20 -static void audio_run_capture(AudioBackend *s) +static void audio_run_capture(AudioDriver *s) { CaptureVoiceOut *cap; =20 @@ -1389,7 +1390,7 @@ static void audio_run_capture(AudioBackend *s) } } =20 -void audio_run(AudioBackend *s, const char *msg) +void audio_run(AudioDriver *s, const char *msg) { audio_run_out(s); audio_run_in(s); @@ -1562,8 +1563,8 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, s= ize_t size) return total; } =20 -static bool audio_driver_init(AudioBackend *s, struct audio_driver *drv, - Audiodev *dev, Error **errp) +static bool audio_driver_do_init(AudioDriver *s, struct audio_driver *drv, + Audiodev *dev, Error **errp) { s->drv_opaque =3D drv->init(dev, errp); if (!s->drv_opaque) { @@ -1595,7 +1596,7 @@ static bool audio_driver_init(AudioBackend *s, struct= audio_driver *drv, static void audio_vm_change_state_handler (void *opaque, bool running, RunState state) { - AudioBackend *s =3D opaque; + AudioDriver *s =3D opaque; HWVoiceOut *hwo =3D NULL; HWVoiceIn *hwi =3D NULL; =20 @@ -1618,7 +1619,47 @@ static const VMStateDescription vmstate_audio; =20 static void audio_be_init(Object *obj) { - AudioBackend *s =3D AUDIO_BACKEND(obj); +} + +static void audio_be_finalize(Object *obj) +{ +} + +static const char *audio_driver_get_id(AudioBackend *be) +{ + return AUDIO_DRIVER(be)->dev->id; +} + +#ifdef CONFIG_GIO +static bool audio_driver_set_dbus_server(AudioBackend *be, + GDBusObjectManagerServer *mana= ger, + bool p2p, + Error **errp) +{ + AudioDriver *d =3D AUDIO_DRIVER(be); + + if (!d->drv->set_dbus_server) { + return false; + } + + return d->drv->set_dbus_server(be, manager, p2p, errp); +} + +#endif + +static void audio_driver_class_init(ObjectClass *klass, const void *data) +{ + AudioBackendClass *be =3D AUDIO_BACKEND_CLASS(klass); + + be->get_id =3D audio_driver_get_id; +#ifdef CONFIG_GIO + be->set_dbus_server =3D audio_driver_set_dbus_server; +#endif +} + +static void audio_driver_init(Object *obj) +{ + AudioDriver *s =3D AUDIO_DRIVER(obj); =20 QLIST_INIT(&s->hw_head_out); QLIST_INIT(&s->hw_head_in); @@ -1631,9 +1672,9 @@ static void audio_be_init(Object *obj) vmstate_register_any(NULL, &vmstate_audio, s); } =20 -static void audio_be_finalize(Object *obj) +static void audio_driver_finalize(Object *obj) { - AudioBackend *s =3D AUDIO_BACKEND(obj); + AudioDriver *s =3D AUDIO_DRIVER(obj); HWVoiceOut *hwo, *hwon; HWVoiceIn *hwi, *hwin; =20 @@ -1749,10 +1790,10 @@ static AudioBackend *audio_init(Audiodev *dev, Erro= r **errp) { int done =3D 0; const char *drvname; - AudioBackend *s; + AudioDriver *s; struct audio_driver *driver; =20 - s =3D AUDIO_BACKEND(object_new(TYPE_AUDIO_BACKEND)); + s =3D AUDIO_DRIVER(object_new(TYPE_AUDIO_DRIVER)); =20 if (dev) { /* -audiodev option */ @@ -1760,7 +1801,7 @@ static AudioBackend *audio_init(Audiodev *dev, Error = **errp) drvname =3D AudiodevDriver_str(dev->driver); driver =3D audio_driver_lookup(drvname); if (driver) { - done =3D audio_driver_init(s, driver, dev, errp); + done =3D audio_driver_do_init(s, driver, dev, errp); } else { error_setg(errp, "Unknown audio driver `%s'", drvname); } @@ -1780,7 +1821,7 @@ static AudioBackend *audio_init(Audiodev *dev, Error = **errp) g_free(e); drvname =3D AudiodevDriver_str(dev->driver); driver =3D audio_driver_lookup(drvname); - if (audio_driver_init(s, driver, dev, NULL)) { + if (audio_driver_do_init(s, driver, dev, NULL)) { break; } qapi_free_Audiodev(dev); @@ -1792,7 +1833,7 @@ static AudioBackend *audio_init(Audiodev *dev, Error = **errp) goto out; } object_unref(s); - return s; + return AUDIO_BACKEND(s); =20 out: object_unref(s); @@ -1831,17 +1872,19 @@ bool AUD_backend_check(AudioBackend **be, Error **e= rrp) static struct audio_pcm_ops capture_pcm_ops; =20 CaptureVoiceOut *AUD_add_capture( - AudioBackend *s, + AudioBackend *be, struct audsettings *as, struct audio_capture_ops *ops, void *cb_opaque ) { + AudioDriver *s =3D AUDIO_DRIVER(be); CaptureVoiceOut *cap; struct capture_callback *cb; =20 if (!s) { - error_report("Capturing without setting an audiodev is not support= ed"); + /* TODO: implement an interface instead (or drop capture support) = */ + error_report("Capturing without setting an audiodev driver is not = supported"); abort(); } =20 @@ -2227,27 +2270,36 @@ AudioBackend *audio_be_by_name(const char *name, Er= ror **errp) } =20 #ifdef CONFIG_GIO +bool audio_be_can_set_dbus_server(AudioBackend *be) +{ + /* + * AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + * return klass->set_dbus_server !=3D NULL; + */ + return AUDIO_DRIVER(be)->drv->set_dbus_server !=3D NULL; +} + bool audio_be_set_dbus_server(AudioBackend *be, GDBusObjectManagerServer *server, bool p2p, Error **errp) { - assert(be !=3D NULL); + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 - if (!be->drv->set_dbus_server) { - error_setg(errp, "Audiodev '%s' is not compatible with DBus", be->= dev->id); + if (!audio_be_can_set_dbus_server(be)) { + error_setg(errp, "Audiodev '%s' is not compatible with DBus", + audio_be_get_id(be)); return false; } =20 - return be->drv->set_dbus_server(be, server, p2p, errp); + return klass->set_dbus_server(be, server, p2p, errp); } #endif =20 const char *audio_be_get_id(AudioBackend *be) { if (be) { - assert(be->dev); - return be->dev->id; + return AUDIO_BACKEND_GET_CLASS(be)->get_id(be); } else { return ""; } @@ -2322,13 +2374,25 @@ static const TypeInfo audio_be_info =3D { .instance_size =3D sizeof(AudioBackend), .instance_init =3D audio_be_init, .instance_finalize =3D audio_be_finalize, - .abstract =3D false, /* TODO: subclass drivers and make it abstract */ + .abstract =3D true, .class_size =3D sizeof(AudioBackendClass), }; =20 +static const TypeInfo audio_driver_info =3D { + .name =3D TYPE_AUDIO_DRIVER, + .parent =3D TYPE_AUDIO_BACKEND, + .instance_size =3D sizeof(AudioDriver), + .instance_init =3D audio_driver_init, + .instance_finalize =3D audio_driver_finalize, + .abstract =3D false, + .class_size =3D sizeof(AudioDriverClass), + .class_init =3D audio_driver_class_init, +}; + static void register_types(void) { type_register_static(&audio_be_info); + type_register_static(&audio_driver_info); } =20 type_init(register_types); diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index 1fe7c4ed64..71b2a6c2cf 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -464,7 +464,7 @@ listener_in_vanished_cb(GDBusConnection *connection, } =20 static gboolean -dbus_audio_register_listener(AudioBackend *s, +dbus_audio_register_listener(AudioDriver *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -621,7 +621,7 @@ dbus_audio_register_listener(AudioBackend *s, } =20 static gboolean -dbus_audio_register_out_listener(AudioBackend *s, +dbus_audio_register_out_listener(AudioDriver *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -637,7 +637,7 @@ dbus_audio_register_out_listener(AudioBackend *s, } =20 static gboolean -dbus_audio_register_in_listener(AudioBackend *s, +dbus_audio_register_in_listener(AudioDriver *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -657,7 +657,7 @@ dbus_audio_set_server(AudioBackend *s, bool p2p, Error **errp) { - DBusAudio *da =3D s->drv_opaque; + DBusAudio *da =3D AUDIO_DRIVER(s)->drv_opaque; =20 g_assert(da); g_assert(!da->server); diff --git a/audio/ossaudio.c b/audio/ossaudio.c index c6cad47a01..9576cdba51 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -107,13 +107,13 @@ static void oss_anal_close (int *fdp) =20 static void oss_helper_poll_out (void *opaque) { - AudioBackend *s =3D opaque; + AudioDriver *s =3D opaque; audio_run(s, "oss_poll_out"); } =20 static void oss_helper_poll_in (void *opaque) { - AudioBackend *s =3D opaque; + AudioDriver *s =3D opaque; audio_run(s, "oss_poll_in"); } =20 diff --git a/ui/dbus.c b/ui/dbus.c index 45fb3c1aa3..b0caa9b154 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -220,7 +220,7 @@ dbus_display_complete(UserCreatable *uc, Error **errp) } =20 AudioBackend *audio_be =3D audio_get_default_audio_be(NULL); - if (audio_be && !g_str_equal(audio_be->drv->name, "dbus")) { + if (audio_be && !audio_be_can_set_dbus_server(audio_be)) { audio_be =3D NULL; } if (dd->audiodev && *dd->audiodev) { @@ -233,7 +233,6 @@ dbus_display_complete(UserCreatable *uc, Error **errp) return; } =20 - consoles =3D g_array_new(FALSE, FALSE, sizeof(guint32)); for (idx =3D 0;; idx++) { if (!qemu_console_lookup_by_index(idx)) { --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588295; cv=none; d=zohomail.com; s=zohoarc; b=S6Z7E0TkD7RbMhDG+jZSMM2UuN2Tje/S4p5tP9hnaTjeLIxiMFp7yE7L0QtKHtzfQzbaNKfDLayZCGDJ9w6N7nsu6p32zzXcde8siyo2VaBmaIikWazTsx7gKinFOUqKWqEYxVukIfyI/+BGnuVrnHnyoSgOeu2l7+8N0F/OmSs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588295; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=2YjEQzyvj7ER2A0dLImTpPvbyU/77B1Cxnti3jqBgQ4=; b=KyR7fS+XBBs6yVJYoLFZJ7K80P4GCjBEqHkCHsK9PpJhPRUy1wk+6CmWu9P7++NOIgGES4O0u7ezTS2OZwQHFNCYquMpJp5eLkbn+wfrgU1NqeK18VSyJvQ7ffoQeqIP9DZ2ESc/FS2qIYj9EEX08B6AGOmrkw9Z1xTAEGk/QHU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588295630809.5516958018464; Mon, 1 Dec 2025 03:24:55 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ211-0000SF-PO; Mon, 01 Dec 2025 06:24:23 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20s-0000Aa-I7 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:17 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20p-0006Xj-Lh for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:14 -0500 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-81-uSLNVEeeNP66v7KxMvpSzg-1; Mon, 01 Dec 2025 06:23:57 -0500 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 954DE1956080; Mon, 1 Dec 2025 11:23:55 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2CD43195608E; Mon, 1 Dec 2025 11:23:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588243; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2YjEQzyvj7ER2A0dLImTpPvbyU/77B1Cxnti3jqBgQ4=; b=ZgO1Y9Dho921+2vctuuLdaJAGSWHEUphCSmQpGMOZX4NzCDabCrtOf/uWxDcuCRMcVdib0 KErwKvmv9hnqfHi+6112YxB12JzTUi2xQroWGPTRGk1HU1mWA/pbhH/tnHwt+OkBszjT04 5BgwQCt/61I2OJpKQYm41ShbALPwJQs= X-MC-Unique: uSLNVEeeNP66v7KxMvpSzg-1 X-Mimecast-MFC-AGG-ID: uSLNVEeeNP66v7KxMvpSzg_1764588235 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 06/24] audio: simplify audio_init() Date: Mon, 1 Dec 2025 15:22:47 +0400 Message-ID: <20251201112309.4163921-7-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588297087019200 From: Marc-Andr=C3=A9 Lureau Factorize looking up the driver in audio_driver_init() Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio.c | 66 ++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 4a43761528..7b978e862c 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1563,11 +1563,18 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf,= size_t size) return total; } =20 -static bool audio_driver_do_init(AudioDriver *s, struct audio_driver *drv, - Audiodev *dev, Error **errp) +static bool audio_driver_do_init(AudioDriver *d, Error **errp) { - s->drv_opaque =3D drv->init(dev, errp); - if (!s->drv_opaque) { + const char *drvname =3D AudiodevDriver_str(d->dev->driver); + struct audio_driver *drv =3D audio_driver_lookup(drvname); + + if (!drv) { + error_setg(errp, "Unknown audio driver `%s'", drvname); + return false; + } + + d->drv_opaque =3D drv->init(d->dev, errp); + if (!d->drv_opaque) { return false; } =20 @@ -1580,14 +1587,14 @@ static bool audio_driver_do_init(AudioDriver *s, st= ruct audio_driver *drv, drv->pcm_ops->put_buffer_out =3D audio_generic_put_buffer_out; } =20 - audio_init_nb_voices_out(s, drv, 1); - audio_init_nb_voices_in(s, drv, 0); - s->drv =3D drv; + audio_init_nb_voices_out(d, drv, 1); + audio_init_nb_voices_in(d, drv, 0); + d->drv =3D drv; =20 - if (dev->timer_period <=3D 0) { - s->period_ticks =3D 1; + if (d->dev->timer_period <=3D 0) { + d->period_ticks =3D 1; } else { - s->period_ticks =3D dev->timer_period * (int64_t)SCALE_US; + d->period_ticks =3D d->dev->timer_period * (int64_t)SCALE_US; } =20 return true; @@ -1788,24 +1795,12 @@ void audio_create_default_audiodevs(void) */ static AudioBackend *audio_init(Audiodev *dev, Error **errp) { - int done =3D 0; - const char *drvname; - AudioDriver *s; - struct audio_driver *driver; + AudioDriver *d; =20 - s =3D AUDIO_DRIVER(object_new(TYPE_AUDIO_DRIVER)); - - if (dev) { - /* -audiodev option */ - s->dev =3D dev; - drvname =3D AudiodevDriver_str(dev->driver); - driver =3D audio_driver_lookup(drvname); - if (driver) { - done =3D audio_driver_do_init(s, driver, dev, errp); - } else { - error_setg(errp, "Unknown audio driver `%s'", drvname); - } - if (!done) { + d =3D AUDIO_DRIVER(object_new(TYPE_AUDIO_DRIVER)); + d->dev =3D dev; + if (d->dev) { + if (!audio_driver_do_init(d, errp)) { goto out; } } else { @@ -1816,27 +1811,24 @@ static AudioBackend *audio_init(Audiodev *dev, Erro= r **errp) error_setg(errp, "no default audio driver available"); goto out; } - s->dev =3D dev =3D e->dev; + d->dev =3D e->dev; QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next); g_free(e); - drvname =3D AudiodevDriver_str(dev->driver); - driver =3D audio_driver_lookup(drvname); - if (audio_driver_do_init(s, driver, dev, NULL)) { + if (audio_driver_do_init(d, NULL)) { break; } - qapi_free_Audiodev(dev); - s->dev =3D NULL; } } =20 - if (!object_property_try_add_child(get_audiodevs_root(), dev->id, OBJE= CT(s), errp)) { + if (!object_property_try_add_child(get_audiodevs_root(), + d->dev->id, OBJECT(d), errp)) { goto out; } - object_unref(s); - return AUDIO_BACKEND(s); + object_unref(d); + return AUDIO_BACKEND(d); =20 out: - object_unref(s); + object_unref(d); return NULL; } =20 --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588286; cv=none; d=zohomail.com; s=zohoarc; b=aDPjd17eIhCNVafMYa5AVqNBg/saFKT+mzrOXpHMIVVY07NOXG+VDm8BEGC0CCPM5pyyoKkopAi1SqsKKe4Z9yt+jAV1jh5GlpW+ZgppYv1o+7JKRs0qHna0XmSqDEpA55s08aeJXiOLLNbAIBanWopJtIReOvqdMRu92RVF8xc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588286; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=eFakANaqmO6A83+P/MHbrOBs9AEyOy7Lrkd3AuAnQEc=; b=QNknzg24B5FccXjJ5kfAecynwTD+/VOKroHHTcxchfIPBrDWJwY+qXcaTXjskRt/TcuErdGxmOplfTSLQtEJzd4xduRuwPUUUXhyoBc7nKb1tkVHlivpNtiii9Kk1wgKjAdKdAzNg/7T6xvxUcUfYC33LVYskbAHDzWHU/mLySc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588286136204.77434016247435; Mon, 1 Dec 2025 03:24:46 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ215-0000jO-ME; Mon, 01 Dec 2025 06:24:27 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20s-0000AY-E4 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:16 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20p-0006Y0-Jb for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:14 -0500 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-166-ZyviYWkQPEWMsTMzkzS7dA-1; Mon, 01 Dec 2025 06:24:05 -0500 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EF2F4180061B; Mon, 1 Dec 2025 11:24:01 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3CB821955F1A; Mon, 1 Dec 2025 11:23:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eFakANaqmO6A83+P/MHbrOBs9AEyOy7Lrkd3AuAnQEc=; b=HCOc+6kUAKqm4zyF0yzB6qaZh9uAnohIQhTm0/h0dmFcHkyBf15AKzyjewW2+EndeQ6LBl zE8hF/nEDVXE7BWsmn0SJZqNj0otSQf/v/BKbLV/AQ4U3UMU7Pui//f+070QpDg0nn1kNP Se2Us2DwT313FFoa4Q5CLfh6sPr+SmE= X-MC-Unique: ZyviYWkQPEWMsTMzkzS7dA-1 X-Mimecast-MFC-AGG-ID: ZyviYWkQPEWMsTMzkzS7dA_1764588243 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 07/24] audio: move object creation to audio_driver_init() Date: Mon, 1 Dec 2025 15:22:48 +0400 Message-ID: <20251201112309.4163921-8-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588289384019200 From: Marc-Andr=C3=A9 Lureau As we will allow other kind of AudioBackend objects to be instantiated, move the object allocation to a dedicated function. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 7b978e862c..fab6024207 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1563,19 +1563,23 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf,= size_t size) return total; } =20 -static bool audio_driver_do_init(AudioDriver *d, Error **errp) +static AudioBackend *audio_be_new(Audiodev *dev, Error **errp) { - const char *drvname =3D AudiodevDriver_str(d->dev->driver); + const char *drvname =3D AudiodevDriver_str(dev->driver); struct audio_driver *drv =3D audio_driver_lookup(drvname); =20 if (!drv) { error_setg(errp, "Unknown audio driver `%s'", drvname); - return false; + return NULL; } =20 + AudioDriver *d =3D AUDIO_DRIVER(object_new(TYPE_AUDIO_DRIVER)); + d->dev =3D dev; + d->drv_opaque =3D drv->init(d->dev, errp); if (!d->drv_opaque) { - return false; + object_unref(OBJECT(d)); + return NULL; } =20 if (!drv->pcm_ops->get_buffer_in) { @@ -1597,7 +1601,7 @@ static bool audio_driver_do_init(AudioDriver *d, Erro= r **errp) d->period_ticks =3D d->dev->timer_period * (int64_t)SCALE_US; } =20 - return true; + return AUDIO_BACKEND(d); } =20 static void audio_vm_change_state_handler (void *opaque, bool running, @@ -1795,13 +1799,12 @@ void audio_create_default_audiodevs(void) */ static AudioBackend *audio_init(Audiodev *dev, Error **errp) { - AudioDriver *d; + AudioBackend *be; =20 - d =3D AUDIO_DRIVER(object_new(TYPE_AUDIO_DRIVER)); - d->dev =3D dev; - if (d->dev) { - if (!audio_driver_do_init(d, errp)) { - goto out; + if (dev) { + be =3D audio_be_new(dev, errp); + if (!be) { + return NULL; } } else { assert(!default_audio_be); @@ -1809,27 +1812,24 @@ static AudioBackend *audio_init(Audiodev *dev, Erro= r **errp) AudiodevListEntry *e =3D QSIMPLEQ_FIRST(&default_audiodevs); if (!e) { error_setg(errp, "no default audio driver available"); - goto out; + return NULL; } - d->dev =3D e->dev; QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next); + be =3D audio_be_new(e->dev, NULL); g_free(e); - if (audio_driver_do_init(d, NULL)) { + if (be) { break; } } } =20 if (!object_property_try_add_child(get_audiodevs_root(), - d->dev->id, OBJECT(d), errp)) { - goto out; + audio_be_get_id(be), OBJECT(be), er= rp)) { + object_unref(be); + return NULL; } - object_unref(d); - return AUDIO_BACKEND(d); - -out: - object_unref(d); - return NULL; + object_unref(be); + return be; } =20 AudioBackend *audio_get_default_audio_be(Error **errp) --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588318; cv=none; d=zohomail.com; s=zohoarc; b=fHDnMH8uZGwwwbA0g6pPO8VOmZFE0uomJNzhePAATQ5psQpsa65vPCevZJo/4EKXbw8pxEeOYcbwLvXBT80t5WXxnQE4801ndWVUChLfNWR5nfCoQmRyHfBBNqaFwqI4s2NIr/DuHnrD8Cjrsr4HGRVmcPjuP4AMrz373W49/Dc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588318; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=sJXOX2dGJoTMX57FacN+pymYbcqx6Y8biS2WWz387cE=; b=gjmrOexQPRON/q9u/RMdE2mGjMNlYENfCNatgPjEZarRYnFv2M6eOcPdEI61BaLefzeGxbxFKpyPbj/MesEyuvh5LWF+HfQP7R7dyfsn2jKrxS72Ap6gX/RIJMg3qzDPimR2RS/dCB5taMvrGz9k13QJaOaYp6hWUblO1ieXt/w= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588318327469.2592198956876; Mon, 1 Dec 2025 03:25:18 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ217-0000nS-49; Mon, 01 Dec 2025 06:24:29 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ211-0000We-U8 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:24 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ20z-0006Zm-2b for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:23 -0500 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-76-k0f0MMcJOQqQ0T9XeZ_vvA-1; Mon, 01 Dec 2025 06:24:15 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1E71C1955BCC; Mon, 1 Dec 2025 11:24:09 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0465B18008CC; Mon, 1 Dec 2025 11:24:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588260; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sJXOX2dGJoTMX57FacN+pymYbcqx6Y8biS2WWz387cE=; b=Y5ex0NCo4cdWhTnnqHi+mwpsfHqFlcsv7lJZWiuzvkaJNEtRtdXEk8ihjC27NaXC0k2iev M1dJVmGuVQCchtMVLKBZyITOWw/mY52DV/2hPffegDhEwFskINU+RIi9aw8IZ48qSC2Vli px5Ry8McVv7M6XUFZHCGy7SmksOhDbc= X-MC-Unique: k0f0MMcJOQqQ0T9XeZ_vvA-1 X-Mimecast-MFC-AGG-ID: k0f0MMcJOQqQ0T9XeZ_vvA_1764588253 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 08/24] audio: add QOM module-objects for each backend Date: Mon, 1 Dec 2025 15:22:49 +0400 Message-ID: <20251201112309.4163921-9-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588321390019200 From: Marc-Andr=C3=A9 Lureau This will allow to use QOM and the dynamic object module loading. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_int.h | 2 ++ audio/alsaaudio.c | 39 +++++++++++++++++++++++++++++++++++++++ audio/dbusaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/dsoundaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/jackaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/noaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/ossaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/paaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/pwaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/sdlaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/sndioaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/spiceaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/wavaudio.c | 36 ++++++++++++++++++++++++++++++++++++ audio/coreaudio.m | 36 ++++++++++++++++++++++++++++++++++++ 14 files changed, 473 insertions(+) diff --git a/audio/audio_int.h b/audio/audio_int.h index e1f962875f..44e63318e8 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -243,6 +243,8 @@ struct SWVoiceCap { =20 struct AudioDriverClass { AudioBackendClass parent_class; + + audio_driver *driver; }; =20 struct AudioDriver { diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 278c74c5de..c28ee05b93 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -27,6 +27,7 @@ #include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/audio.h" +#include "qom/object.h" #include "trace.h" =20 #pragma GCC diagnostic ignored "-Waddress" @@ -36,6 +37,32 @@ =20 #define DEBUG_ALSA 0 =20 +#define TYPE_AUDIO_ALSA "audio-alsa" +OBJECT_DECLARE_TYPE(AudioALSA, AudioBEDriverClass, AUDIO_ALSA) + +struct AudioALSA { + AudioDriver parent; +}; + +static struct audio_driver alsa_audio_driver; + +static void audio_alsa_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &alsa_audio_driver; +} + +static void audio_alsa_init(Object *obj) +{ + +} + +static void audio_alsa_finalize(Object *obj) +{ + +} + struct pollhlp { snd_pcm_t *handle; struct pollfd *pfds; @@ -945,8 +972,20 @@ static struct audio_driver alsa_audio_driver =3D { .voice_size_in =3D sizeof (ALSAVoiceIn) }; =20 +static const TypeInfo audio_alsa_info =3D { + .name =3D TYPE_AUDIO_ALSA, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioALSA), + .instance_init =3D audio_alsa_init, + .instance_finalize =3D audio_alsa_finalize, + .class_init =3D audio_alsa_class_init, +}; + + static void register_audio_alsa(void) { audio_driver_register(&alsa_audio_driver); + type_register_static(&audio_alsa_info); } type_init(register_audio_alsa); +module_obj(TYPE_AUDIO_ALSA); diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index 71b2a6c2cf..f0b17be6e8 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -26,6 +26,7 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/dbus.h" +#include "qom/object.h" =20 #ifdef G_OS_UNIX #include @@ -44,6 +45,30 @@ =20 #define DBUS_DEFAULT_AUDIO_NSAMPLES 480 =20 +#define TYPE_AUDIO_DBUS "audio-dbus" +OBJECT_DECLARE_TYPE(AudioDbus, AudioDriverClass, AUDIO_DBUS) + +struct AudioDbus { + AudioDriver parent; +}; + +static struct audio_driver dbus_audio_driver; + +static void audio_dbus_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &dbus_audio_driver; +} + +static void audio_dbus_init(Object *obj) +{ +} + +static void audio_dbus_finalize(Object *obj) +{ +} + typedef struct DBusAudio { Audiodev *dev; GDBusObjectManagerServer *server; @@ -711,10 +736,21 @@ static struct audio_driver dbus_audio_driver =3D { .voice_size_in =3D sizeof(DBusVoiceIn) }; =20 +static const TypeInfo audio_dbus_info =3D { + .name =3D TYPE_AUDIO_DBUS, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioDbus), + .instance_init =3D audio_dbus_init, + .instance_finalize =3D audio_dbus_finalize, + .class_init =3D audio_dbus_class_init, +}; + static void register_audio_dbus(void) { audio_driver_register(&dbus_audio_driver); + type_register_static(&audio_dbus_info); } type_init(register_audio_dbus); =20 module_dep("ui-dbus") +module_obj(TYPE_AUDIO_DBUS) diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 7a03d1dad8..341df9e6d8 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -33,6 +33,7 @@ #include "audio_int.h" #include "qemu/module.h" #include "qapi/error.h" +#include "qom/object.h" =20 #include #include @@ -41,6 +42,30 @@ =20 #include "audio_win_int.h" =20 +#define TYPE_AUDIO_DSOUND "audio-dsound" +OBJECT_DECLARE_TYPE(AudioDsound, AudioDriverClass, AUDIO_DSOUND) + +struct AudioDsound { + AudioDriver parent; +}; + +static struct audio_driver dsound_audio_driver; + +static void audio_dsound_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &dsound_audio_driver; +} + +static void audio_dsound_init(Object *obj) +{ +} + +static void audio_dsound_finalize(Object *obj) +{ +} + /* #define DEBUG_DSOUND */ =20 typedef struct { @@ -694,8 +719,19 @@ static struct audio_driver dsound_audio_driver =3D { .voice_size_in =3D sizeof (DSoundVoiceIn) }; =20 +static const TypeInfo audio_dsound_info =3D { + .name =3D TYPE_AUDIO_DSOUND, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioDsound), + .instance_init =3D audio_dsound_init, + .instance_finalize =3D audio_dsound_finalize, + .class_init =3D audio_dsound_class_init, +}; + static void register_audio_dsound(void) { audio_driver_register(&dsound_audio_driver); + type_register_static(&audio_dsound_info); } type_init(register_audio_dsound); +module_obj(TYPE_AUDIO_DSOUND); diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 7a3fcaedba..7706fbcb6e 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -27,6 +27,7 @@ #include "qemu/atomic.h" #include "qemu/main-loop.h" #include "qemu/audio.h" +#include "qom/object.h" =20 #define AUDIO_CAP "jack" #include "audio_int.h" @@ -34,6 +35,30 @@ #include #include =20 +#define TYPE_AUDIO_JACK "audio-jack" +OBJECT_DECLARE_TYPE(AudioJack, AudioDriverClass, AUDIO_JACK) + +struct AudioJack { + AudioDriver parent; +}; + +static struct audio_driver jack_driver; + +static void audio_jack_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &jack_driver; +} + +static void audio_jack_init(Object *obj) +{ +} + +static void audio_jack_finalize(Object *obj) +{ +} + struct QJack; =20 typedef enum QJackState { @@ -691,10 +716,20 @@ static void qjack_info(const char *msg) dolog("I: %s\n", msg); } =20 +static const TypeInfo audio_jack_info =3D { + .name =3D TYPE_AUDIO_JACK, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioJack), + .instance_init =3D audio_jack_init, + .instance_finalize =3D audio_jack_finalize, + .class_init =3D audio_jack_class_init, +}; + static void register_audio_jack(void) { qemu_mutex_init(&qjack_shutdown_lock); audio_driver_register(&jack_driver); + type_register_static(&audio_jack_info); #if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID) jack_set_thread_creator(qjack_thread_creator); #endif @@ -702,3 +737,4 @@ static void register_audio_jack(void) jack_set_info_function(qjack_info); } type_init(register_audio_jack); +module_obj(TYPE_AUDIO_JACK); diff --git a/audio/noaudio.c b/audio/noaudio.c index 4ed9d2156c..6f5af23004 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -25,10 +25,35 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "qemu/audio.h" +#include "qom/object.h" =20 #define AUDIO_CAP "noaudio" #include "audio_int.h" =20 +#define TYPE_AUDIO_NONE "audio-none" +OBJECT_DECLARE_TYPE(AudioNone, AudioDriverClass, AUDIO_NONE) + +struct AudioNone { + AudioDriver parent; +}; + +static struct audio_driver no_audio_driver; + +static void audio_none_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &no_audio_driver; +} + +static void audio_none_init(Object *obj) +{ +} + +static void audio_none_finalize(Object *obj) +{ +} + typedef struct NoVoiceOut { HWVoiceOut hw; RateCtl rate; @@ -138,8 +163,19 @@ static struct audio_driver no_audio_driver =3D { .voice_size_in =3D sizeof (NoVoiceIn) }; =20 +static const TypeInfo audio_none_info =3D { + .name =3D TYPE_AUDIO_NONE, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioNone), + .instance_init =3D audio_none_init, + .instance_finalize =3D audio_none_finalize, + .class_init =3D audio_none_class_init, +}; + static void register_audio_none(void) { audio_driver_register(&no_audio_driver); + type_register_static(&audio_none_info); } type_init(register_audio_none); +module_obj(TYPE_AUDIO_NONE); diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 9576cdba51..f5ce04928a 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -30,11 +30,36 @@ #include "qemu/host-utils.h" #include "qapi/error.h" #include "qemu/audio.h" +#include "qom/object.h" #include "trace.h" =20 #define AUDIO_CAP "oss" #include "audio_int.h" =20 +#define TYPE_AUDIO_OSS "audio-oss" +OBJECT_DECLARE_TYPE(AudioOss, AudioDriverClass, AUDIO_OSS) + +struct AudioOss { + AudioDriver parent; +}; + +static struct audio_driver oss_audio_driver; + +static void audio_oss_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &oss_audio_driver; +} + +static void audio_oss_init(Object *obj) +{ +} + +static void audio_oss_finalize(Object *obj) +{ +} + #if defined OSS_GETVERSION && defined SNDCTL_DSP_POLICY #define USE_DSP_POLICY #endif @@ -772,8 +797,19 @@ static struct audio_driver oss_audio_driver =3D { .voice_size_in =3D sizeof (OSSVoiceIn) }; =20 +static const TypeInfo audio_oss_info =3D { + .name =3D TYPE_AUDIO_OSS, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioOss), + .instance_init =3D audio_oss_init, + .instance_finalize =3D audio_oss_finalize, + .class_init =3D audio_oss_class_init, +}; + static void register_audio_oss(void) { audio_driver_register(&oss_audio_driver); + type_register_static(&audio_oss_info); } type_init(register_audio_oss); +module_obj(TYPE_AUDIO_OSS); diff --git a/audio/paaudio.c b/audio/paaudio.c index 0c06a39719..abeb2c2d81 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -4,12 +4,37 @@ #include "qemu/module.h" #include "qemu/audio.h" #include "qapi/error.h" +#include "qom/object.h" =20 #include =20 #define AUDIO_CAP "pulseaudio" #include "audio_int.h" =20 +#define TYPE_AUDIO_PA "audio-pa" +OBJECT_DECLARE_TYPE(AudioPa, AudioDriverClass, AUDIO_PA) + +struct AudioPa { + AudioDriver parent; +}; + +static struct audio_driver pa_audio_driver; + +static void audio_pa_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &pa_audio_driver; +} + +static void audio_pa_init(Object *obj) +{ +} + +static void audio_pa_finalize(Object *obj) +{ +} + typedef struct PAConnection { char *server; int refcount; @@ -931,8 +956,19 @@ static struct audio_driver pa_audio_driver =3D { .voice_size_in =3D sizeof (PAVoiceIn), }; =20 +static const TypeInfo audio_pa_info =3D { + .name =3D TYPE_AUDIO_PA, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioPa), + .instance_init =3D audio_pa_init, + .instance_finalize =3D audio_pa_finalize, + .class_init =3D audio_pa_class_init, +}; + static void register_audio_pa(void) { audio_driver_register(&pa_audio_driver); + type_register_static(&audio_pa_info); } type_init(register_audio_pa); +module_obj(TYPE_AUDIO_PA); diff --git a/audio/pwaudio.c b/audio/pwaudio.c index 30f717ccac..5b51a933ae 100644 --- a/audio/pwaudio.c +++ b/audio/pwaudio.c @@ -13,6 +13,7 @@ #include "qemu/audio.h" #include "qemu/error-report.h" #include "qapi/error.h" +#include "qom/object.h" #include #include #include @@ -27,6 +28,30 @@ =20 #include "audio_int.h" =20 +#define TYPE_AUDIO_PW "audio-pipewire" +OBJECT_DECLARE_TYPE(AudioPw, AudioDriverClass, AUDIO_PW) + +struct AudioPw { + AudioDriver parent; +}; + +static struct audio_driver pw_audio_driver; + +static void audio_pw_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &pw_audio_driver; +} + +static void audio_pw_init(Object *obj) +{ +} + +static void audio_pw_finalize(Object *obj) +{ +} + typedef struct pwvolume { uint32_t channels; float values[SPA_AUDIO_MAX_CHANNELS]; @@ -847,10 +872,21 @@ static struct audio_driver pw_audio_driver =3D { .voice_size_in =3D sizeof(PWVoiceIn), }; =20 +static const TypeInfo audio_pw_info =3D { + .name =3D TYPE_AUDIO_PW, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioPw), + .instance_init =3D audio_pw_init, + .instance_finalize =3D audio_pw_finalize, + .class_init =3D audio_pw_class_init, +}; + static void register_audio_pw(void) { audio_driver_register(&pw_audio_driver); + type_register_static(&audio_pw_info); } =20 type_init(register_audio_pw); +module_obj(TYPE_AUDIO_PW); diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 707110973a..65fab1427e 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -28,6 +28,7 @@ #include "qemu/module.h" #include "qapi/error.h" #include "qemu/audio.h" +#include "qom/object.h" =20 #ifndef _WIN32 #ifdef __sun__ @@ -40,6 +41,30 @@ #define AUDIO_CAP "sdl" #include "audio_int.h" =20 +#define TYPE_AUDIO_SDL "audio-sdl" +OBJECT_DECLARE_TYPE(AudioSdl, AudioDriverClass, AUDIO_SDL) + +struct AudioSdl { + AudioDriver parent; +}; + +static struct audio_driver sdl_audio_driver; + +static void audio_sdl_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &sdl_audio_driver; +} + +static void audio_sdl_init(Object *obj) +{ +} + +static void audio_sdl_finalize(Object *obj) +{ +} + typedef struct SDLVoiceOut { HWVoiceOut hw; int exit; @@ -491,8 +516,19 @@ static struct audio_driver sdl_audio_driver =3D { .voice_size_in =3D sizeof(SDLVoiceIn), }; =20 +static const TypeInfo audio_sdl_info =3D { + .name =3D TYPE_AUDIO_SDL, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioSdl), + .instance_init =3D audio_sdl_init, + .instance_finalize =3D audio_sdl_finalize, + .class_init =3D audio_sdl_class_init, +}; + static void register_audio_sdl(void) { audio_driver_register(&sdl_audio_driver); + type_register_static(&audio_sdl_info); } type_init(register_audio_sdl); +module_obj(TYPE_AUDIO_SDL); diff --git a/audio/sndioaudio.c b/audio/sndioaudio.c index 8197b8b0b4..1a4912fb60 100644 --- a/audio/sndioaudio.c +++ b/audio/sndioaudio.c @@ -20,10 +20,35 @@ #include "qemu/main-loop.h" #include "qemu/audio.h" #include "trace.h" +#include "qom/object.h" =20 #define AUDIO_CAP "sndio" #include "audio_int.h" =20 +#define TYPE_AUDIO_SNDIO "audio-sndio" +OBJECT_DECLARE_TYPE(AudioSndio, AudioDriverClass, AUDIO_SNDIO) + +struct AudioSndio { + AudioDriver parent; +}; + +static struct audio_driver sndio_audio_driver; + +static void audio_sndio_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &sndio_audio_driver; +} + +static void audio_sndio_init(Object *obj) +{ +} + +static void audio_sndio_finalize(Object *obj) +{ +} + /* default latency in microseconds if no option is set */ #define SNDIO_LATENCY_US 50000 =20 @@ -555,9 +580,20 @@ static struct audio_driver sndio_audio_driver =3D { .voice_size_in =3D sizeof(SndioVoice) }; =20 +static const TypeInfo audio_sndio_info =3D { + .name =3D TYPE_AUDIO_SNDIO, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioSndio), + .instance_init =3D audio_sndio_init, + .instance_finalize =3D audio_sndio_finalize, + .class_init =3D audio_sndio_class_init, +}; + static void register_audio_sndio(void) { audio_driver_register(&sndio_audio_driver); + type_register_static(&audio_sndio_info); } =20 type_init(register_audio_sndio); +module_obj(TYPE_AUDIO_SNDIO); diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 7db2d1f0df..d8451d5877 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -24,11 +24,36 @@ #include "qemu/timer.h" #include "qapi/error.h" #include "ui/qemu-spice.h" +#include "qom/object.h" =20 #define AUDIO_CAP "spice" #include "qemu/audio.h" #include "audio_int.h" =20 +#define TYPE_AUDIO_SPICE "audio-spice" +OBJECT_DECLARE_TYPE(AudioSpice, AudioDriverClass, AUDIO_SPICE) + +struct AudioSpice { + AudioDriver parent; +}; + +static struct audio_driver spice_audio_driver; + +static void audio_spice_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &spice_audio_driver; +} + +static void audio_spice_init(Object *obj) +{ +} + +static void audio_spice_finalize(Object *obj) +{ +} + #if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= =3D 3 #define LINE_OUT_SAMPLES (480 * 4) #else @@ -325,10 +350,21 @@ static struct audio_driver spice_audio_driver =3D { .voice_size_in =3D sizeof (SpiceVoiceIn), }; =20 +static const TypeInfo audio_spice_info =3D { + .name =3D TYPE_AUDIO_SPICE, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioSpice), + .instance_init =3D audio_spice_init, + .instance_finalize =3D audio_spice_finalize, + .class_init =3D audio_spice_class_init, +}; + static void register_audio_spice(void) { audio_driver_register(&spice_audio_driver); + type_register_static(&audio_spice_info); } type_init(register_audio_spice); +module_obj(TYPE_AUDIO_SPICE); =20 module_dep("ui-spice-core"); diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 46460a5d57..3c1f352f11 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -25,10 +25,35 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "qemu/audio.h" +#include "qom/object.h" =20 #define AUDIO_CAP "wav" #include "audio_int.h" =20 +#define TYPE_AUDIO_WAV "audio-wav" +OBJECT_DECLARE_TYPE(AudioWav, AudioDriverClass, AUDIO_WAV) + +struct AudioWav { + AudioDriver parent; +}; + +static struct audio_driver wav_audio_driver; + +static void audio_wav_class_init(ObjectClass *klass, const void *data) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &wav_audio_driver; +} + +static void audio_wav_init(Object *obj) +{ +} + +static void audio_wav_finalize(Object *obj) +{ +} + typedef struct WAVVoiceOut { HWVoiceOut hw; FILE *f; @@ -214,8 +239,19 @@ static struct audio_driver wav_audio_driver =3D { .voice_size_in =3D 0 }; =20 +static const TypeInfo audio_wav_info =3D { + .name =3D TYPE_AUDIO_WAV, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioWav), + .instance_init =3D audio_wav_init, + .instance_finalize =3D audio_wav_finalize, + .class_init =3D audio_wav_class_init, +}; + static void register_audio_wav(void) { audio_driver_register(&wav_audio_driver); + type_register_static(&audio_wav_info); } type_init(register_audio_wav); +module_obj(TYPE_AUDIO_WAV); diff --git a/audio/coreaudio.m b/audio/coreaudio.m index 997017a1e9..d1a837f4bc 100644 --- a/audio/coreaudio.m +++ b/audio/coreaudio.m @@ -29,10 +29,35 @@ #include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/audio.h" +#include "qom/object.h" =20 #define AUDIO_CAP "coreaudio" #include "audio_int.h" =20 +#define TYPE_AUDIO_COREAUDIO "audio-coreaudio" +OBJECT_DECLARE_TYPE(AudioCoreaudio, AudioDriverClass, AUDIO_COREAUDIO) + +struct AudioCoreaudio { + AudioDriver parent; +}; + +static struct audio_driver coreaudio_audio_driver; + +static void audio_coreaudio_class_init(ObjectClass *klass, const void *dat= a) +{ + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + k->driver =3D &coreaudio_audio_driver; +} + +static void audio_coreaudio_init(Object *obj) +{ +} + +static void audio_coreaudio_finalize(Object *obj) +{ +} + typedef struct coreaudioVoiceOut { HWVoiceOut hw; pthread_mutex_t buf_mutex; @@ -673,8 +698,19 @@ static void coreaudio_audio_fini (void *opaque) .voice_size_in =3D 0 }; =20 +static const TypeInfo audio_coreaudio_info =3D { + .name =3D TYPE_AUDIO_COREAUDIO, + .parent =3D TYPE_AUDIO_DRIVER, + .instance_size =3D sizeof(AudioCoreaudio), + .instance_init =3D audio_coreaudio_init, + .instance_finalize =3D audio_coreaudio_finalize, + .class_init =3D audio_coreaudio_class_init, +}; + static void register_audio_coreaudio(void) { audio_driver_register(&coreaudio_audio_driver); + type_register_static(&audio_coreaudio_info); } type_init(register_audio_coreaudio); +module_obj(TYPE_AUDIO_COREAUDIO); --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588287; cv=none; d=zohomail.com; s=zohoarc; b=DCTm+t3cPshJO50Mqpy5DNMAjtbZ9HbLCZNZ0STxp35X6d9dYVnj/eix3Wl0ciTvygmW5o/hx6XJg8NTeB3sXYsjjhnf7sSem9EvgpQHXQw/T5qWsLg6LCFN8dcjVM+DQw85N1cEPoVsV/3WGxt4o9YwH5vQ4emmRoE9PRjsZvA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588287; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=TlG1sPXnGLhOhnk3rhuSP7v3hdO6MZAFD+uX2XjeOcs=; b=JYEytGgu1+4J9W7EYHAFiW/744Cv8Ct8EmuzEpvI5J1gp7TIXX4pjxbbVeblsA/YgfVv1YKeywPipPoIc5TVR6/af8GsPCgP+vj1FWrWanJGSW+jpY413eZnn0aKSZcXsTLG6W8Kdzbi2aImYJpAmmb4uRxgcOIvET5T2XUQsy8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588287798474.77738703761156; Mon, 1 Dec 2025 03:24:47 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ21B-00019r-Df; Mon, 01 Dec 2025 06:24:33 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ219-000113-DQ for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:31 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ217-0006aT-I8 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:31 -0500 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-614-C6o0hx1FPyCKA6hrPzEl0w-1; Mon, 01 Dec 2025 06:24:25 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 459E1180134A; Mon, 1 Dec 2025 11:24:16 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CB465180087B; Mon, 1 Dec 2025 11:24:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588268; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TlG1sPXnGLhOhnk3rhuSP7v3hdO6MZAFD+uX2XjeOcs=; b=ZbSHK/ShbCgdpQ6dmzjq0JCOk4AGvfrcjWUDXsQ3bnDOzYtiAYUjzNnpH10cBX/KrEUFfC SJwZkY6+rTJkwWbIkj+adXcpUzbJR+zXGuopFKFg8hDi3Sy63Zs9XQKAjgqQGklMzMIXXb SMI12kqgwXz+yiC5YYIbzDWG0xnOGLo= X-MC-Unique: C6o0hx1FPyCKA6hrPzEl0w-1 X-Mimecast-MFC-AGG-ID: C6o0hx1FPyCKA6hrPzEl0w_1764588264 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 09/24] audio: remove set_dbus_server from audio_driver Date: Mon, 1 Dec 2025 15:22:50 +0400 Message-ID: <20251201112309.4163921-10-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588289406019201 From: Marc-Andr=C3=A9 Lureau Use the QOM class vtable only instead. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_int.h | 6 ------ audio/audio.c | 28 +++------------------------- audio/dbusaudio.c | 34 ++++++++++++++++++---------------- 3 files changed, 21 insertions(+), 47 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index 44e63318e8..e289ef5f66 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -147,12 +147,6 @@ struct audio_driver { const char *name; void *(*init) (Audiodev *, Error **); void (*fini) (void *); -#ifdef CONFIG_GIO - bool (*set_dbus_server)(AudioBackend *be, - GDBusObjectManagerServer *manager, - bool p2p, - Error **errp); -#endif struct audio_pcm_ops *pcm_ops; int max_voices_out; int max_voices_in; diff --git a/audio/audio.c b/audio/audio.c index fab6024207..1693563c62 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1641,31 +1641,11 @@ static const char *audio_driver_get_id(AudioBackend= *be) return AUDIO_DRIVER(be)->dev->id; } =20 -#ifdef CONFIG_GIO -static bool audio_driver_set_dbus_server(AudioBackend *be, - GDBusObjectManagerServer *mana= ger, - bool p2p, - Error **errp) -{ - AudioDriver *d =3D AUDIO_DRIVER(be); - - if (!d->drv->set_dbus_server) { - return false; - } - - return d->drv->set_dbus_server(be, manager, p2p, errp); -} - -#endif - static void audio_driver_class_init(ObjectClass *klass, const void *data) { AudioBackendClass *be =3D AUDIO_BACKEND_CLASS(klass); =20 be->get_id =3D audio_driver_get_id; -#ifdef CONFIG_GIO - be->set_dbus_server =3D audio_driver_set_dbus_server; -#endif } =20 static void audio_driver_init(Object *obj) @@ -2264,11 +2244,9 @@ AudioBackend *audio_be_by_name(const char *name, Err= or **errp) #ifdef CONFIG_GIO bool audio_be_can_set_dbus_server(AudioBackend *be) { - /* - * AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - * return klass->set_dbus_server !=3D NULL; - */ - return AUDIO_DRIVER(be)->drv->set_dbus_server !=3D NULL; + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->set_dbus_server !=3D NULL; } =20 bool audio_be_set_dbus_server(AudioBackend *be, diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index f0b17be6e8..edd551a80f 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -54,21 +54,6 @@ struct AudioDbus { =20 static struct audio_driver dbus_audio_driver; =20 -static void audio_dbus_class_init(ObjectClass *klass, const void *data) -{ - AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); - - k->driver =3D &dbus_audio_driver; -} - -static void audio_dbus_init(Object *obj) -{ -} - -static void audio_dbus_finalize(Object *obj) -{ -} - typedef struct DBusAudio { Audiodev *dev; GDBusObjectManagerServer *server; @@ -728,7 +713,6 @@ static struct audio_driver dbus_audio_driver =3D { .name =3D "dbus", .init =3D dbus_audio_init, .fini =3D dbus_audio_fini, - .set_dbus_server =3D dbus_audio_set_server, .pcm_ops =3D &dbus_pcm_ops, .max_voices_out =3D INT_MAX, .max_voices_in =3D INT_MAX, @@ -736,6 +720,24 @@ static struct audio_driver dbus_audio_driver =3D { .voice_size_in =3D sizeof(DBusVoiceIn) }; =20 +static void audio_dbus_class_init(ObjectClass *klass, const void *data) +{ + AudioBackendClass *b =3D AUDIO_BACKEND_CLASS(klass); + AudioDriverClass *k =3D AUDIO_DRIVER_CLASS(klass); + + b->set_dbus_server =3D dbus_audio_set_server; + k->driver =3D &dbus_audio_driver; +} + +static void audio_dbus_init(Object *obj) +{ +} + +static void audio_dbus_finalize(Object *obj) +{ +} + + static const TypeInfo audio_dbus_info =3D { .name =3D TYPE_AUDIO_DBUS, .parent =3D TYPE_AUDIO_DRIVER, --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588293; cv=none; d=zohomail.com; s=zohoarc; b=ItD/Z4L8o3jk2mqkiA6WL39KEBqKHAIJwb0ezX3noL/FYyABDq6Wfx9h55uAVNhVmXBlEIwnnkHmcZ+2WhWW4NpJU5o+SSSnlppF+/cts53mhV56w2N5rbZ46uhfzeCYD5bIeaPqkO7FQQEbs4d1JXrMeNC6zI5yld44VMmVKi0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588293; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=g+OW/DPD4MLSKrF9wdP7p/as6/OerG5A2lPxhjUVmGM=; b=gsre6svxwDvGMBm2LL+zIHMlS3Xcih0YM1I0aehMhSdHvg/ntfnXm5scKmc7pX1E3YsMMHy5Uj6NO4WRFnttZklJMD5DsYdDsaYKATFmw/jT5y1vtYxu6aFHlFB3anIwlAiUkGEvJttrPC9EH/yMLcCX5nRUj1aIUfHtUKdM+8s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588293517285.60072302805906; Mon, 1 Dec 2025 03:24:53 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ21F-0001DD-Oa; Mon, 01 Dec 2025 06:24:37 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21E-0001Cc-H8 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:36 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21C-0006b7-Pd for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:36 -0500 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-154-bx10GkvtMFq_534SB5yHIA-1; Mon, 01 Dec 2025 06:24:30 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5642A193531C; Mon, 1 Dec 2025 11:24:22 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E3D501800451; Mon, 1 Dec 2025 11:24:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588274; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=g+OW/DPD4MLSKrF9wdP7p/as6/OerG5A2lPxhjUVmGM=; b=jOePC6R2nyfHJMRr9mGdknC88ZCKFFEJCryD3BAcHaRXM7yn2ogRzNnQbI4RzXNKB7QdXB vWOiKwli6Lj2MQVc9zsdp1SYdaLDqe2Z+90IaAZO0pxLXMNyW5pHCaY+YzfeWPMxMh0X8M NZtzKt18EQpsEJSJpbaxxLXl5TNSoo8= X-MC-Unique: bx10GkvtMFq_534SB5yHIA-1 X-Mimecast-MFC-AGG-ID: bx10GkvtMFq_534SB5yHIA_1764588269 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 10/24] audio: lookup "audio-" object types, and realize them Date: Mon, 1 Dec 2025 15:22:51 +0400 Message-ID: <20251201112309.4163921-11-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588296342019200 From: Marc-Andr=C3=A9 Lureau Now "audio_driver" is a detail implementation of AudioBEDriver and not required to implement an AudioBE. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qemu/audio.h | 1 + audio/audio.c | 38 +++++++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/include/qemu/audio.h b/include/qemu/audio.h index f83f8326ab..3abf1037f8 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -51,6 +51,7 @@ typedef struct AudioBackend { typedef struct AudioBackendClass { ObjectClass parent_class; =20 + bool (*realize)(AudioBackend *be, Audiodev *dev, Error **errp); const char *(*get_id)(AudioBackend *be); #ifdef CONFIG_GIO bool (*set_dbus_server)(AudioBackend *be, diff --git a/audio/audio.c b/audio/audio.c index 1693563c62..31459f9707 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1563,23 +1563,15 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf,= size_t size) return total; } =20 -static AudioBackend *audio_be_new(Audiodev *dev, Error **errp) +static bool audio_be_driver_realize(AudioBackend *abe, Audiodev *dev, Erro= r **errp) { - const char *drvname =3D AudiodevDriver_str(dev->driver); - struct audio_driver *drv =3D audio_driver_lookup(drvname); - - if (!drv) { - error_setg(errp, "Unknown audio driver `%s'", drvname); - return NULL; - } + AudioDriver *d =3D AUDIO_DRIVER(abe); + audio_driver *drv =3D AUDIO_DRIVER_GET_CLASS(d)->driver; =20 - AudioDriver *d =3D AUDIO_DRIVER(object_new(TYPE_AUDIO_DRIVER)); d->dev =3D dev; - d->drv_opaque =3D drv->init(d->dev, errp); if (!d->drv_opaque) { - object_unref(OBJECT(d)); - return NULL; + return false; } =20 if (!drv->pcm_ops->get_buffer_in) { @@ -1601,7 +1593,26 @@ static AudioBackend *audio_be_new(Audiodev *dev, Err= or **errp) d->period_ticks =3D d->dev->timer_period * (int64_t)SCALE_US; } =20 - return AUDIO_BACKEND(d); + return true; +} + +static AudioBackend *audio_be_new(Audiodev *dev, Error **errp) +{ + const char *drvname =3D AudiodevDriver_str(dev->driver); + g_autofree char *type =3D g_strconcat("audio-", drvname, NULL); + AudioBackend *be =3D AUDIO_BACKEND(object_new(type)); + + if (!be) { + error_setg(errp, "Unknown audio driver `%s'", drvname); + return NULL; + } + + if (!AUDIO_BACKEND_GET_CLASS(be)->realize(be, dev, errp)) { + object_unref(OBJECT(be)); + return NULL; + } + + return be; } =20 static void audio_vm_change_state_handler (void *opaque, bool running, @@ -1645,6 +1656,7 @@ static void audio_driver_class_init(ObjectClass *klas= s, const void *data) { AudioBackendClass *be =3D AUDIO_BACKEND_CLASS(klass); =20 + be->realize =3D audio_be_driver_realize; be->get_id =3D audio_driver_get_id; } =20 --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588307; cv=none; d=zohomail.com; s=zohoarc; b=A556ICxQcynh2oB9S8LFCuu9zyYZqa5RKtYzzsYW8FgL1ea7y7CyqrWIKTH93mWcNmM0y/QaCn8Dk4Zds3U9U3a6qQqi6oxRfIQvO6PF1GSMU7LGA3BasDSTUg92BzSFvp8TQ5JnQB1mphoExX+p0g/kI/ihYWvjj8H5Sv4SwW8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588307; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=gbV3yRehhUnpngzS2Eefm+9zcrjOE+PZ5+HQpxGNrRU=; b=jVhvb2kyOXnn3gUsrBU0JRyBBIU6It3eD2alo4e2MliquTk8sQnZF13u7h9k+F12kYPSBFkKOFV64OKICS5FCu9lGiy43caqKyAC1brAzeUSkgviMnyl+Wy3ZkG2CV92XrNZ4R6PF490clIzeO97aHbvtNOLUZu1hZ4RLRQKgzk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588307174116.39927136548079; Mon, 1 Dec 2025 03:25:07 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ21J-0001Vu-RD; Mon, 01 Dec 2025 06:24:41 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21I-0001PU-Lb for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:40 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21G-0006bo-O0 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:40 -0500 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-270-Cnzrsj14MuS7wDTqffaE7g-1; Mon, 01 Dec 2025 06:24:34 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4298518002D6; Mon, 1 Dec 2025 11:24:29 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3C3643002D0C; Mon, 1 Dec 2025 11:24:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588278; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gbV3yRehhUnpngzS2Eefm+9zcrjOE+PZ5+HQpxGNrRU=; b=cHAHYCOPi0qwVItfxMspsFWPKlP1FLJ7ion+Uop3Lwsk1t7r4hQUJnOVuh6Bd7D+fL4MTB z9jUojxFrLlb6bbOD8Abip8T3KyeVjcAGrMuGEbcGkAY0vtbzwfFzLbfLAPvAWvAwm8E3B 13Dr5eWVKFvOCTL1WljqG8OMzbrIuA8= X-MC-Unique: Cnzrsj14MuS7wDTqffaE7g-1 X-Mimecast-MFC-AGG-ID: Cnzrsj14MuS7wDTqffaE7g_1764588272 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 11/24] audio: switch to module-object, drop audio driver registration Date: Mon, 1 Dec 2025 15:22:52 +0400 Message-ID: <20251201112309.4163921-12-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588309390019200 From: Marc-Andr=C3=A9 Lureau module_object_class_by_name() handles loading the module providing the requested object. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_int.h | 2 -- audio/alsaaudio.c | 1 - audio/audio.c | 43 +++++++++++++------------------------------ audio/dbusaudio.c | 1 - audio/dsoundaudio.c | 1 - audio/jackaudio.c | 1 - audio/noaudio.c | 1 - audio/ossaudio.c | 1 - audio/paaudio.c | 1 - audio/pwaudio.c | 1 - audio/sdlaudio.c | 1 - audio/sndioaudio.c | 1 - audio/spiceaudio.c | 1 - audio/wavaudio.c | 1 - audio/coreaudio.m | 1 - 15 files changed, 13 insertions(+), 45 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index e289ef5f66..eaf7838bfe 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -266,8 +266,6 @@ extern const struct mixeng_volume nominal_volume; =20 extern const char *audio_prio_list[]; =20 -void audio_driver_register(audio_driver *drv); - void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings = *as); void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int= len); =20 diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index c28ee05b93..1056bdd63d 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -984,7 +984,6 @@ static const TypeInfo audio_alsa_info =3D { =20 static void register_audio_alsa(void) { - audio_driver_register(&alsa_audio_driver); type_register_static(&audio_alsa_info); } type_init(register_audio_alsa); diff --git a/audio/audio.c b/audio/audio.c index 31459f9707..8523f14daa 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -67,40 +67,21 @@ const char *audio_prio_list[] =3D { NULL }; =20 -static QLIST_HEAD(, audio_driver) audio_drivers; static AudiodevListHead audiodevs =3D QSIMPLEQ_HEAD_INITIALIZER(audiodevs); static AudiodevListHead default_audiodevs =3D QSIMPLEQ_HEAD_INITIALIZER(default_audiodevs); =20 - -void audio_driver_register(audio_driver *drv) -{ - QLIST_INSERT_HEAD(&audio_drivers, drv, next); -} - -static audio_driver *audio_driver_lookup(const char *name) +static AudioBackendClass *audio_be_class_by_name(const char *name) { - struct audio_driver *d; - Error *local_err =3D NULL; - int rv; + g_autofree char *tname =3D g_strconcat("audio-", name, NULL); + ObjectClass *oc =3D module_object_class_by_name(tname); =20 - QLIST_FOREACH(d, &audio_drivers, next) { - if (strcmp(name, d->name) =3D=3D 0) { - return d; - } - } - rv =3D audio_module_load(name, &local_err); - if (rv > 0) { - QLIST_FOREACH(d, &audio_drivers, next) { - if (strcmp(name, d->name) =3D=3D 0) { - return d; - } - } - } else if (rv < 0) { - error_report_err(local_err); + if (!oc || !object_class_dynamic_cast(oc, TYPE_AUDIO_BACKEND)) { + return NULL; } - return NULL; + + return AUDIO_BACKEND_CLASS(oc); } =20 static AudioBackend *default_audio_be; @@ -1765,7 +1746,7 @@ static const VMStateDescription vmstate_audio =3D { void audio_create_default_audiodevs(void) { for (int i =3D 0; audio_prio_list[i]; i++) { - if (audio_driver_lookup(audio_prio_list[i])) { + if (audio_be_class_by_name(audio_prio_list[i]) !=3D NULL) { QDict *dict =3D qdict_new(); Audiodev *dev =3D NULL; Visitor *v; @@ -2129,9 +2110,11 @@ void audio_help(void) printf("Available audio drivers:\n"); =20 for (i =3D 0; i < AUDIODEV_DRIVER__MAX; i++) { - audio_driver *driver =3D audio_driver_lookup(AudiodevDriver_str(i)= ); - if (driver) { - printf("%s\n", driver->name); + const char *name =3D AudiodevDriver_str(i); + AudioBackendClass *be =3D audio_be_class_by_name(name); + + if (be) { + printf("%s\n", name); } } } diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index edd551a80f..187da7fa65 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -749,7 +749,6 @@ static const TypeInfo audio_dbus_info =3D { =20 static void register_audio_dbus(void) { - audio_driver_register(&dbus_audio_driver); type_register_static(&audio_dbus_info); } type_init(register_audio_dbus); diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 341df9e6d8..9c6ff93022 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -730,7 +730,6 @@ static const TypeInfo audio_dsound_info =3D { =20 static void register_audio_dsound(void) { - audio_driver_register(&dsound_audio_driver); type_register_static(&audio_dsound_info); } type_init(register_audio_dsound); diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 7706fbcb6e..d472f4e5c6 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -728,7 +728,6 @@ static const TypeInfo audio_jack_info =3D { static void register_audio_jack(void) { qemu_mutex_init(&qjack_shutdown_lock); - audio_driver_register(&jack_driver); type_register_static(&audio_jack_info); #if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID) jack_set_thread_creator(qjack_thread_creator); diff --git a/audio/noaudio.c b/audio/noaudio.c index 6f5af23004..b788bc5f8e 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -174,7 +174,6 @@ static const TypeInfo audio_none_info =3D { =20 static void register_audio_none(void) { - audio_driver_register(&no_audio_driver); type_register_static(&audio_none_info); } type_init(register_audio_none); diff --git a/audio/ossaudio.c b/audio/ossaudio.c index f5ce04928a..60aff632a6 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -808,7 +808,6 @@ static const TypeInfo audio_oss_info =3D { =20 static void register_audio_oss(void) { - audio_driver_register(&oss_audio_driver); type_register_static(&audio_oss_info); } type_init(register_audio_oss); diff --git a/audio/paaudio.c b/audio/paaudio.c index abeb2c2d81..02fb29cb2f 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -967,7 +967,6 @@ static const TypeInfo audio_pa_info =3D { =20 static void register_audio_pa(void) { - audio_driver_register(&pa_audio_driver); type_register_static(&audio_pa_info); } type_init(register_audio_pa); diff --git a/audio/pwaudio.c b/audio/pwaudio.c index 5b51a933ae..c42f81b820 100644 --- a/audio/pwaudio.c +++ b/audio/pwaudio.c @@ -884,7 +884,6 @@ static const TypeInfo audio_pw_info =3D { static void register_audio_pw(void) { - audio_driver_register(&pw_audio_driver); type_register_static(&audio_pw_info); } =20 diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 65fab1427e..e52616bec8 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -527,7 +527,6 @@ static const TypeInfo audio_sdl_info =3D { =20 static void register_audio_sdl(void) { - audio_driver_register(&sdl_audio_driver); type_register_static(&audio_sdl_info); } type_init(register_audio_sdl); diff --git a/audio/sndioaudio.c b/audio/sndioaudio.c index 1a4912fb60..c1468ef2b9 100644 --- a/audio/sndioaudio.c +++ b/audio/sndioaudio.c @@ -591,7 +591,6 @@ static const TypeInfo audio_sndio_info =3D { =20 static void register_audio_sndio(void) { - audio_driver_register(&sndio_audio_driver); type_register_static(&audio_sndio_info); } =20 diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index d8451d5877..1165f88400 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -361,7 +361,6 @@ static const TypeInfo audio_spice_info =3D { =20 static void register_audio_spice(void) { - audio_driver_register(&spice_audio_driver); type_register_static(&audio_spice_info); } type_init(register_audio_spice); diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 3c1f352f11..dbf0e8e00c 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -250,7 +250,6 @@ static const TypeInfo audio_wav_info =3D { =20 static void register_audio_wav(void) { - audio_driver_register(&wav_audio_driver); type_register_static(&audio_wav_info); } type_init(register_audio_wav); diff --git a/audio/coreaudio.m b/audio/coreaudio.m index d1a837f4bc..9e4266ee97 100644 --- a/audio/coreaudio.m +++ b/audio/coreaudio.m @@ -709,7 +709,6 @@ static void coreaudio_audio_fini (void *opaque) =20 static void register_audio_coreaudio(void) { - audio_driver_register(&coreaudio_audio_driver); type_register_static(&audio_coreaudio_info); } type_init(register_audio_coreaudio); --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588340; cv=none; d=zohomail.com; s=zohoarc; b=A5q9jqx4DSsbj0WYWqkSl12a0oZa2cTTbFc0T5BgmxkmxStXKEh+t9Szs4TUrPK+dlvfQb92OHxf2qV6FxIku0y2rVtc0ktrVyaBWq+IUwkz1qbccT0RVRHzcXAGxin5Z7wYDAQLHAK2xtIsJtTrr25b4mB4NOQiE2zQFImwwM4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588340; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=WIKo7w2GHW/q7SLrcO5Qg01VSqMPQaJgBVlfEQ4RmBw=; b=PPyV+PWLPD9I0MpotjZLktXw4+efFmjt6Nb8/MLjKYlZIjF2ZzTPp3kbytb7K/bUMVdGTLuY0v9KMI89OZ+YxbtBXYn/xgnRqBmCKEolNwJfcTyRiqe+1Nra/AjamVnpkErnk/cy9eA59AYFWkSTug4DZ0H65pjs+FSdvifrUcY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588340720301.8935207108425; Mon, 1 Dec 2025 03:25:40 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ21N-0001o7-8I; Mon, 01 Dec 2025 06:24:45 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21L-0001cE-8A for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:43 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21J-0006cJ-Os for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:42 -0500 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-292-bsKchikzO8-3YHuEF1qI6A-1; Mon, 01 Dec 2025 06:24:37 -0500 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 364201955E7F; Mon, 1 Dec 2025 11:24:36 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id F281E195608E; Mon, 1 Dec 2025 11:24:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588281; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WIKo7w2GHW/q7SLrcO5Qg01VSqMPQaJgBVlfEQ4RmBw=; b=U0I7ij/QKMiEwM1Hcb2BgQe+lnXAZZtnLD/rGj3HoTWAaZZbjqIpmoFqLZL7PLfor7exJG bgEw+/4t34UKx7X22EwPDwNDKaFn9VzQtaVMhgkNTUOVwsmEd3pFPTYKOAobXMdgvjG3CT 5VtBbcOZariqTUHWpoZ08ITNUtovKWY= X-MC-Unique: bsKchikzO8-3YHuEF1qI6A-1 X-Mimecast-MFC-AGG-ID: bsKchikzO8-3YHuEF1qI6A_1764588276 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 12/24] module: remove audio module support Date: Mon, 1 Dec 2025 15:22:53 +0400 Message-ID: <20251201112309.4163921-13-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588342111019200 From: Marc-Andr=C3=A9 Lureau It relies on dynamic object loading support instead. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qemu/module.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/qemu/module.h b/include/qemu/module.h index c37ce74b16..9885ac9afb 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -63,7 +63,6 @@ typedef enum { #define migration_init(function) module_init(function, MODULE_INIT_MIGRATI= ON) #define block_module_load(lib, errp) module_load("block-", lib, errp) #define ui_module_load(lib, errp) module_load("ui-", lib, errp) -#define audio_module_load(lib, errp) module_load("audio-", lib, errp) =20 void register_module_init(void (*fn)(void), module_init_type type); void register_dso_module_init(void (*fn)(void), module_init_type type); @@ -78,7 +77,7 @@ void module_call_init(module_init_type type); * - get_relocated_path(CONFIG_QEMU_MODDIR); * - /var/run/qemu/${version_dir} * - * prefix: a subsystem prefix, or the empty string ("audio-", ...,= "") + * prefix: a subsystem prefix, or the empty string ("ui-", ..., "") * name: name of the module * errp: error to set in case the module is found, but load fail= ed. * --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588318; cv=none; d=zohomail.com; s=zohoarc; b=Gq+7X0hI8/e9ne+RBQ2F76mWKWOh4j2ZQlIvb0XjTCOc9Pfeat6B5Wpi9SLo0Khv4JuisA63hn79iNMJA5fH8k213ltaW5Wpz1KbJl2cIqwFzRgC1H75K4NsBvIoymiAdq8/fgILpSM0KdMbRaRENuSMplBRJgOcF6LssYe5zCk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588318; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=3g8JxiwbPFLnYrOLWm3YCZxCI3y+1VP+hhdBbtdOIKM=; b=LtaCj3pYyLmqiOGKm13AgnyuwxOwe/adgIkLbXCfOV7neITcQYqKcK2fNF3m2zVeaFyzxG+Qz43pUhJ7zjghnJU9FzZr5GW0rYRk8Z3zTN+KN8H9AlX4/KHUHT0j1b+tfyJejqqvCxFOvLGMZakA3VzwBUnxc4yBxolmMIR3XX0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588318412797.275667561076; Mon, 1 Dec 2025 03:25:18 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ21U-0002sq-CT; Mon, 01 Dec 2025 06:24:52 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21S-0002cT-9B for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:50 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21Q-0006dV-Ps for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:50 -0500 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-414-rXlObdUbPI63wvzysurcWQ-1; Mon, 01 Dec 2025 06:24:43 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 48DC2180034A; Mon, 1 Dec 2025 11:24:42 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C3206180087D; Mon, 1 Dec 2025 11:24:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588288; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3g8JxiwbPFLnYrOLWm3YCZxCI3y+1VP+hhdBbtdOIKM=; b=XlP+4/Rd5ooKSJuVAIKh7zSKP7DuvzZFmnYtw1v5OonJKmdzCPvv6MKftIhGXPw/iPLAB4 qCGptEIVcCwI05gN7uAyyft8sou7Qd02mOcr3KZvUoIztcIptncefSGWMx9G9U3v37qatc W0a7M9Qs8hTZQxjXllP2zZdltWkm0bQ= X-MC-Unique: rXlObdUbPI63wvzysurcWQ-1 X-Mimecast-MFC-AGG-ID: rXlObdUbPI63wvzysurcWQ_1764588282 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 13/24] audio: keep a strong reference on the backend Date: Mon, 1 Dec 2025 15:22:54 +0400 Message-ID: <20251201112309.4163921-14-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588321402019200 From: Marc-Andr=C3=A9 Lureau Since we are going to convert audio_driver-based backends, we need to properly handle reference counting to allow for a different order of class finalization (for example, pulse class before base driver class). Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_template.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/audio/audio_template.h b/audio/audio_template.h index 925a878f6d..7d204d25bc 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -231,6 +231,7 @@ static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp) glue(hw->pcm_ops->fini_, TYPE) (hw); glue(s->nb_hw_voices_, TYPE) +=3D 1; glue(audio_pcm_hw_free_resources_ , TYPE) (hw); + object_unref(hw->s); g_free(hw); *hwp =3D NULL; } @@ -287,7 +288,7 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioDrive= r *s, * is guaranteed to be !=3D 0. See the audio_init_nb_voices_* function= s. */ hw =3D g_malloc0(glue(drv->voice_size_, TYPE)); - hw->s =3D s; + hw->s =3D AUDIO_DRIVER(object_ref(s)); hw->pcm_ops =3D drv->pcm_ops; =20 QLIST_INIT (&hw->sw_head); @@ -335,6 +336,7 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioDrive= r *s, err1: glue (hw->pcm_ops->fini_, TYPE) (hw); err0: + object_unref(hw->s); g_free (hw); return NULL; } @@ -441,7 +443,7 @@ static SW *glue(audio_pcm_create_voice_pair_, TYPE)( } =20 sw =3D g_new0(SW, 1); - sw->s =3D s; + sw->s =3D AUDIO_DRIVER(object_ref(s)); =20 hw =3D glue(audio_pcm_hw_add_, TYPE)(s, &hw_as); if (!hw) { @@ -461,6 +463,7 @@ err2: glue (audio_pcm_hw_del_sw_, TYPE) (sw); glue (audio_pcm_hw_gc_, TYPE) (&hw); err1: + object_unref(sw->s); g_free(sw); return NULL; } @@ -470,6 +473,8 @@ static void glue (audio_close_, TYPE) (SW *sw) glue (audio_pcm_sw_fini_, TYPE) (sw); glue (audio_pcm_hw_del_sw_, TYPE) (sw); glue (audio_pcm_hw_gc_, TYPE) (&sw->hw); + + object_unref(sw->s); g_free (sw); } =20 --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588322; cv=none; d=zohomail.com; s=zohoarc; b=Y5NkjQGwuPhlvke9K+u8ZqO2sFVqdKF8jAjNwZzi7Rcbg28LloLDWwQ+K7+yd5GgFebGeJlMf0aPzERcKHgRrnV5EfTvc4/2GPcG7o+96KRBFMytOziZROFxREM66h7sMqRLXyq6jxkAAfv4ZVTf8AU6fA4slBW8351tNvkKses= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588322; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=OqqV1rAyj9tFNJdjrOVW2/JSZTxqKWI42PQNdQQe5eI=; b=n13dRy8HYe/8+Mjqq5TMzzreqMV8EHzyOfhjdcEFAC1dMqvUhxG1MooxvSNmEjCl06RjwgNbCxEXyMkvpRSJ0Ou7MRkJhKfq+n0Gw83oDV2S8nB2oe1R8Ns+Z+o0JG6s28llfoHtrjIxjMSlgj+JWdp5x/WLSko/5emJ47OS4Ig= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 176458832220035.83153646983703; Mon, 1 Dec 2025 03:25:22 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ21a-00034F-Nq; Mon, 01 Dec 2025 06:25:00 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21X-00031f-Cy for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:55 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21V-0006dz-U8 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:24:55 -0500 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-544-bTz3ri5gPo-1cjdBBNi0ww-1; Mon, 01 Dec 2025 06:24:50 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8789F1955DA0; Mon, 1 Dec 2025 11:24:48 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E6B6819560A7; Mon, 1 Dec 2025 11:24:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588293; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OqqV1rAyj9tFNJdjrOVW2/JSZTxqKWI42PQNdQQe5eI=; b=FpvD4+/TnvNWDcz1xWJ72DCGzECw9lvz69PyBvpBrmbvp0ExGAj2SQBVsXE64tyJJAfkTb kfCyPYOX/Pz8OIQkasRus8ljykr+k7Ca31WPkNVq7m2bD/nahUsXvL5jzqou3gtmxyiNpc 6OP5EnGjUzXF3mQQaG+zhzKcvcL1Avs= X-MC-Unique: bTz3ri5gPo-1cjdBBNi0ww-1 X-Mimecast-MFC-AGG-ID: bTz3ri5gPo-1cjdBBNi0ww_1764588289 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 14/24] audio: make list type declaration private Date: Mon, 1 Dec 2025 15:22:55 +0400 Message-ID: <20251201112309.4163921-15-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588323243019200 From: Marc-Andr=C3=A9 Lureau No need to share in a common header. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_int.h | 7 ------- audio/audio.c | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index eaf7838bfe..3bf1cf6a99 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -313,13 +313,6 @@ static inline size_t audio_ring_posb(size_t pos, size_= t dist, size_t len) #define ldebug(fmt, ...) (void)0 #endif =20 -typedef struct AudiodevListEntry { - Audiodev *dev; - QSIMPLEQ_ENTRY(AudiodevListEntry) next; -} AudiodevListEntry; - -typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead; - void audio_create_pdos(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev); diff --git a/audio/audio.c b/audio/audio.c index 8523f14daa..138d7b502a 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -67,6 +67,13 @@ const char *audio_prio_list[] =3D { NULL }; =20 +typedef struct AudiodevListEntry { + Audiodev *dev; + QSIMPLEQ_ENTRY(AudiodevListEntry) next; +} AudiodevListEntry; + +typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead; + static AudiodevListHead audiodevs =3D QSIMPLEQ_HEAD_INITIALIZER(audiodevs); static AudiodevListHead default_audiodevs =3D --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588349; cv=none; d=zohomail.com; s=zohoarc; b=OiduAlTBMrTL5O74VcJa6+knso1s447ygmAdDUi+YHJaFuQVJK5NOgNwUsdo7MPnyVVsSjEQzKEub8knIcHXHKueu3Bv51tewYIaZvhVQ/rcEv4VEt0kmfIcYDSo83up3n/vpybZ3cgNMuxL4MWdab3xFGHxusWVxUZlBUpCUHo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588349; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=fgXIFNbzNbMEISNKwvTVpu1p++Wmxf2WWlB2/7fqY9M=; b=m7aMSoUEfSq9iFQ9evNSyWOC1rN7S9h9wA8h+su77C7DuGxT61mexxtAbfhz14jvchm+8CHQF00fH2wbewQBLf9qyy6cszl3iVgc1w6458hm0FczSMu3m9rfOvOGKyEa7VS6nlsiBlQI5jTFw/6PPTnOf8ui7qB5Xfz1tcUOczI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588349249292.8934434661975; Mon, 1 Dec 2025 03:25:49 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ21l-0003Ih-Pv; Mon, 01 Dec 2025 06:25:11 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21g-0003DE-1Y for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:04 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21b-0006ed-Tc for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:01 -0500 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-549-8tLoAzrVPzuaH25-8RooCw-1; Mon, 01 Dec 2025 06:24:55 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 48EC6180048E; Mon, 1 Dec 2025 11:24:54 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BF5C130001A4; Mon, 1 Dec 2025 11:24:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588299; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fgXIFNbzNbMEISNKwvTVpu1p++Wmxf2WWlB2/7fqY9M=; b=DxQ7sil9uzEtaI+cIUON3K8tfs81VmHhmUBJyv/Gh3SlORQDBDErSlZQEgP3dJXgVeJqeX cqNokwzI7lLMjbeKp+INDVQvbkVNt1m+FgkCEVWb2keSaWJxZAZVxf14bKy4AqvmtjsEVz 9ELoRE8wz5Rp0ZOecaRfrbpbBtFNC7w= X-MC-Unique: 8tLoAzrVPzuaH25-8RooCw-1 X-Mimecast-MFC-AGG-ID: 8tLoAzrVPzuaH25-8RooCw_1764588294 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 15/24] audio: make create_pdos() private Date: Mon, 1 Dec 2025 15:22:56 +0400 Message-ID: <20251201112309.4163921-16-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588349709019200 From: Marc-Andr=C3=A9 Lureau Clean up. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_int.h | 1 - audio/audio.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index 3bf1cf6a99..d2d54b924e 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -313,7 +313,6 @@ static inline size_t audio_ring_posb(size_t pos, size_t= dist, size_t len) #define ldebug(fmt, ...) (void)0 #endif =20 -void audio_create_pdos(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev); =20 diff --git a/audio/audio.c b/audio/audio.c index 138d7b502a..7e5fb4ff8a 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1990,7 +1990,7 @@ void AUD_set_volume_in(SWVoiceIn *sw, Volume *vol) } } =20 -void audio_create_pdos(Audiodev *dev) +static void audio_create_pdos(Audiodev *dev) { switch (dev->driver) { #define CASE(DRIVER, driver, pdo_name) \ --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588348; cv=none; d=zohomail.com; s=zohoarc; b=BTtnWvJJklyQymqrlES4tG/4G5SGor/AcS5j7XcKD3LVU9cP4e41GRxueaY9Rjm0zPOMRHMOnMKP10T+MwqnbwcapgYJncQQ8WE8QmFcRZOc3xkcJfguvvJtK2te6mwrwUqbCI+bP13rBVH6gnd9EEMXKQsDRVSclWGkMFWiPWY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588348; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=SjlS5jM2VJyjoucUnciKUWXKQgrLk2dMyYE8uQ43Koc=; b=dFWd+N7SYvQUaGnq/F9e9WefNFngHL3UFMf+uPJ8bdYCuo7VJ3KEK9RnM8Pqtksxifu8kx5dbeVXlfeJ9hyTbHOgsW03Gg676M0ONGXM+8LMQ6QUd6DBvJjpWKA/agJFI498O5hpFyeaWtvjcZDDq+fxOeVMjvrE23mWy5TSuc8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588348127488.44702328693006; Mon, 1 Dec 2025 03:25:48 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22F-0004Yv-By; Mon, 01 Dec 2025 06:25:39 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ229-0004DI-Bv for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:35 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21l-0006sT-J8 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:12 -0500 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-528--mAunWC7MrqrahD7a1k-Yg-1; Mon, 01 Dec 2025 06:25:01 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1D89C1955DC0; Mon, 1 Dec 2025 11:25:00 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A64861800451; Mon, 1 Dec 2025 11:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588304; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SjlS5jM2VJyjoucUnciKUWXKQgrLk2dMyYE8uQ43Koc=; b=J1+tuWCUug+gRuzD+JFT956adwVS/l6tez51pnOkLe885N/yla/gtbbySv/opx11a+LJuF mJiN4L6w/vK/TPQdwlVF0UGCscHgBYsieEDqrDQzjjGaKUE+kLEhZP9hSKOWOHJ4r5sj9I ZED6zQQ6jK96ABXv9V5Ch2jd2moYVBc= X-MC-Unique: -mAunWC7MrqrahD7a1k-Yg-1 X-Mimecast-MFC-AGG-ID: -mAunWC7MrqrahD7a1k-Yg_1764588300 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [RFC 16/24] replay: remove dependency on audio/ Date: Mon, 1 Dec 2025 15:22:57 +0400 Message-ID: <20251201112309.4163921-17-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588349936019200 From: Marc-Andr=C3=A9 Lureau The replay infrastructure shouldn't depend on internals of audio/. (st_sample is an internal implementation detail and could be different) Let audio drive the audio samples recording/replaying. Notice also we don't need to save & restore the internal ring "wpos", all replay should care about is the number of samples and the samples. Bump the replay version. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_int.h | 5 ++++ include/qemu/audio.h | 5 ---- include/system/replay.h | 8 +++++-- replay/replay-internal.h | 2 ++ audio/audio.c | 23 ++++++++++++++++-- replay/replay-audio.c | 51 +++++++++++++++++++++++----------------- replay/replay.c | 2 +- replay/stubs-system.c | 8 ++++++- 8 files changed, 72 insertions(+), 32 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index d2d54b924e..79e54fd60a 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -316,6 +316,11 @@ static inline size_t audio_ring_posb(size_t pos, size_= t dist, size_t len) AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev); =20 +void audio_sample_to_uint64(const st_sample *sample, int pos, + uint64_t *left, uint64_t *right); +void audio_sample_from_uint64(st_sample *sample, int pos, + uint64_t left, uint64_t right); + #define TYPE_AUDIO_DRIVER "audio-driver" OBJECT_DECLARE_TYPE(AudioDriver, AudioDriverClass, AUDIO_DRIVER) =20 diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 3abf1037f8..07a2e23998 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -124,11 +124,6 @@ void audio_cleanup(void); =20 typedef struct st_sample st_sample; =20 -void audio_sample_to_uint64(const st_sample *sample, int pos, - uint64_t *left, uint64_t *right); -void audio_sample_from_uint64(st_sample *sample, int pos, - uint64_t left, uint64_t right); - void audio_add_audiodev(Audiodev *audio); void audio_add_default_audiodev(Audiodev *dev, Error **errp); void audio_parse_option(const char *opt); diff --git a/include/system/replay.h b/include/system/replay.h index 68f91bdfbf..0ee5230586 100644 --- a/include/system/replay.h +++ b/include/system/replay.h @@ -165,8 +165,12 @@ void replay_net_packet_event(ReplayNetState *rns, unsi= gned flags, =20 /*! Saves/restores number of played samples of audio out operation. */ void replay_audio_out(size_t *played); -/*! Saves/restores recorded samples of audio in operation. */ -void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, s= ize_t size); +/*! Start saves/restores recorded samples of audio in operation, must be c= alled before replay_audio_in_sample_lr(). */ +void replay_audio_in_start(size_t *recorded); +/*! Saves/restores recorded samples. */ +void replay_audio_in_sample_lr(uint64_t *left, uint64_t *right); +/*! Finish saves/restores recorded samples. */ +void replay_audio_in_finish(void); =20 /* VM state operations */ =20 diff --git a/replay/replay-internal.h b/replay/replay-internal.h index 75249b7693..643b357da1 100644 --- a/replay/replay-internal.h +++ b/replay/replay-internal.h @@ -85,6 +85,7 @@ enum ReplayEvents { * @file_offset: offset into replay log at replay snapshot * @block_request_id: current serialised block request id * @read_event_id: current async read event id + * @n_audio_samples: expected audio samples */ typedef struct ReplayState { int64_t cached_clock[REPLAY_CLOCK_COUNT]; @@ -96,6 +97,7 @@ typedef struct ReplayState { uint64_t file_offset; uint64_t block_request_id; uint64_t read_event_id; + size_t n_audio_samples; } ReplayState; extern ReplayState replay_state; =20 diff --git a/audio/audio.c b/audio/audio.c index 7e5fb4ff8a..f0e31ce4a0 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1301,13 +1301,32 @@ static void audio_run_in(AudioDriver *s) while ((hw =3D audio_pcm_hw_find_any_enabled_in(s, hw))) { SWVoiceIn *sw; size_t captured =3D 0, min; + int pos; =20 if (replay_mode !=3D REPLAY_MODE_PLAY) { captured =3D audio_pcm_hw_run_in( hw, hw->conv_buf.size - audio_pcm_hw_get_live_in(hw)); } - replay_audio_in(&captured, hw->conv_buf.buffer, &hw->conv_buf.pos, - hw->conv_buf.size); + + replay_audio_in_start(&captured); + assert(captured <=3D hw->conv_buf.size); + if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + hw->conv_buf.pos =3D (hw->conv_buf.pos + captured) % hw->conv_= buf.size; + } + for (pos =3D (hw->conv_buf.pos - captured + hw->conv_buf.size) % h= w->conv_buf.size; + pos !=3D hw->conv_buf.pos; + pos =3D (pos + 1) % hw->conv_buf.size) { + uint64_t left, right; + + if (replay_mode =3D=3D REPLAY_MODE_RECORD) { + audio_sample_to_uint64(hw->conv_buf.buffer, pos, &left= , &right); + } + replay_audio_in_sample_lr(&left, &right); + if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + audio_sample_from_uint64(hw->conv_buf.buffer, pos, lef= t, right); + } + } + replay_audio_in_finish(); =20 min =3D audio_pcm_hw_find_min_in (hw); hw->total_samples_captured +=3D captured - min; diff --git a/replay/replay-audio.c b/replay/replay-audio.c index 1b614f4137..7d20ae9110 100644 --- a/replay/replay-audio.c +++ b/replay/replay-audio.c @@ -13,7 +13,6 @@ #include "qemu/error-report.h" #include "system/replay.h" #include "replay-internal.h" -#include "qemu/audio.h" =20 void replay_audio_out(size_t *played) { @@ -35,38 +34,48 @@ void replay_audio_out(size_t *played) } } =20 -void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, s= ize_t size) +void replay_audio_in_start(size_t *nsamples) { - int pos; - uint64_t left, right; if (replay_mode =3D=3D REPLAY_MODE_RECORD) { g_assert(replay_mutex_locked()); replay_save_instructions(); replay_put_event(EVENT_AUDIO_IN); - replay_put_qword(*recorded); - replay_put_qword(*wpos); - for (pos =3D (*wpos - *recorded + size) % size ; pos !=3D *wpos - ; pos =3D (pos + 1) % size) { - audio_sample_to_uint64(samples, pos, &left, &right); - replay_put_qword(left); - replay_put_qword(right); - } + replay_put_qword(*nsamples); + replay_state.n_audio_samples =3D *nsamples; } else if (replay_mode =3D=3D REPLAY_MODE_PLAY) { g_assert(replay_mutex_locked()); replay_account_executed_instructions(); if (replay_next_event_is(EVENT_AUDIO_IN)) { - *recorded =3D replay_get_qword(); - *wpos =3D replay_get_qword(); - for (pos =3D (*wpos - *recorded + size) % size ; pos !=3D *wpos - ; pos =3D (pos + 1) % size) { - left =3D replay_get_qword(); - right =3D replay_get_qword(); - audio_sample_from_uint64(samples, pos, left, right); - } - replay_finish_event(); + *nsamples =3D replay_get_qword(); + replay_state.n_audio_samples =3D *nsamples; } else { error_report("Missing audio in event in the replay log"); abort(); } } } + +void replay_audio_in_sample_lr(uint64_t *left, uint64_t *right) +{ + if (replay_mode =3D=3D REPLAY_MODE_RECORD) { + replay_put_qword(*left); + replay_put_qword(*right); + } else if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + *left =3D replay_get_qword(); + *right =3D replay_get_qword(); + } else { + return; + } + + assert(replay_state.n_audio_samples > 0); + replay_state.n_audio_samples--; +} + +void replay_audio_in_finish(void) +{ + assert(replay_state.n_audio_samples =3D=3D 0); + + if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + replay_finish_event(); + } +} diff --git a/replay/replay.c b/replay/replay.c index b2121788c1..2e5c6fa82e 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -22,7 +22,7 @@ =20 /* Current version of the replay mechanism. Increase it when file format changes. */ -#define REPLAY_VERSION 0xe0200c +#define REPLAY_VERSION 0xe0200d /* Size of replay log header */ #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) =20 diff --git a/replay/stubs-system.c b/replay/stubs-system.c index 7f85764936..b2c52bc404 100644 --- a/replay/stubs-system.c +++ b/replay/stubs-system.c @@ -15,7 +15,13 @@ void replay_input_sync_event(void) void replay_add_blocker(const char *feature) { } -void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, s= ize_t size) +void replay_audio_in_start(size_t *nsamples) +{ +} +void replay_audio_in_sample_lr(uint64_t *left, uint64_t *right) +{ +} +void replay_audio_in_finish(void) { } void replay_audio_out(size_t *played) --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588357; cv=none; d=zohomail.com; s=zohoarc; b=W4KOzNuZbH0AwyoEfCq3gmY8F4RNPSAzoLxG/jPA/RJHwk1VeCxZfDPKcIc5aVMR/EtTZJM4BOftcn9DgOoVbGwmjPtvNLVqf7w+a3dFjKStu0tq7eLYjVSkbQze4xmTAe79UB7pwm9Wc56+VSePA6wgkj0tw5akRp1cCoYnVco= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588357; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=MnZ8xf1jNhx3OIPoccDARGdVwIWeeUhhnCgaTBsALM4=; b=KJxXAhmn66o4UTkDD1nwrAxRB2mprcBqwemrxwk8n0rXhsCIiTofmoR9XJ17E8SgtVwbypPS8pVKCuJS6ppVkaOUkwCb07D6dSwGtRwgvIKLqw+pX83K4yQ85xlKnERjHPIhPByUTzkjGa3AV5GpoxBuwTvKK86WdrLfwWlFqYU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 176458835775052.68048539401957; Mon, 1 Dec 2025 03:25:57 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22M-0004sU-Bn; Mon, 01 Dec 2025 06:25:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ229-0004DL-CP for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:35 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ21r-0006yV-8H for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:19 -0500 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-669-vEZKrdhcPA6RphpM6xpnsA-1; Mon, 01 Dec 2025 06:25:10 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A2A6F195608F; Mon, 1 Dec 2025 11:25:07 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 29DDA180035F; Mon, 1 Dec 2025 11:25:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588314; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MnZ8xf1jNhx3OIPoccDARGdVwIWeeUhhnCgaTBsALM4=; b=S6b2xynSLq0ZLB+smgFUdljcV3BibWjTwKKHARMYb4mCTH9kpKhQKtWPG7HHvimlPWQQ5w XS0XvWU4DMdrQLrFtUBHJcUjiLlkud8Ss6iNyeD+kuOx2opT/dqcmYQdU+GvZR8gCwpzUH hzocqaCvVtKMepM8amFj0rqSfbtais8= X-MC-Unique: vEZKrdhcPA6RphpM6xpnsA-1 X-Mimecast-MFC-AGG-ID: vEZKrdhcPA6RphpM6xpnsA_1764588308 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier , Manos Pitsidianakis , "Michael S. Tsirkin" , Alistair Francis , "Edgar E. Iglesias" , Peter Maydell , qemu-arm@nongnu.org (open list:Xilinx ZynqMP and...) Subject: [RFC 17/24] audio: make all the backend-specific APIs take the be Date: Mon, 1 Dec 2025 15:22:58 +0400 Message-ID: <20251201112309.4163921-18-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588359607019200 From: Marc-Andr=C3=A9 Lureau This will allow to dispatch to different implementations next. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_template.h | 2 +- include/qemu/audio-capture.h | 9 ++++++--- include/qemu/audio.h | 30 +++++++++++++++--------------- audio/audio.c | 18 +++++++++--------- audio/wavcapture.c | 7 +++++-- hw/audio/ac97.c | 24 ++++++++++++------------ hw/audio/adlib.c | 9 +++++---- hw/audio/asc.c | 16 ++++++++-------- hw/audio/cs4231a.c | 16 ++++++++-------- hw/audio/es1370.c | 12 ++++++------ hw/audio/gus.c | 9 +++++---- hw/audio/hda-codec.c | 16 ++++++++-------- hw/audio/lm4549.c | 12 ++++++------ hw/audio/pcspk.c | 4 ++-- hw/audio/sb16.c | 14 +++++++------- hw/audio/via-ac97.c | 14 +++++++------- hw/audio/virtio-snd.c | 14 ++++++++------ hw/audio/wm8750.c | 24 ++++++++++++------------ hw/display/xlnx_dp.c | 10 +++++----- hw/usb/dev-audio.c | 12 ++++++------ ui/vnc.c | 2 +- 21 files changed, 142 insertions(+), 132 deletions(-) diff --git a/audio/audio_template.h b/audio/audio_template.h index 7d204d25bc..8d66f9cd40 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -569,7 +569,7 @@ SW *glue (AUD_open_, TYPE) ( return NULL; } =20 -bool glue(AUD_is_active_, TYPE)(SW *sw) +bool glue(AUD_is_active_, TYPE)(AudioBackend *be, SW *sw) { return sw ? sw->active : 0; } diff --git a/include/qemu/audio-capture.h b/include/qemu/audio-capture.h index a07412db85..f500b0a7f8 100644 --- a/include/qemu/audio-capture.h +++ b/include/qemu/audio-capture.h @@ -36,8 +36,11 @@ CaptureVoiceOut *AUD_add_capture( AudioBackend *be, struct audsettings *as, struct audio_capture_ops *ops, - void *opaque - ); -void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque); + void *opaque); + +void AUD_del_capture( + AudioBackend *be, + CaptureVoiceOut *cap, + void *cb_opaque); =20 #endif /* QEMU_AUDIO_CAPTURE_H */ diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 07a2e23998..745ee881b8 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -67,7 +67,7 @@ typedef struct QEMUAudioTimeStamp { =20 bool AUD_backend_check(AudioBackend **be, Error **errp); =20 -SWVoiceOut *AUD_open_out ( +SWVoiceOut *AUD_open_out( AudioBackend *be, SWVoiceOut *sw, const char *name, @@ -76,11 +76,11 @@ SWVoiceOut *AUD_open_out ( struct audsettings *settings ); =20 -void AUD_close_out (AudioBackend *be, SWVoiceOut *sw); -size_t AUD_write (SWVoiceOut *sw, void *pcm_buf, size_t size); -int AUD_get_buffer_size_out (SWVoiceOut *sw); -void AUD_set_active_out(SWVoiceOut *sw, bool on); -bool AUD_is_active_out(SWVoiceOut *sw); +void AUD_close_out(AudioBackend *be, SWVoiceOut *sw); +size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *pcm_buf, size_t s= ize); +int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw); +void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on); +bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw); =20 #define AUDIO_MAX_CHANNELS 16 typedef struct Volume { @@ -89,19 +89,19 @@ typedef struct Volume { uint8_t vol[AUDIO_MAX_CHANNELS]; } Volume; =20 -void AUD_set_volume_out(SWVoiceOut *sw, Volume *vol); -void AUD_set_volume_in(SWVoiceIn *sw, Volume *vol); +void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol); +void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol); =20 static inline void -AUD_set_volume_out_lr(SWVoiceOut *sw, bool mut, uint8_t lvol, uint8_t rvol= ) { - AUD_set_volume_out(sw, &(Volume) { +AUD_set_volume_out_lr(AudioBackend *be, SWVoiceOut *sw, bool mut, uint8_t = lvol, uint8_t rvol) { + AUD_set_volume_out(be, sw, &(Volume) { .mute =3D mut, .channels =3D 2, .vol =3D { lvol, rvol } }); } =20 static inline void -AUD_set_volume_in_lr(SWVoiceIn *sw, bool mut, uint8_t lvol, uint8_t rvol) { - AUD_set_volume_in(sw, &(Volume) { +AUD_set_volume_in_lr(AudioBackend *be, SWVoiceIn *sw, bool mut, uint8_t lv= ol, uint8_t rvol) { + AUD_set_volume_in(be, sw, &(Volume) { .mute =3D mut, .channels =3D 2, .vol =3D { lvol, rvol } }); } @@ -116,9 +116,9 @@ SWVoiceIn *AUD_open_in( ); =20 void AUD_close_in(AudioBackend *be, SWVoiceIn *sw); -size_t AUD_read (SWVoiceIn *sw, void *pcm_buf, size_t size); -void AUD_set_active_in(SWVoiceIn *sw, bool on); -bool AUD_is_active_in(SWVoiceIn *sw); +size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *pcm_buf, size_t siz= e); +void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on); +bool AUD_is_active_in(AudioBackend *be, SWVoiceIn *sw); =20 void audio_cleanup(void); =20 diff --git a/audio/audio.c b/audio/audio.c index f0e31ce4a0..cc65153dfa 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -846,7 +846,7 @@ static void audio_timer (void *opaque) /* * Public API */ -size_t AUD_write(SWVoiceOut *sw, void *buf, size_t size) +size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size) { HWVoiceOut *hw; =20 @@ -868,7 +868,7 @@ size_t AUD_write(SWVoiceOut *sw, void *buf, size_t size) } } =20 -size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size) +size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size) { HWVoiceIn *hw; =20 @@ -890,7 +890,7 @@ size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size) } } =20 -int AUD_get_buffer_size_out(SWVoiceOut *sw) +int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw) { if (!sw) { return 0; @@ -903,7 +903,7 @@ int AUD_get_buffer_size_out(SWVoiceOut *sw) return sw->hw->samples * sw->hw->info.bytes_per_frame; } =20 -void AUD_set_active_out(SWVoiceOut *sw, bool on) +void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on) { HWVoiceOut *hw; =20 @@ -951,7 +951,7 @@ void AUD_set_active_out(SWVoiceOut *sw, bool on) } } =20 -void AUD_set_active_in(SWVoiceIn *sw, bool on) +void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on) { HWVoiceIn *hw; =20 @@ -996,7 +996,7 @@ void AUD_set_active_in(SWVoiceIn *sw, bool on) } } =20 -static size_t audio_get_avail (SWVoiceIn *sw) +static size_t audio_get_avail(SWVoiceIn *sw) { size_t live; =20 @@ -1938,7 +1938,7 @@ CaptureVoiceOut *AUD_add_capture( return cap; } =20 -void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque) +void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaq= ue) { struct capture_callback *cb; =20 @@ -1977,7 +1977,7 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_= opaque) } } =20 -void AUD_set_volume_out(SWVoiceOut *sw, Volume *vol) +void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol) { if (sw) { HWVoiceOut *hw =3D sw->hw; @@ -1993,7 +1993,7 @@ void AUD_set_volume_out(SWVoiceOut *sw, Volume *vol) } } =20 -void AUD_set_volume_in(SWVoiceIn *sw, Volume *vol) +void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol) { if (sw) { HWVoiceIn *hw =3D sw->hw; diff --git a/audio/wavcapture.c b/audio/wavcapture.c index b33a38ff45..2950ceaf24 100644 --- a/audio/wavcapture.c +++ b/audio/wavcapture.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "qemu/audio.h" #include "qemu/qemu-print.h" #include "qemu/error-report.h" #include "audio_int.h" @@ -10,6 +11,7 @@ typedef struct { int freq; int bits; int nchannels; + AudioBackend *audio_be; CaptureVoiceOut *cap; } WAVState; =20 @@ -84,7 +86,7 @@ static void wav_capture_destroy (void *opaque) { WAVState *wav =3D opaque; =20 - AUD_del_capture (wav->cap, wav); + AUD_del_capture(wav->audio_be, wav->cap, wav); g_free (wav); } =20 @@ -159,6 +161,7 @@ int wav_start_capture(AudioBackend *state, CaptureState= *s, const char *path, return -1; } =20 + wav->audio_be =3D state; wav->path =3D g_strdup (path); wav->bits =3D bits; wav->nchannels =3D nchannels; @@ -169,7 +172,7 @@ int wav_start_capture(AudioBackend *state, CaptureState= *s, const char *path, goto error_free; } =20 - cap =3D AUD_add_capture(state, &as, &ops, wav); + cap =3D AUD_add_capture(wav->audio_be, &as, &ops, wav); if (!cap) { error_report("Failed to add audio capture"); goto error_free; diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 60daa62ea3..e9a1daf92a 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -246,15 +246,15 @@ static void voice_set_active(AC97LinkState *s, int bm= _index, int on) { switch (bm_index) { case PI_INDEX: - AUD_set_active_in(s->voice_pi, on); + AUD_set_active_in(s->audio_be, s->voice_pi, on); break; =20 case PO_INDEX: - AUD_set_active_out(s->voice_po, on); + AUD_set_active_out(s->audio_be, s->voice_po, on); break; =20 case MC_INDEX: - AUD_set_active_in(s->voice_mc, on); + AUD_set_active_in(s->audio_be, s->voice_mc, on); break; =20 default: @@ -378,15 +378,15 @@ static void reset_voices(AC97LinkState *s, uint8_t ac= tive[LAST_INDEX]) =20 freq =3D mixer_load(s, AC97_PCM_LR_ADC_Rate); open_voice(s, PI_INDEX, freq); - AUD_set_active_in(s->voice_pi, active[PI_INDEX]); + AUD_set_active_in(s->audio_be, s->voice_pi, active[PI_INDEX]); =20 freq =3D mixer_load(s, AC97_PCM_Front_DAC_Rate); open_voice(s, PO_INDEX, freq); - AUD_set_active_out(s->voice_po, active[PO_INDEX]); + AUD_set_active_out(s->audio_be, s->voice_po, active[PO_INDEX]); =20 freq =3D mixer_load(s, AC97_MIC_ADC_Rate); open_voice(s, MC_INDEX, freq); - AUD_set_active_in(s->voice_mc, active[MC_INDEX]); + AUD_set_active_in(s->audio_be, s->voice_mc, active[MC_INDEX]); } =20 static void get_volume(uint16_t vol, uint16_t mask, int inverse, @@ -416,7 +416,7 @@ static void update_combined_volume_out(AC97LinkState *s) lvol =3D (lvol * plvol) / 255; rvol =3D (rvol * prvol) / 255; =20 - AUD_set_volume_out_lr(s->voice_po, mute, lvol, rvol); + AUD_set_volume_out_lr(s->audio_be, s->voice_po, mute, lvol, rvol); } =20 static void update_volume_in(AC97LinkState *s) @@ -427,7 +427,7 @@ static void update_volume_in(AC97LinkState *s) get_volume(mixer_load(s, AC97_Record_Gain_Mute), 0x0f, 0, &mute, &lvol, &rvol); =20 - AUD_set_volume_in_lr(s->voice_pi, mute, lvol, rvol); + AUD_set_volume_in_lr(s->audio_be, s->voice_pi, mute, lvol, rvol); } =20 static void set_volume(AC97LinkState *s, int index, uint32_t val) @@ -904,7 +904,7 @@ static int write_audio(AC97LinkState *s, AC97BusMasterR= egs *r, int copied; to_copy =3D MIN(temp, sizeof(tmpbuf)); pci_dma_read(&s->dev, addr, tmpbuf, to_copy); - copied =3D AUD_write(s->voice_po, tmpbuf, to_copy); + copied =3D AUD_write(s->audio_be, s->voice_po, tmpbuf, to_copy); dolog("write_audio max=3D%x to_copy=3D%x copied=3D%x", max, to_copy, copied); if (!copied) { @@ -948,7 +948,7 @@ static void write_bup(AC97LinkState *s, int elapsed) while (elapsed) { int temp =3D MIN(elapsed, sizeof(s->silence)); while (temp) { - int copied =3D AUD_write(s->voice_po, s->silence, temp); + int copied =3D AUD_write(s->audio_be, s->voice_po, s->silence,= temp); if (!copied) { return; } @@ -978,7 +978,7 @@ static int read_audio(AC97LinkState *s, AC97BusMasterRe= gs *r, while (temp) { int acquired; to_copy =3D MIN(temp, sizeof(tmpbuf)); - acquired =3D AUD_read(voice, tmpbuf, to_copy); + acquired =3D AUD_read(s->audio_be, voice, tmpbuf, to_copy); if (!acquired) { *stop =3D 1; break; @@ -1275,7 +1275,7 @@ static void ac97_realize(PCIDevice *dev, Error **errp) AC97LinkState *s =3D AC97(dev); uint8_t *c =3D s->dev.config; =20 - if (!AUD_backend_check (&s->audio_be, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } =20 diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 2a2fe7d04f..d3677c1d7f 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -96,7 +96,7 @@ static void adlib_write(void *opaque, uint32_t nport, uin= t32_t val) int a =3D nport & 3; =20 s->active =3D 1; - AUD_set_active_out (s->voice, 1); + AUD_set_active_out(s->audio_be, s->voice, 1); =20 adlib_kill_timers (s); =20 @@ -145,7 +145,8 @@ static int write_audio (AdlibState *s, int samples) int nbytes, wbytes, wsampl; =20 nbytes =3D samples << SHIFT; - wbytes =3D AUD_write ( + wbytes =3D AUD_write( + s->audio_be, s->voice, s->mixbuf + (pos << (SHIFT - 1)), nbytes @@ -257,7 +258,7 @@ static void adlib_realizefn (DeviceState *dev, Error **= errp) as.fmt =3D AUDIO_FORMAT_S16; as.endianness =3D HOST_BIG_ENDIAN; =20 - s->voice =3D AUD_open_out ( + s->voice =3D AUD_open_out( s->audio_be, s->voice, "adlib", @@ -271,7 +272,7 @@ static void adlib_realizefn (DeviceState *dev, Error **= errp) return; } =20 - s->samples =3D AUD_get_buffer_size_out (s->voice) >> SHIFT; + s->samples =3D AUD_get_buffer_size_out(s->audio_be, s->voice) >> SHIFT; s->mixbuf =3D g_malloc0 (s->samples << SHIFT); =20 adlib_portio_list[0].offset =3D s->port; diff --git a/hw/audio/asc.c b/hw/audio/asc.c index 0abb106979..c7bb40df83 100644 --- a/hw/audio/asc.c +++ b/hw/audio/asc.c @@ -355,12 +355,12 @@ static void asc_out_cb(void *opaque, int free_b) * loop because the FIFO has run out of data, and the driver * reuses the stale content in its circular audio buffer. */ - AUD_write(s->voice, s->silentbuf, samples << s->shift); + AUD_write(s->audio_be, s->voice, s->silentbuf, samples << s->s= hift); } return; } =20 - AUD_write(s->voice, s->mixbuf, generated << s->shift); + AUD_write(s->audio_be, s->voice, s->mixbuf, generated << s->shift); } =20 static uint64_t asc_fifo_read(void *opaque, hwaddr addr, @@ -470,9 +470,9 @@ static void asc_write(void *opaque, hwaddr addr, uint64= _t value, asc_fifo_reset(&s->fifos[1]); asc_lower_irq(s); if (value !=3D 0) { - AUD_set_active_out(s->voice, 1); + AUD_set_active_out(s->audio_be, s->voice, 1); } else { - AUD_set_active_out(s->voice, 0); + AUD_set_active_out(s->audio_be, s->voice, 0); } } break; @@ -489,7 +489,7 @@ static void asc_write(void *opaque, hwaddr addr, uint64= _t value, { int vol =3D (value & 0xe0); =20 - AUD_set_volume_out_lr(s->voice, 0, vol, vol); + AUD_set_volume_out_lr(s->audio_be, s->voice, 0, vol, vol); break; } } @@ -545,7 +545,7 @@ static int asc_post_load(void *opaque, int version) ASCState *s =3D ASC(opaque); =20 if (s->regs[ASC_MODE] !=3D 0) { - AUD_set_active_out(s->voice, 1); + AUD_set_active_out(s->audio_be, s->voice, 1); } =20 return 0; @@ -614,7 +614,7 @@ static void asc_reset_hold(Object *obj, ResetType type) { ASCState *s =3D ASC(obj); =20 - AUD_set_active_out(s->voice, 0); + AUD_set_active_out(s->audio_be, s->voice, 0); =20 memset(s->regs, 0, sizeof(s->regs)); asc_fifo_reset(&s->fifos[0]); @@ -658,7 +658,7 @@ static void asc_realize(DeviceState *dev, Error **errp) } =20 s->shift =3D 1; - s->samples =3D AUD_get_buffer_size_out(s->voice) >> s->shift; + s->samples =3D AUD_get_buffer_size_out(s->audio_be, s->voice) >> s->sh= ift; s->mixbuf =3D g_malloc0(s->samples << s->shift); =20 s->silentbuf =3D g_malloc(s->samples << s->shift); diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 98fdbc5b72..ff68a9ccd9 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -327,7 +327,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) goto error; } =20 - s->voice =3D AUD_open_out ( + s->voice =3D AUD_open_out( s->audio_be, s->voice, "cs4231a", @@ -339,7 +339,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) if (s->dregs[Interface_Configuration] & PEN) { if (!s->dma_running) { k->hold_DREQ(s->isa_dma, s->dma); - AUD_set_active_out (s->voice, 1); + AUD_set_active_out(s->audio_be, s->voice, 1); s->transferred =3D 0; } s->dma_running =3D 1; @@ -347,7 +347,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) else { if (s->dma_running) { k->release_DREQ(s->isa_dma, s->dma); - AUD_set_active_out (s->voice, 0); + AUD_set_active_out(s->audio_be, s->voice, 0); } s->dma_running =3D 0; } @@ -356,7 +356,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) error: if (s->dma_running) { k->release_DREQ(s->isa_dma, s->dma); - AUD_set_active_out (s->voice, 0); + AUD_set_active_out(s->audio_be, s->voice, 0); } } =20 @@ -465,7 +465,7 @@ static void cs_write (void *opaque, hwaddr addr, if (s->dma_running) { IsaDmaClass *k =3D ISADMA_GET_CLASS(s->isa_dma); k->release_DREQ(s->isa_dma, s->dma); - AUD_set_active_out (s->voice, 0); + AUD_set_active_out(s->audio_be, s->voice, 0); s->dma_running =3D 0; } } @@ -551,11 +551,11 @@ static int cs_write_audio (CSState *s, int nchan, int= dma_pos, =20 for (i =3D 0; i < copied; ++i) linbuf[i] =3D s->tab[tmpbuf[i]]; - copied =3D AUD_write (s->voice, linbuf, copied << 1); + copied =3D AUD_write(s->audio_be, s->voice, linbuf, copied << = 1); copied >>=3D 1; } else { - copied =3D AUD_write (s->voice, tmpbuf, copied); + copied =3D AUD_write(s->audio_be, s->voice, tmpbuf, copied); } =20 temp -=3D copied; @@ -614,7 +614,7 @@ static int cs4231a_pre_load (void *opaque) if (s->dma_running) { IsaDmaClass *k =3D ISADMA_GET_CLASS(s->isa_dma); k->release_DREQ(s->isa_dma, s->dma); - AUD_set_active_out (s->voice, 0); + AUD_set_active_out(s->audio_be, s->voice, 0); } s->dma_running =3D 0; return 0; diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 9873ffadab..0422cf9836 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -411,7 +411,7 @@ static void es1370_update_voices (ES1370State *s, uint3= 2_t ctl, uint32_t sctl) =20 if (i =3D=3D ADC_CHANNEL) { s->adc_voice =3D - AUD_open_in ( + AUD_open_in( s->audio_be, s->adc_voice, "es1370.adc", @@ -421,7 +421,7 @@ static void es1370_update_voices (ES1370State *s, uint3= 2_t ctl, uint32_t sctl) ); } else { s->dac_voice[i] =3D - AUD_open_out ( + AUD_open_out( s->audio_be, s->dac_voice[i], i ? "es1370.dac2" : "es1370.dac1", @@ -438,9 +438,9 @@ static void es1370_update_voices (ES1370State *s, uint3= 2_t ctl, uint32_t sctl) int on =3D (ctl & b->ctl_en) && !(sctl & b->sctl_pause); =20 if (i =3D=3D ADC_CHANNEL) { - AUD_set_active_in (s->adc_voice, on); + AUD_set_active_in(s->audio_be, s->adc_voice, on); } else { - AUD_set_active_out (s->dac_voice[i], on); + AUD_set_active_out(s->audio_be, s->dac_voice[i], on); } } } @@ -627,7 +627,7 @@ static void es1370_transfer_audio (ES1370State *s, stru= ct chan *d, int loop_sel, int acquired, to_copy; =20 to_copy =3D MIN(to_transfer, sizeof(tmpbuf)); - acquired =3D AUD_read (s->adc_voice, tmpbuf, to_copy); + acquired =3D AUD_read(s->audio_be, s->adc_voice, tmpbuf, to_co= py); if (!acquired) { break; } @@ -646,7 +646,7 @@ static void es1370_transfer_audio (ES1370State *s, stru= ct chan *d, int loop_sel, =20 to_copy =3D MIN(to_transfer, sizeof(tmpbuf)); pci_dma_read (&s->dev, addr, tmpbuf, to_copy); - copied =3D AUD_write (voice, tmpbuf, to_copy); + copied =3D AUD_write(s->audio_be, voice, tmpbuf, to_copy); if (!copied) { break; } diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 68f89e994c..df069a19fc 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -87,7 +87,8 @@ static int write_audio (GUSState *s, int samples) int nbytes, wbytes, wsampl; =20 nbytes =3D samples << s->shift; - wbytes =3D AUD_write ( + wbytes =3D AUD_write( + s->audio_be, s->voice, s->mixbuf + (pos << (s->shift - 1)), nbytes @@ -257,7 +258,7 @@ static void gus_realizefn (DeviceState *dev, Error **er= rp) as.fmt =3D AUDIO_FORMAT_S16; as.endianness =3D HOST_BIG_ENDIAN; =20 - s->voice =3D AUD_open_out ( + s->voice =3D AUD_open_out( s->audio_be, NULL, "gus", @@ -272,7 +273,7 @@ static void gus_realizefn (DeviceState *dev, Error **er= rp) } =20 s->shift =3D 2; - s->samples =3D AUD_get_buffer_size_out (s->voice) >> s->shift; + s->samples =3D AUD_get_buffer_size_out(s->audio_be, s->voice) >> s->sh= ift; s->mixbuf =3D g_malloc0 (s->samples << s->shift); =20 isa_register_portio_list(d, &s->portio_list1, s->port, @@ -287,7 +288,7 @@ static void gus_realizefn (DeviceState *dev, Error **er= rp) s->emu.opaque =3D s; s->pic =3D isa_bus_get_irq(bus, s->emu.gusirq); =20 - AUD_set_active_out (s->voice, 1); + AUD_set_active_out(s->audio_be, s->voice, 1); } =20 static const Property gus_properties[] =3D { diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index e90c9de046..1daa2c25c5 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -275,7 +275,7 @@ static void hda_audio_input_cb(void *opaque, int avail) while (to_transfer) { uint32_t start =3D (uint32_t) (wpos & B_MASK); uint32_t chunk =3D (uint32_t) MIN(B_SIZE - start, to_transfer); - uint32_t read =3D AUD_read(st->voice.in, st->buf + start, chunk); + uint32_t read =3D AUD_read(st->state->audio_be, st->voice.in, st->= buf + start, chunk); wpos +=3D read; to_transfer -=3D read; st->wpos +=3D read; @@ -354,7 +354,7 @@ static void hda_audio_output_cb(void *opaque, int avail) while (to_transfer) { uint32_t start =3D (uint32_t) (rpos & B_MASK); uint32_t chunk =3D (uint32_t) MIN(B_SIZE - start, to_transfer); - uint32_t written =3D AUD_write(st->voice.out, st->buf + start, chu= nk); + uint32_t written =3D AUD_write(st->state->audio_be, st->voice.out,= st->buf + start, chunk); rpos +=3D written; to_transfer -=3D written; st->rpos +=3D written; @@ -375,7 +375,7 @@ static void hda_audio_compat_input_cb(void *opaque, int= avail) =20 while (avail - recv >=3D sizeof(st->compat_buf)) { if (st->compat_bpos !=3D sizeof(st->compat_buf)) { - len =3D AUD_read(st->voice.in, st->compat_buf + st->compat_bpo= s, + len =3D AUD_read(st->state->audio_be, st->voice.in, st->compat= _buf + st->compat_bpos, sizeof(st->compat_buf) - st->compat_bpos); st->compat_bpos +=3D len; recv +=3D len; @@ -408,7 +408,7 @@ static void hda_audio_compat_output_cb(void *opaque, in= t avail) } st->compat_bpos =3D 0; } - len =3D AUD_write(st->voice.out, st->compat_buf + st->compat_bpos, + len =3D AUD_write(st->state->audio_be, st->voice.out, st->compat_b= uf + st->compat_bpos, sizeof(st->compat_buf) - st->compat_bpos); st->compat_bpos +=3D len; sent +=3D len; @@ -440,9 +440,9 @@ static void hda_audio_set_running(HDAAudioStream *st, b= ool running) } } if (st->output) { - AUD_set_active_out(st->voice.out, st->running); + AUD_set_active_out(st->state->audio_be, st->voice.out, st->running= ); } else { - AUD_set_active_in(st->voice.in, st->running); + AUD_set_active_in(st->state->audio_be, st->voice.in, st->running); } } =20 @@ -466,9 +466,9 @@ static void hda_audio_set_amp(HDAAudioStream *st) return; } if (st->output) { - AUD_set_volume_out_lr(st->voice.out, muted, left, right); + AUD_set_volume_out_lr(st->state->audio_be, st->voice.out, muted, l= eft, right); } else { - AUD_set_volume_in_lr(st->voice.in, muted, left, right); + AUD_set_volume_in_lr(st->state->audio_be, st->voice.in, muted, lef= t, right); } } =20 diff --git a/hw/audio/lm4549.c b/hw/audio/lm4549.c index bf711c49c0..4adf67f967 100644 --- a/hw/audio/lm4549.c +++ b/hw/audio/lm4549.c @@ -101,11 +101,11 @@ static void lm4549_audio_transfer(lm4549_state *s) uint32_t i; =20 /* Activate the voice */ - AUD_set_active_out(s->voice, 1); + AUD_set_active_out(s->audio_be, s->voice, 1); s->voice_is_active =3D 1; =20 /* Try to write the buffer content */ - written_bytes =3D AUD_write(s->voice, s->buffer, + written_bytes =3D AUD_write(s->audio_be, s->voice, s->buffer, s->buffer_level * sizeof(uint16_t)); written_samples =3D written_bytes >> 1; =20 @@ -129,14 +129,14 @@ static void lm4549_audio_out_callback(void *opaque, i= nt free) static uint32_t prev_buffer_level; =20 #ifdef LM4549_DEBUG - int size =3D AUD_get_buffer_size_out(s->voice); + int size =3D AUD_get_buffer_size_out(s->audio_be, s->voice); DPRINTF("audio_out_callback size =3D %i free =3D %i\n", size, free); #endif =20 /* Detect that no data are consumed =3D> disable the voice */ if (s->buffer_level =3D=3D prev_buffer_level) { - AUD_set_active_out(s->voice, 0); + AUD_set_active_out(s->audio_be, s->voice, 0); s->voice_is_active =3D 0; } prev_buffer_level =3D s->buffer_level; @@ -285,7 +285,7 @@ static int lm4549_post_load(void *opaque, int version_i= d) =20 /* Request data */ if (s->voice_is_active =3D=3D 1) { - lm4549_audio_out_callback(s, AUD_get_buffer_size_out(s->voice)); + lm4549_audio_out_callback(s, AUD_get_buffer_size_out(s->audio_be, = s->voice)); } =20 return 0; @@ -323,7 +323,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_= req_cb, void* opaque, &as ); =20 - AUD_set_volume_out_lr(s->voice, 0, 255, 255); + AUD_set_volume_out_lr(s->audio_be, s->voice, 0, 255, 255); =20 s->voice_is_active =3D 0; =20 diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 916c56fa4c..a74a263b37 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -106,7 +106,7 @@ static void pcspk_callback(void *opaque, int free) =20 while (free > 0) { n =3D MIN(s->samples - s->play_pos, (unsigned int)free); - n =3D AUD_write(s->voice, &s->sample_buf[s->play_pos], n); + n =3D AUD_write(s->audio_be, s->voice, &s->sample_buf[s->play_pos]= , n); if (!n) break; s->play_pos =3D (s->play_pos + n) % s->samples; @@ -164,7 +164,7 @@ static void pcspk_io_write(void *opaque, hwaddr addr, u= int64_t val, if (s->voice) { if (gate) /* restart */ s->play_pos =3D 0; - AUD_set_active_out(s->voice, gate & s->data_on); + AUD_set_active_out(s->audio_be, s->voice, gate & s->data_on); } } =20 diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 1e3c4caf5e..47b36dfc69 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -185,11 +185,11 @@ static void control (SB16State *s, int hold) =20 if (hold) { k->hold_DREQ(isa_dma, dma); - AUD_set_active_out (s->voice, 1); + AUD_set_active_out(s->audio_be, s->voice, 1); } else { k->release_DREQ(isa_dma, dma); - AUD_set_active_out (s->voice, 0); + AUD_set_active_out(s->audio_be, s->voice, 0); } } =20 @@ -215,7 +215,7 @@ static void continue_dma8 (SB16State *s) as.fmt =3D s->fmt; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out ( + s->voice =3D AUD_open_out( s->audio_be, s->voice, "sb16", @@ -378,7 +378,7 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t= d0, int dma_len) as.fmt =3D s->fmt; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out ( + s->voice =3D AUD_open_out( s->audio_be, s->voice, "sb16", @@ -879,7 +879,7 @@ static void legacy_reset (SB16State *s) as.fmt =3D AUDIO_FORMAT_U8; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out ( + s->voice =3D AUD_open_out( s->audio_be, s->voice, "sb16", @@ -1196,7 +1196,7 @@ static int write_audio (SB16State *s, int nchan, int = dma_pos, } =20 copied =3D k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy= ); - copied =3D AUD_write (s->voice, tmpbuf, copied); + copied =3D AUD_write(s->audio_be, s->voice, tmpbuf, copied); =20 temp -=3D copied; dma_pos =3D (dma_pos + copied) % dma_len; @@ -1302,7 +1302,7 @@ static int sb16_post_load (void *opaque, int version_= id) as.fmt =3D s->fmt; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out ( + s->voice =3D AUD_open_out( s->audio_be, s->voice, "sb16", diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c index 019d296853..5b344d7a0f 100644 --- a/hw/audio/via-ac97.c +++ b/hw/audio/via-ac97.c @@ -53,7 +53,7 @@ static void codec_volume_set_out(ViaAC97State *s) rvol /=3D 255; mute =3D CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT; mute |=3D CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> MUTE_SHIFT; - AUD_set_volume_out_lr(s->vo, mute, lvol, rvol); + AUD_set_volume_out_lr(s->audio_be, s->vo, mute, lvol, rvol); } =20 static void codec_reset(ViaAC97State *s) @@ -189,7 +189,7 @@ static void out_cb(void *opaque, int avail) while (temp) { to_copy =3D MIN(temp, sizeof(tmpbuf)); pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy); - copied =3D AUD_write(s->vo, tmpbuf, to_copy); + copied =3D AUD_write(s->audio_be, s->vo, tmpbuf, to_copy); if (!copied) { stop =3D true; break; @@ -208,7 +208,7 @@ static void out_cb(void *opaque, int avail) c->stat |=3D STAT_PAUSED; } else { c->stat &=3D ~STAT_ACTIVE; - AUD_set_active_out(s->vo, 0); + AUD_set_active_out(s->audio_be, s->vo, 0); } if (c->type & STAT_EOL) { via_isa_set_irq(&s->dev, 0, 1); @@ -317,20 +317,20 @@ static void sgd_write(void *opaque, hwaddr addr, uint= 64_t val, unsigned size) break; case 1: if (val & CNTL_START) { - AUD_set_active_out(s->vo, 1); + AUD_set_active_out(s->audio_be, s->vo, 1); s->aur.stat =3D STAT_ACTIVE; } if (val & CNTL_TERM) { - AUD_set_active_out(s->vo, 0); + AUD_set_active_out(s->audio_be, s->vo, 0); s->aur.stat &=3D ~(STAT_ACTIVE | STAT_PAUSED); s->aur.clen =3D 0; } if (val & CNTL_PAUSE) { - AUD_set_active_out(s->vo, 0); + AUD_set_active_out(s->audio_be, s->vo, 0); s->aur.stat &=3D ~STAT_ACTIVE; s->aur.stat |=3D STAT_PAUSED; } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) { - AUD_set_active_out(s->vo, 1); + AUD_set_active_out(s->audio_be, s->vo, 1); s->aur.stat |=3D STAT_ACTIVE; s->aur.stat &=3D ~STAT_PAUSED; } diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 9101560f38..47fef61af8 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -463,7 +463,7 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, = uint32_t stream_id) stream, virtio_snd_pcm_out_cb, &as); - AUD_set_volume_out_lr(stream->voice.out, 0, 255, 255); + AUD_set_volume_out_lr(s->audio_be, stream->voice.out, 0, 255, 255); } else { stream->voice.in =3D AUD_open_in(s->audio_be, stream->voice.in, @@ -471,7 +471,7 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, = uint32_t stream_id) stream, virtio_snd_pcm_in_cb, &as); - AUD_set_volume_in_lr(stream->voice.in, 0, 255, 255); + AUD_set_volume_in_lr(s->audio_be, stream->voice.in, 0, 255, 255); } =20 return cpu_to_le32(VIRTIO_SND_S_OK); @@ -561,9 +561,9 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSoun= d *s, stream->active =3D start; } if (stream->info.direction =3D=3D VIRTIO_SND_D_OUTPUT) { - AUD_set_active_out(stream->voice.out, start); + AUD_set_active_out(s->audio_be, stream->voice.out, start); } else { - AUD_set_active_in(stream->voice.in, start); + AUD_set_active_in(s->audio_be, stream->voice.in, start); } } else { error_report("Invalid stream id: %"PRIu32, stream_id); @@ -1166,7 +1166,8 @@ static void virtio_snd_pcm_out_cb(void *data, int ava= ilable) buffer->populated =3D true; } for (;;) { - size =3D AUD_write(stream->voice.out, + size =3D AUD_write(stream->s->audio_be, + stream->voice.out, buffer->data + buffer->offset, MIN(buffer->size, available)); assert(size <=3D MIN(buffer->size, available)); @@ -1258,7 +1259,8 @@ static void virtio_snd_pcm_in_cb(void *data, int avai= lable) return_rx_buffer(stream, buffer); break; } - size =3D AUD_read(stream->voice.in, + size =3D AUD_read(stream->s->audio_be, + stream->voice.in, buffer->data + buffer->size, MIN(available, (stream->params.period_bytes - buffer->size))); diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index 336fb6d20b..bc347fe537 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -72,7 +72,7 @@ static inline void wm8750_in_load(WM8750State *s) if (s->idx_in + s->req_in <=3D sizeof(s->data_in)) return; s->idx_in =3D MAX(0, (int) sizeof(s->data_in) - s->req_in); - AUD_read(*s->in[0], s->data_in + s->idx_in, + AUD_read(s->audio_be, *s->in[0], s->data_in + s->idx_in, sizeof(s->data_in) - s->idx_in); } =20 @@ -80,7 +80,7 @@ static inline void wm8750_out_flush(WM8750State *s) { int sent =3D 0; while (sent < s->idx_out) - sent +=3D AUD_write(*s->out[0], s->data_out + sent, s->idx_out - s= ent) + sent +=3D AUD_write(s->audio_be, *s->out[0], s->data_out + sent, s= ->idx_out - sent) ?: s->idx_out; s->idx_out =3D 0; } @@ -145,30 +145,30 @@ static void wm8750_vol_update(WM8750State *s) { /* FIXME: multiply all volumes by s->invol[2], s->invol[3] */ =20 - AUD_set_volume_in_lr(s->adc_voice[0], s->mute, + AUD_set_volume_in_lr(s->audio_be, s->adc_voice[0], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])= ); - AUD_set_volume_in_lr(s->adc_voice[1], s->mute, + AUD_set_volume_in_lr(s->audio_be, s->adc_voice[1], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])= ); - AUD_set_volume_in_lr(s->adc_voice[2], s->mute, + AUD_set_volume_in_lr(s->audio_be, s->adc_voice[2], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])= ); =20 /* FIXME: multiply all volumes by s->outvol[0], s->outvol[1] */ =20 /* Speaker: LOUT2VOL ROUT2VOL */ - AUD_set_volume_out_lr(s->dac_voice[0], s->mute, + AUD_set_volume_out_lr(s->audio_be, s->dac_voice[0], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 4]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 5])); =20 /* Headphone: LOUT1VOL ROUT1VOL */ - AUD_set_volume_out_lr(s->dac_voice[1], s->mute, + AUD_set_volume_out_lr(s->audio_be, s->dac_voice[1], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 2]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 3])); =20 /* MONOOUT: MONOVOL MONOVOL */ - AUD_set_volume_out_lr(s->dac_voice[2], s->mute, + AUD_set_volume_out_lr(s->audio_be, s->dac_voice[2], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 6]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 6])); } @@ -182,9 +182,9 @@ static void wm8750_set_format(WM8750State *s) wm8750_out_flush(s); =20 if (s->in[0] && *s->in[0]) - AUD_set_active_in(*s->in[0], 0); + AUD_set_active_in(s->audio_be, *s->in[0], 0); if (s->out[0] && *s->out[0]) - AUD_set_active_out(*s->out[0], 0); + AUD_set_active_out(s->audio_be, *s->out[0], 0); =20 for (i =3D 0; i < IN_PORT_N; i ++) if (s->adc_voice[i]) { @@ -235,9 +235,9 @@ static void wm8750_set_format(WM8750State *s) * for mixing or combining paths to different ports, so we * connect both channels to where the left channel is routed. */ if (s->in[0] && *s->in[0]) - AUD_set_active_in(*s->in[0], 1); + AUD_set_active_in(s->audio_be, *s->in[0], 1); if (s->out[0] && *s->out[0]) - AUD_set_active_out(*s->out[0], 1); + AUD_set_active_out(s->audio_be, *s->out[0], 1); } =20 static void wm8750_clk_update(WM8750State *s, int ext) diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index a248b943a5..e89f1ffaf6 100644 --- a/hw/display/xlnx_dp.c +++ b/hw/display/xlnx_dp.c @@ -331,7 +331,7 @@ static inline void xlnx_dp_audio_activate(XlnxDPState *= s) { bool activated =3D ((s->core_registers[DP_TX_AUDIO_CONTROL] & DP_TX_AUD_CTRL) !=3D 0); - AUD_set_active_out(s->amixer_output_stream, activated); + AUD_set_active_out(s->audio_be, s->amixer_output_stream, activated); xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(0), &s->audio_buffer_0); xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(1), @@ -401,7 +401,7 @@ static void xlnx_dp_audio_callback(void *opaque, int av= ail) /* Send the buffer through the audio. */ if (s->byte_left <=3D MAX_QEMU_BUFFER_SIZE) { if (s->byte_left !=3D 0) { - written =3D AUD_write(s->amixer_output_stream, + written =3D AUD_write(s->audio_be, s->amixer_output_stream, &s->out_buffer[s->data_ptr], s->byte_left); } else { int len_to_copy; @@ -413,12 +413,12 @@ static void xlnx_dp_audio_callback(void *opaque, int = avail) while (avail) { len_to_copy =3D MIN(AUD_CHBUF_MAX_DEPTH, avail); memset(s->out_buffer, 0, len_to_copy); - avail -=3D AUD_write(s->amixer_output_stream, s->out_buffe= r, + avail -=3D AUD_write(s->audio_be, s->amixer_output_stream,= s->out_buffer, len_to_copy); } } } else { - written =3D AUD_write(s->amixer_output_stream, + written =3D AUD_write(s->audio_be, s->amixer_output_stream, &s->out_buffer[s->data_ptr], MAX_QEMU_BUFFER_S= IZE); } s->byte_left -=3D written; @@ -1401,7 +1401,7 @@ static void xlnx_dp_realize(DeviceState *dev, Error *= *errp) s, xlnx_dp_audio_callback, &as); - AUD_set_volume_out_lr(s->amixer_output_stream, 0, 255, 255); + AUD_set_volume_out_lr(s->audio_be, s->amixer_output_stream, 0, 255, 25= 5); xlnx_dp_audio_activate(s); s->vblank =3D ptimer_init(vblank_hit, s, DP_VBLANK_PTIMER_POLICY); ptimer_transaction_begin(s->vblank); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 8dd9d26599..189fd1df26 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -669,7 +669,7 @@ static void output_callback(void *opaque, int avail) return; } =20 - written =3D AUD_write(s->out.voice, data, len); + written =3D AUD_write(s->audio_be, s->out.voice, data, len); avail -=3D written; s->out.buf.cons +=3D written; =20 @@ -683,7 +683,7 @@ static int usb_audio_set_output_altset(USBAudioState *s= , int altset) { switch (altset) { case ALTSET_OFF: - AUD_set_active_out(s->out.voice, false); + AUD_set_active_out(s->audio_be, s->out.voice, false); break; case ALTSET_STEREO: case ALTSET_51: @@ -692,7 +692,7 @@ static int usb_audio_set_output_altset(USBAudioState *s= , int altset) usb_audio_reinit(USB_DEVICE(s), altset_channels[altset]); } streambuf_init(&s->out.buf, s->buffer, s->out.channels); - AUD_set_active_out(s->out.voice, true); + AUD_set_active_out(s->audio_be, s->out.voice, true); break; default: return -1; @@ -805,7 +805,7 @@ static int usb_audio_set_control(USBAudioState *s, uint= 8_t attrib, } fprintf(stderr, "\n"); } - AUD_set_volume_out(s->out.voice, &s->out.vol); + AUD_set_volume_out(s->audio_be, s->out.voice, &s->out.vol); } =20 return ret; @@ -980,8 +980,8 @@ static void usb_audio_reinit(USBDevice *dev, unsigned c= hannels) =20 s->out.voice =3D AUD_open_out(s->audio_be, s->out.voice, TYPE_USB_AUDI= O, s, output_callback, &s->out.as); - AUD_set_volume_out(s->out.voice, &s->out.vol); - AUD_set_active_out(s->out.voice, 0); + AUD_set_volume_out(s->audio_be, s->out.voice, &s->out.vol); + AUD_set_active_out(s->audio_be, s->out.voice, 0); } =20 static const VMStateDescription vmstate_usb_audio =3D { diff --git a/ui/vnc.c b/ui/vnc.c index 0d499b208b..5c8af65202 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1286,7 +1286,7 @@ static void audio_add(VncState *vs) static void audio_del(VncState *vs) { if (vs->audio_cap) { - AUD_del_capture(vs->audio_cap, vs); + AUD_del_capture(vs->vd->audio_be, vs->audio_cap, vs); vs->audio_cap =3D NULL; } } --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588413; cv=none; d=zohomail.com; s=zohoarc; b=IijZMhqUhrv6osGGp9WcgalFoP+EPQn2erbZqCqYb8rBDi6fS0Bzngbn6wKoIOJyLrfWRvEoZ/mRlajm+ewh6TnOcgwYdzNPyIAeqi1v8ZwbM2VHLUA1RGpOlvshjnz42tLCVUnB3oL6N+8bK3k9w7fr8zWzxTZ6UwlHhXsaKoQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588413; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=AMQeH2cjF88ml33Pu3oNyA0OPW5m9DbkCmqc6SBMCVs=; b=Gb68FjHuktexOl3rq9RVy3witA8h/NEiIMJ7jjWgl/Ml+ZQPoJ/SYz3BikzEwZ/RWrnAUK3KnvrvlhgJOgTdMbNFjAv+zpK8M4qxqYPED7PWJY0DXULGnSrD0YjgZXSRp0gN5hklYr7FkCep4p/7gcJkTFJeL3qUJZKdBhqAI7E= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588413264486.2282797745131; Mon, 1 Dec 2025 03:26:53 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22T-0005Qo-3c; Mon, 01 Dec 2025 06:25:53 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22C-0004M9-Rm for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:37 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ227-0006zx-Pf for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:35 -0500 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-184-uildAgrJOoae2HbSz5M-Gw-1; Mon, 01 Dec 2025 06:25:18 -0500 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id F266D1800579; Mon, 1 Dec 2025 11:25:14 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 851401956095; Mon, 1 Dec 2025 11:25:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588323; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AMQeH2cjF88ml33Pu3oNyA0OPW5m9DbkCmqc6SBMCVs=; b=KhbwEW0P4NZsJKY8xq+7KNt3s9VAYl4wA9vT4N2vhjb0XnfsFc34fO2Mgxe2zZ3gwpd1aW UINTmrncs+fYMEqR9ixxBxaFO/8Jo7Gfw/KajXJ0ltsUm6IKrLXgw+8kgv7l8069sXEf+B ihmVct753Xb0Ot6r5sR7ffY1jXVdDCM= X-MC-Unique: uildAgrJOoae2HbSz5M-Gw-1 X-Mimecast-MFC-AGG-ID: uildAgrJOoae2HbSz5M-Gw_1764588316 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 18/24] audio: make AudioBackend truely abstract Date: Mon, 1 Dec 2025 15:22:59 +0400 Message-ID: <20251201112309.4163921-19-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588416402019200 From: Marc-Andr=C3=A9 Lureau Add virtual methods to be implemented by concrete classes, like AudioDriverClass. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_template.h | 9 +- include/qemu/audio-capture.h | 13 --- include/qemu/audio.h | 61 ++++++++-- audio/audio.c | 208 ++++++++++++++++++++++++++++++----- 4 files changed, 237 insertions(+), 54 deletions(-) diff --git a/audio/audio_template.h b/audio/audio_template.h index 8d66f9cd40..9dee8575f3 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -478,7 +478,7 @@ static void glue (audio_close_, TYPE) (SW *sw) g_free (sw); } =20 -void glue(AUD_close_, TYPE)(AudioBackend *be, SW *sw) +static void glue(audio_driver_close_, TYPE)(AudioBackend *be, SW *sw) { if (sw) { if (audio_bug(__func__, !be)) { @@ -490,14 +490,13 @@ void glue(AUD_close_, TYPE)(AudioBackend *be, SW *sw) } } =20 -SW *glue (AUD_open_, TYPE) ( +static SW *glue(audio_driver_open_, TYPE) ( AudioBackend *be, SW *sw, const char *name, void *callback_opaque , audio_callback_fn callback_fn, - struct audsettings *as - ) + struct audsettings *as) { AudioDriver *s =3D AUDIO_DRIVER(be); AudiodevPerDirectionOptions *pdo; @@ -569,7 +568,7 @@ SW *glue (AUD_open_, TYPE) ( return NULL; } =20 -bool glue(AUD_is_active_, TYPE)(AudioBackend *be, SW *sw) +static bool glue(audio_driver_is_active_, TYPE)(AudioBackend *be, SW *sw) { return sw ? sw->active : 0; } diff --git a/include/qemu/audio-capture.h b/include/qemu/audio-capture.h index f500b0a7f8..5bfbdd0298 100644 --- a/include/qemu/audio-capture.h +++ b/include/qemu/audio-capture.h @@ -8,19 +8,6 @@ =20 #include "audio.h" =20 -typedef struct CaptureVoiceOut CaptureVoiceOut; - -typedef enum { - AUD_CNOTIFY_ENABLE, - AUD_CNOTIFY_DISABLE -} audcnotification_e; - -struct audio_capture_ops { - void (*notify) (void *opaque, audcnotification_e cmd); - void (*capture) (void *opaque, const void *buf, int size); - void (*destroy) (void *opaque); -}; - struct capture_ops { void (*info) (void *opaque); void (*destroy) (void *opaque); diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 745ee881b8..672f9befe5 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -43,6 +43,25 @@ typedef struct audsettings { =20 typedef struct SWVoiceOut SWVoiceOut; typedef struct SWVoiceIn SWVoiceIn; +typedef struct CaptureVoiceOut CaptureVoiceOut; + +typedef enum { + AUD_CNOTIFY_ENABLE, + AUD_CNOTIFY_DISABLE +} audcnotification_e; + +struct audio_capture_ops { + void (*notify) (void *opaque, audcnotification_e cmd); + void (*capture) (void *opaque, const void *buf, int size); + void (*destroy) (void *opaque); +}; + +#define AUDIO_MAX_CHANNELS 16 +typedef struct Volume { + bool mute; + int channels; + uint8_t vol[AUDIO_MAX_CHANNELS]; +} Volume; =20 typedef struct AudioBackend { Object parent_obj; @@ -53,6 +72,38 @@ typedef struct AudioBackendClass { =20 bool (*realize)(AudioBackend *be, Audiodev *dev, Error **errp); const char *(*get_id)(AudioBackend *be); + SWVoiceOut *(*open_out)( + AudioBackend *be, + SWVoiceOut *sw, + const char *name, + void *callback_opaque , + audio_callback_fn callback_fn, + struct audsettings *as); + SWVoiceIn *(*open_in)( + AudioBackend *be, + SWVoiceIn *sw, + const char *name, + void *callback_opaque , + audio_callback_fn callback_fn, + struct audsettings *as); + void (*close_out)(AudioBackend *be, SWVoiceOut *sw); + void (*close_in)(AudioBackend *be, SWVoiceIn *sw); + bool (*is_active_out)(AudioBackend *be, SWVoiceOut *sw); + bool (*is_active_in)(AudioBackend *be, SWVoiceIn *sw); + void (*set_active_out)(AudioBackend *be, SWVoiceOut *sw, bool on); + void (*set_active_in)(AudioBackend *be, SWVoiceIn *sw, bool on); + void (*set_volume_out)(AudioBackend *be, SWVoiceOut *sw, Volume *vol); + void (*set_volume_in)(AudioBackend *be, SWVoiceIn *sw, Volume *vol); + size_t (*write)(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t si= ze); + size_t (*read)(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size= ); + int (*get_buffer_size_out)(AudioBackend *be, SWVoiceOut *sw); + CaptureVoiceOut *(*add_capture)( + AudioBackend *be, + struct audsettings *as, + struct audio_capture_ops *ops, + void *cb_opaque); + void (*del_capture)(AudioBackend *be, CaptureVoiceOut *cap, void *cb_o= paque); + #ifdef CONFIG_GIO bool (*set_dbus_server)(AudioBackend *be, GDBusObjectManagerServer *manager, @@ -73,8 +124,7 @@ SWVoiceOut *AUD_open_out( const char *name, void *callback_opaque, audio_callback_fn callback_fn, - struct audsettings *settings - ); + struct audsettings *settings); =20 void AUD_close_out(AudioBackend *be, SWVoiceOut *sw); size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *pcm_buf, size_t s= ize); @@ -82,13 +132,6 @@ int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceO= ut *sw); void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on); bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw); =20 -#define AUDIO_MAX_CHANNELS 16 -typedef struct Volume { - bool mute; - int channels; - uint8_t vol[AUDIO_MAX_CHANNELS]; -} Volume; - void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol); void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol); =20 diff --git a/audio/audio.c b/audio/audio.c index cc65153dfa..d9c338ea91 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -846,29 +846,36 @@ static void audio_timer (void *opaque) /* * Public API */ + static size_t audio_driver_write(AudioBackend *be, SWVoiceOut *sw, void *= buf, size_t size) + { + HWVoiceOut *hw; + + if (!sw) { + /* XXX: Consider options */ + return size; + } + hw =3D sw->hw; + + if (!hw->enabled) { + dolog ("Writing to disabled voice %s\n", SW_NAME (sw)); + return 0; + } + + if (audio_get_pdo_out(hw->s->dev)->mixing_engine) { + return audio_pcm_sw_write(sw, buf, size); + } else { + return hw->pcm_ops->write(hw, buf, size); + } + } + size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size) { - HWVoiceOut *hw; - - if (!sw) { - /* XXX: Consider options */ - return size; - } - hw =3D sw->hw; - - if (!hw->enabled) { - dolog ("Writing to disabled voice %s\n", SW_NAME (sw)); - return 0; - } + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 - if (audio_get_pdo_out(hw->s->dev)->mixing_engine) { - return audio_pcm_sw_write(sw, buf, size); - } else { - return hw->pcm_ops->write(hw, buf, size); - } + return klass->write(be, sw, buf, size); } =20 -size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size) +static size_t audio_driver_read(AudioBackend *be, SWVoiceIn *sw, void *buf= , size_t size) { HWVoiceIn *hw; =20 @@ -888,9 +895,17 @@ size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void = *buf, size_t size) } else { return hw->pcm_ops->read(hw, buf, size); } + } =20 -int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw) +size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->read(be, sw, buf, size); +} + +static int audio_driver_get_buffer_size_out(AudioBackend *be, SWVoiceOut *= sw) { if (!sw) { return 0; @@ -903,7 +918,14 @@ int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceO= ut *sw) return sw->hw->samples * sw->hw->info.bytes_per_frame; } =20 -void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on) +int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->get_buffer_size_out(be, sw); +} + +static void audio_driver_set_active_out(AudioBackend *be, SWVoiceOut *sw, = bool on) { HWVoiceOut *hw; =20 @@ -949,9 +971,17 @@ void AUD_set_active_out(AudioBackend *be, SWVoiceOut *= sw, bool on) } sw->active =3D on; } + } =20 -void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on) +void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->set_active_out(be, sw, on); +} + +static void audio_driver_set_active_in(AudioBackend *be, SWVoiceIn *sw, bo= ol on) { HWVoiceIn *hw; =20 @@ -996,6 +1026,13 @@ void AUD_set_active_in(AudioBackend *be, SWVoiceIn *s= w, bool on) } } =20 +void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->set_active_in(be, sw, on); +} + static size_t audio_get_avail(SWVoiceIn *sw) { size_t live; @@ -1659,12 +1696,95 @@ static const char *audio_driver_get_id(AudioBackend= *be) return AUDIO_DRIVER(be)->dev->id; } =20 +static CaptureVoiceOut *audio_driver_add_capture( + AudioBackend *be, + struct audsettings *as, + struct audio_capture_ops *ops, + void *cb_opaque); + +static void audio_driver_del_capture( + AudioBackend *be, + CaptureVoiceOut *cap, + void *cb_opaque); + +static void audio_driver_set_volume_out(AudioBackend *be, SWVoiceOut *sw, = Volume *vol); +static void audio_driver_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Vo= lume *vol); + +SWVoiceOut *AUD_open_out( + AudioBackend *be, + SWVoiceOut *sw, + const char *name, + void *callback_opaque , + audio_callback_fn callback_fn, + struct audsettings *as) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->open_out(be, sw, name, callback_opaque, callback_fn, as); +} + +SWVoiceIn *AUD_open_in( + AudioBackend *be, + SWVoiceIn *sw, + const char *name, + void *callback_opaque , + audio_callback_fn callback_fn, + struct audsettings *as) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->open_in(be, sw, name, callback_opaque, callback_fn, as); +} + +void AUD_close_out(AudioBackend *be, SWVoiceOut *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->close_out(be, sw); +} + +void AUD_close_in(AudioBackend *be, SWVoiceIn *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->close_in(be, sw); +} + +bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->is_active_out(be, sw); +} + +bool AUD_is_active_in(AudioBackend *be, SWVoiceIn *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->is_active_in(be, sw); +} + static void audio_driver_class_init(ObjectClass *klass, const void *data) { AudioBackendClass *be =3D AUDIO_BACKEND_CLASS(klass); =20 be->realize =3D audio_be_driver_realize; be->get_id =3D audio_driver_get_id; + be->open_in =3D audio_driver_open_in; + be->open_out =3D audio_driver_open_out; + be->close_in =3D audio_driver_close_in; + be->close_out =3D audio_driver_close_out; + be->is_active_out =3D audio_driver_is_active_out; + be->is_active_in =3D audio_driver_is_active_in; + be->set_active_out =3D audio_driver_set_active_out; + be->set_active_in =3D audio_driver_set_active_in; + be->set_volume_out =3D audio_driver_set_volume_out; + be->set_volume_in =3D audio_driver_set_volume_in; + be->read =3D audio_driver_read; + be->write =3D audio_driver_write; + be->get_buffer_size_out =3D audio_driver_get_buffer_size_out; + be->add_capture =3D audio_driver_add_capture; + be->del_capture =3D audio_driver_del_capture; } =20 static void audio_driver_init(Object *obj) @@ -1862,12 +1982,11 @@ bool AUD_backend_check(AudioBackend **be, Error **e= rrp) =20 static struct audio_pcm_ops capture_pcm_ops; =20 -CaptureVoiceOut *AUD_add_capture( +static CaptureVoiceOut *audio_driver_add_capture( AudioBackend *be, struct audsettings *as, struct audio_capture_ops *ops, - void *cb_opaque - ) + void *cb_opaque) { AudioDriver *s =3D AUDIO_DRIVER(be); CaptureVoiceOut *cap; @@ -1938,7 +2057,21 @@ CaptureVoiceOut *AUD_add_capture( return cap; } =20 -void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaq= ue) +CaptureVoiceOut *AUD_add_capture( + AudioBackend *be, + struct audsettings *as, + struct audio_capture_ops *ops, + void *cb_opaque) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->add_capture(be, as, ops, cb_opaque); +} + +static void audio_driver_del_capture( + AudioBackend *be, + CaptureVoiceOut *cap, + void *cb_opaque) { struct capture_callback *cb; =20 @@ -1977,7 +2110,14 @@ void AUD_del_capture(AudioBackend *be, CaptureVoiceO= ut *cap, void *cb_opaque) } } =20 -void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol) +void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaq= ue) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + klass->del_capture(be, cap, cb_opaque); +} + +static void audio_driver_set_volume_out(AudioBackend *be, SWVoiceOut *sw, = Volume *vol) { if (sw) { HWVoiceOut *hw =3D sw->hw; @@ -1993,7 +2133,14 @@ void AUD_set_volume_out(AudioBackend *be, SWVoiceOut= *sw, Volume *vol) } } =20 -void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol) +void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + klass->set_volume_out(be, sw, vol); +} + +static void audio_driver_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Vo= lume *vol) { if (sw) { HWVoiceIn *hw =3D sw->hw; @@ -2009,6 +2156,13 @@ void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *= sw, Volume *vol) } } =20 +void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + klass->set_volume_in(be, sw, vol); +} + static void audio_create_pdos(Audiodev *dev) { switch (dev->driver) { --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588348; cv=none; d=zohomail.com; s=zohoarc; b=f7bo74bYyhxicr1N1kkwORkPi/OUyl5z59i99osIuSw+D0zOAI59oRHRIoj/IX0k7FDYWm8IneX2bUrNGVlloxN0xwHYWwFe4HtPN/51ay4lvX3YIWKEpJ05XjN/f5UrzQT+07LM6C9TkMZFKTnIp2VBBu6MMT4tDDxqLdNDTHs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588348; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=WeVZF3ijdiVf7ReEzERlNJDV4DDQf1oUAP+81yN3YQE=; b=USo7wKeLhaZrfsywRLvTtyIRimLDaBbBcfEZ8714CLK9lBPAI0ghvgK/XRVIxjP+9a9AyJz+Jqbgkxzg23WvzD4fapGnsWRAoukpS4+xKjrIX42cJNbAscF3J9omO4jRG5cZE7Opw8wL9X4cg8lGIenYIJ4s8i755c4yMaoWHIU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588348806302.74383153842234; Mon, 1 Dec 2025 03:25:48 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22L-0004sE-UR; Mon, 01 Dec 2025 06:25:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22C-0004MK-Rc for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:37 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ227-00070d-Om for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:35 -0500 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-217-oQhTXVkrPIy818hj7Rrjcg-1; Mon, 01 Dec 2025 06:25:23 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7F2611956094; Mon, 1 Dec 2025 11:25:21 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8DF9618002AC; Mon, 1 Dec 2025 11:25:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588326; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WeVZF3ijdiVf7ReEzERlNJDV4DDQf1oUAP+81yN3YQE=; b=WRP/a5SbTQLizTglIPv2lU32o40w0Gqelkh6UaC7/oc16Q75nmt3TctZLaTFcl3hTZQ4Kx zDEYD/bqsowlDwOP/tnWaFdWUHz0qiHYTXPIvj/rewDQ8wL1fNzzjfY9YcUURuetCjW19F Gg/8kfaVDBQ+hz2zQn1ZNmy/Gp4+FO0= X-MC-Unique: oQhTXVkrPIy818hj7Rrjcg-1 X-Mimecast-MFC-AGG-ID: oQhTXVkrPIy818hj7Rrjcg_1764588321 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 19/24] audio: split AudioBackend Date: Mon, 1 Dec 2025 15:23:00 +0400 Message-ID: <20251201112309.4163921-20-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588351746019200 From: Marc-Andr=C3=A9 Lureau Code clean-up, to allow building bare abstract class separately. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qemu/audio.h | 2 + audio/audio-be.c | 210 +++++++++++++++++++++++++++++++++++++++++++ audio/audio.c | 188 -------------------------------------- audio/meson.build | 1 + 4 files changed, 213 insertions(+), 188 deletions(-) create mode 100644 audio/audio-be.c diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 672f9befe5..649fb89de2 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -118,6 +118,8 @@ typedef struct QEMUAudioTimeStamp { =20 bool AUD_backend_check(AudioBackend **be, Error **errp); =20 +AudioBackend *audio_be_new(Audiodev *dev, Error **errp); + SWVoiceOut *AUD_open_out( AudioBackend *be, SWVoiceOut *sw, diff --git a/audio/audio-be.c b/audio/audio-be.c new file mode 100644 index 0000000000..565b7a4cc5 --- /dev/null +++ b/audio/audio-be.c @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: MIT */ + +#include "qemu/osdep.h" +#include "qemu/audio.h" +#include "qemu/audio-capture.h" +#include "qapi/error.h" + +bool AUD_backend_check(AudioBackend **be, Error **errp) +{ + assert(be !=3D NULL); + + if (!*be) { + *be =3D audio_get_default_audio_be(errp); + if (!*be) { + return false; + } + } + + return true; +} + +SWVoiceIn *AUD_open_in( + AudioBackend *be, + SWVoiceIn *sw, + const char *name, + void *callback_opaque , + audio_callback_fn callback_fn, + struct audsettings *as) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->open_in(be, sw, name, callback_opaque, callback_fn, as); +} + +SWVoiceOut *AUD_open_out( + AudioBackend *be, + SWVoiceOut *sw, + const char *name, + void *callback_opaque , + audio_callback_fn callback_fn, + struct audsettings *as) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->open_out(be, sw, name, callback_opaque, callback_fn, as); +} + +void AUD_close_out(AudioBackend *be, SWVoiceOut *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->close_out(be, sw); +} + +void AUD_close_in(AudioBackend *be, SWVoiceIn *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->close_in(be, sw); +} + +bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->is_active_out(be, sw); +} + +bool AUD_is_active_in(AudioBackend *be, SWVoiceIn *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->is_active_in(be, sw); +} + +size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->write(be, sw, buf, size); +} + +size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->read(be, sw, buf, size); +} + +int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->get_buffer_size_out(be, sw); +} + +void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->set_active_out(be, sw, on); +} + +void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->set_active_in(be, sw, on); +} + +void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + klass->set_volume_out(be, sw, vol); +} + +void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + klass->set_volume_in(be, sw, vol); +} + +CaptureVoiceOut *AUD_add_capture( + AudioBackend *be, + struct audsettings *as, + struct audio_capture_ops *ops, + void *cb_opaque) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->add_capture(be, as, ops, cb_opaque); +} + +void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaq= ue) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + klass->del_capture(be, cap, cb_opaque); +} + +#ifdef CONFIG_GIO +bool audio_be_can_set_dbus_server(AudioBackend *be) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + return klass->set_dbus_server !=3D NULL; +} + +bool audio_be_set_dbus_server(AudioBackend *be, + GDBusObjectManagerServer *server, + bool p2p, + Error **errp) +{ + AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); + + if (!audio_be_can_set_dbus_server(be)) { + error_setg(errp, "Audiodev '%s' is not compatible with DBus", + audio_be_get_id(be)); + return false; + } + + return klass->set_dbus_server(be, server, p2p, errp); +} +#endif + +const char *audio_be_get_id(AudioBackend *be) +{ + if (be) { + return AUDIO_BACKEND_GET_CLASS(be)->get_id(be); + } else { + return ""; + } +} + +AudioBackend *audio_be_new(Audiodev *dev, Error **errp) +{ + const char *drvname =3D AudiodevDriver_str(dev->driver); + g_autofree char *type =3D g_strconcat("audio-", drvname, NULL); + AudioBackend *be =3D AUDIO_BACKEND(object_new(type)); + + if (!be) { + error_setg(errp, "Unknown audio driver `%s'", drvname); + return NULL; + } + + if (!AUDIO_BACKEND_GET_CLASS(be)->realize(be, dev, errp)) { + object_unref(OBJECT(be)); + return NULL; + } + + return be; +} + + +static const TypeInfo audio_be_info =3D { + .name =3D TYPE_AUDIO_BACKEND, + .parent =3D TYPE_OBJECT, + .instance_size =3D sizeof(AudioBackend), + .abstract =3D true, + .class_size =3D sizeof(AudioBackendClass), +}; + +static void register_types(void) +{ + type_register_static(&audio_be_info); +} + +type_init(register_types); diff --git a/audio/audio.c b/audio/audio.c index d9c338ea91..3d1c650cc0 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -868,13 +868,6 @@ static void audio_timer (void *opaque) } } =20 -size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->write(be, sw, buf, size); -} - static size_t audio_driver_read(AudioBackend *be, SWVoiceIn *sw, void *buf= , size_t size) { HWVoiceIn *hw; @@ -898,13 +891,6 @@ static size_t audio_driver_read(AudioBackend *be, SWVo= iceIn *sw, void *buf, size =20 } =20 -size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->read(be, sw, buf, size); -} - static int audio_driver_get_buffer_size_out(AudioBackend *be, SWVoiceOut *= sw) { if (!sw) { @@ -918,13 +904,6 @@ static int audio_driver_get_buffer_size_out(AudioBacke= nd *be, SWVoiceOut *sw) return sw->hw->samples * sw->hw->info.bytes_per_frame; } =20 -int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->get_buffer_size_out(be, sw); -} - static void audio_driver_set_active_out(AudioBackend *be, SWVoiceOut *sw, = bool on) { HWVoiceOut *hw; @@ -974,13 +953,6 @@ static void audio_driver_set_active_out(AudioBackend *= be, SWVoiceOut *sw, bool o =20 } =20 -void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->set_active_out(be, sw, on); -} - static void audio_driver_set_active_in(AudioBackend *be, SWVoiceIn *sw, bo= ol on) { HWVoiceIn *hw; @@ -1026,13 +998,6 @@ static void audio_driver_set_active_in(AudioBackend *= be, SWVoiceIn *sw, bool on) } } =20 -void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->set_active_in(be, sw, on); -} - static size_t audio_get_avail(SWVoiceIn *sw) { size_t live; @@ -1683,14 +1648,6 @@ static void audio_vm_change_state_handler (void *opa= que, bool running, =20 static const VMStateDescription vmstate_audio; =20 -static void audio_be_init(Object *obj) -{ -} - -static void audio_be_finalize(Object *obj) -{ -} - static const char *audio_driver_get_id(AudioBackend *be) { return AUDIO_DRIVER(be)->dev->id; @@ -1710,60 +1667,6 @@ static void audio_driver_del_capture( static void audio_driver_set_volume_out(AudioBackend *be, SWVoiceOut *sw, = Volume *vol); static void audio_driver_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Vo= lume *vol); =20 -SWVoiceOut *AUD_open_out( - AudioBackend *be, - SWVoiceOut *sw, - const char *name, - void *callback_opaque , - audio_callback_fn callback_fn, - struct audsettings *as) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->open_out(be, sw, name, callback_opaque, callback_fn, as); -} - -SWVoiceIn *AUD_open_in( - AudioBackend *be, - SWVoiceIn *sw, - const char *name, - void *callback_opaque , - audio_callback_fn callback_fn, - struct audsettings *as) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->open_in(be, sw, name, callback_opaque, callback_fn, as); -} - -void AUD_close_out(AudioBackend *be, SWVoiceOut *sw) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->close_out(be, sw); -} - -void AUD_close_in(AudioBackend *be, SWVoiceIn *sw) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->close_in(be, sw); -} - -bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->is_active_out(be, sw); -} - -bool AUD_is_active_in(AudioBackend *be, SWVoiceIn *sw) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->is_active_in(be, sw); -} - static void audio_driver_class_init(ObjectClass *klass, const void *data) { AudioBackendClass *be =3D AUDIO_BACKEND_CLASS(klass); @@ -1966,20 +1869,6 @@ AudioBackend *audio_get_default_audio_be(Error **err= p) return default_audio_be; } =20 -bool AUD_backend_check(AudioBackend **be, Error **errp) -{ - assert(be !=3D NULL); - - if (!*be) { - *be =3D audio_get_default_audio_be(errp); - if (!*be) { - return false; - } - } - - return true; -} - static struct audio_pcm_ops capture_pcm_ops; =20 static CaptureVoiceOut *audio_driver_add_capture( @@ -2057,17 +1946,6 @@ static CaptureVoiceOut *audio_driver_add_capture( return cap; } =20 -CaptureVoiceOut *AUD_add_capture( - AudioBackend *be, - struct audsettings *as, - struct audio_capture_ops *ops, - void *cb_opaque) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->add_capture(be, as, ops, cb_opaque); -} - static void audio_driver_del_capture( AudioBackend *be, CaptureVoiceOut *cap, @@ -2110,13 +1988,6 @@ static void audio_driver_del_capture( } } =20 -void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaq= ue) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - klass->del_capture(be, cap, cb_opaque); -} - static void audio_driver_set_volume_out(AudioBackend *be, SWVoiceOut *sw, = Volume *vol) { if (sw) { @@ -2133,13 +2004,6 @@ static void audio_driver_set_volume_out(AudioBackend= *be, SWVoiceOut *sw, Volume } } =20 -void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - klass->set_volume_out(be, sw, vol); -} - static void audio_driver_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Vo= lume *vol) { if (sw) { @@ -2156,13 +2020,6 @@ static void audio_driver_set_volume_in(AudioBackend = *be, SWVoiceIn *sw, Volume * } } =20 -void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - klass->set_volume_in(be, sw, vol); -} - static void audio_create_pdos(Audiodev *dev) { switch (dev->driver) { @@ -2416,40 +2273,6 @@ AudioBackend *audio_be_by_name(const char *name, Err= or **errp) } } =20 -#ifdef CONFIG_GIO -bool audio_be_can_set_dbus_server(AudioBackend *be) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - return klass->set_dbus_server !=3D NULL; -} - -bool audio_be_set_dbus_server(AudioBackend *be, - GDBusObjectManagerServer *server, - bool p2p, - Error **errp) -{ - AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); - - if (!audio_be_can_set_dbus_server(be)) { - error_setg(errp, "Audiodev '%s' is not compatible with DBus", - audio_be_get_id(be)); - return false; - } - - return klass->set_dbus_server(be, server, p2p, errp); -} -#endif - -const char *audio_be_get_id(AudioBackend *be) -{ - if (be) { - return AUDIO_BACKEND_GET_CLASS(be)->get_id(be); - } else { - return ""; - } -} - const char *audio_application_name(void) { const char *vm_name; @@ -2513,16 +2336,6 @@ AudiodevList *qmp_query_audiodevs(Error **errp) return ret; } =20 -static const TypeInfo audio_be_info =3D { - .name =3D TYPE_AUDIO_BACKEND, - .parent =3D TYPE_OBJECT, - .instance_size =3D sizeof(AudioBackend), - .instance_init =3D audio_be_init, - .instance_finalize =3D audio_be_finalize, - .abstract =3D true, - .class_size =3D sizeof(AudioBackendClass), -}; - static const TypeInfo audio_driver_info =3D { .name =3D TYPE_AUDIO_DRIVER, .parent =3D TYPE_AUDIO_BACKEND, @@ -2536,7 +2349,6 @@ static const TypeInfo audio_driver_info =3D { =20 static void register_types(void) { - type_register_static(&audio_be_info); type_register_static(&audio_driver_info); } =20 diff --git a/audio/meson.build b/audio/meson.build index b2dca2c640..2450098eb8 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -1,5 +1,6 @@ system_ss.add(files( 'audio.c', + 'audio-be.c', 'mixeng.c', 'noaudio.c', 'wavaudio.c', --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588414; cv=none; d=zohomail.com; s=zohoarc; b=ipDeKrri2LtU8S0VpbO8ce6DTu29Y6e9WWAx9IGW5x9xyk2kj/Iq90ZY7iglCvMmktSFWoy/tigW/wDI6Sp+XnFx83VenVuCVlPURgm7Wf4eOrTGq9u1AFXJc/n2S0eYu4TzArbo2jZ7KW0mcBjkAqpNGV72DdTeuRBU7JCZJKA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588414; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=5PFcRApT//8JzRQ+6cXUt5WlIp1nPXfuDtWOdvpdyOw=; b=FRCLMLm4ohaiOpXaCB/FBcfUME0sc7rqppTvN2jrzrC564dOHqCfQ2zJEQ88uyXWMKRvlEdDR3M9ALS6556LhYGUZMKWmnMQDURdpViRKPR1tcoq+h8M7hBZaTjDoftokAm8kSWId2k+Js13cCbNyz/oXZvDWKfwyA+wI75/sOY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588414852563.9883554276608; Mon, 1 Dec 2025 03:26:54 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22W-0005hu-4U; Mon, 01 Dec 2025 06:25:56 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22N-00051o-9H for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:47 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22F-00072E-J1 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:45 -0500 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-662-qdYBJo_aOxKgPX-CPrm9MQ-1; Mon, 01 Dec 2025 06:25:31 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D68541956088; Mon, 1 Dec 2025 11:25:29 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 72B5C19560A7; Mon, 1 Dec 2025 11:25:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588337; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5PFcRApT//8JzRQ+6cXUt5WlIp1nPXfuDtWOdvpdyOw=; b=XBqlHH9NaLSE+AD2tGwJgUuPqStbRDPRySj5maTdmBXqQRNHWL8tDLc6KHOL+5edv46xSx O6pAQ1TmdzZUQyXAXWOu3Cm+hncEhueSPC2lvMMok6dD21BrwDxMHTyQVKlH/uuHzLP8sH sny1g9xVIzz27UKpu5JqvpBry9hA0TA= X-MC-Unique: qdYBJo_aOxKgPX-CPrm9MQ-1 X-Mimecast-MFC-AGG-ID: qdYBJo_aOxKgPX-CPrm9MQ_1764588330 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier , Manos Pitsidianakis , "Michael S. Tsirkin" , Alistair Francis , "Edgar E. Iglesias" , Peter Maydell , qemu-arm@nongnu.org (open list:Xilinx ZynqMP and...) Subject: [RFC 20/24] audio: AUD_ -> audio_be_ Date: Mon, 1 Dec 2025 15:23:01 +0400 Message-ID: <20251201112309.4163921-21-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588416493019200 From: Marc-Andr=C3=A9 Lureau Use the associate AudioBackend prefix for readability. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_template.h | 4 ++-- include/qemu/audio-capture.h | 4 ++-- include/qemu/audio.h | 37 +++++++++++++++---------------- audio/audio-be.c | 32 +++++++++++++-------------- audio/audio.c | 19 ---------------- audio/wavcapture.c | 4 ++-- hw/audio/ac97.c | 42 ++++++++++++++++++------------------ hw/audio/adlib.c | 10 ++++----- hw/audio/asc.c | 20 ++++++++--------- hw/audio/cs4231a.c | 18 ++++++++-------- hw/audio/es1370.c | 26 +++++++++++----------- hw/audio/gus.c | 10 ++++----- hw/audio/hda-codec.c | 26 +++++++++++----------- hw/audio/lm4549.c | 20 ++++++++--------- hw/audio/pcspk.c | 8 +++---- hw/audio/sb16.c | 22 +++++++++---------- hw/audio/via-ac97.c | 20 ++++++++--------- hw/audio/virtio-snd.c | 34 ++++++++++++++--------------- hw/audio/wm8750.c | 42 ++++++++++++++++++------------------ hw/display/xlnx_dp.c | 14 ++++++------ hw/usb/dev-audio.c | 18 ++++++++-------- ui/vnc.c | 4 ++-- 22 files changed, 208 insertions(+), 226 deletions(-) diff --git a/audio/audio_template.h b/audio/audio_template.h index 9dee8575f3..40d1ad9dea 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -527,7 +527,7 @@ static SW *glue(audio_driver_open_, TYPE) ( } =20 if (!pdo->fixed_settings && sw) { - glue(AUD_close_, TYPE)(be, sw); + glue(audio_be_close_, TYPE)(be, sw); sw =3D NULL; } =20 @@ -564,7 +564,7 @@ static SW *glue(audio_driver_open_, TYPE) ( return sw; =20 fail: - glue(AUD_close_, TYPE)(be, sw); + glue(audio_be_close_, TYPE)(be, sw); return NULL; } =20 diff --git a/include/qemu/audio-capture.h b/include/qemu/audio-capture.h index 5bfbdd0298..d799823224 100644 --- a/include/qemu/audio-capture.h +++ b/include/qemu/audio-capture.h @@ -19,13 +19,13 @@ typedef struct CaptureState { QLIST_ENTRY(CaptureState) entries; } CaptureState; =20 -CaptureVoiceOut *AUD_add_capture( +CaptureVoiceOut *audio_be_add_capture( AudioBackend *be, struct audsettings *as, struct audio_capture_ops *ops, void *opaque); =20 -void AUD_del_capture( +void audio_be_del_capture( AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaque); diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 649fb89de2..1794702c30 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -116,11 +116,11 @@ typedef struct QEMUAudioTimeStamp { uint64_t old_ts; } QEMUAudioTimeStamp; =20 -bool AUD_backend_check(AudioBackend **be, Error **errp); +bool audio_be_backend_check(AudioBackend **be, Error **errp); =20 AudioBackend *audio_be_new(Audiodev *dev, Error **errp); =20 -SWVoiceOut *AUD_open_out( +SWVoiceOut *audio_be_open_out( AudioBackend *be, SWVoiceOut *sw, const char *name, @@ -128,30 +128,31 @@ SWVoiceOut *AUD_open_out( audio_callback_fn callback_fn, struct audsettings *settings); =20 -void AUD_close_out(AudioBackend *be, SWVoiceOut *sw); -size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *pcm_buf, size_t s= ize); -int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw); -void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on); -bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw); +void audio_be_close_out(AudioBackend *be, SWVoiceOut *sw); +size_t audio_be_write(AudioBackend *be, SWVoiceOut *sw, void *pcm_buf, siz= e_t size); +int audio_be_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw); +void audio_be_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on); +bool audio_be_is_active_out(AudioBackend *be, SWVoiceOut *sw); =20 -void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol); -void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol); + +void audio_be_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol= ); +void audio_be_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol); =20 static inline void -AUD_set_volume_out_lr(AudioBackend *be, SWVoiceOut *sw, bool mut, uint8_t = lvol, uint8_t rvol) { - AUD_set_volume_out(be, sw, &(Volume) { +audio_be_set_volume_out_lr(AudioBackend *be, SWVoiceOut *sw, bool mut, uin= t8_t lvol, uint8_t rvol) { + audio_be_set_volume_out(be, sw, &(Volume) { .mute =3D mut, .channels =3D 2, .vol =3D { lvol, rvol } }); } =20 static inline void -AUD_set_volume_in_lr(AudioBackend *be, SWVoiceIn *sw, bool mut, uint8_t lv= ol, uint8_t rvol) { - AUD_set_volume_in(be, sw, &(Volume) { +audio_be_set_volume_in_lr(AudioBackend *be, SWVoiceIn *sw, bool mut, uint8= _t lvol, uint8_t rvol) { + audio_be_set_volume_in(be, sw, &(Volume) { .mute =3D mut, .channels =3D 2, .vol =3D { lvol, rvol } }); } =20 -SWVoiceIn *AUD_open_in( +SWVoiceIn *audio_be_open_in( AudioBackend *be, SWVoiceIn *sw, const char *name, @@ -160,10 +161,10 @@ SWVoiceIn *AUD_open_in( struct audsettings *settings ); =20 -void AUD_close_in(AudioBackend *be, SWVoiceIn *sw); -size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *pcm_buf, size_t siz= e); -void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on); -bool AUD_is_active_in(AudioBackend *be, SWVoiceIn *sw); +void audio_be_close_in(AudioBackend *be, SWVoiceIn *sw); +size_t audio_be_read(AudioBackend *be, SWVoiceIn *sw, void *pcm_buf, size_= t size); +void audio_be_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on); +bool audio_be_is_active_in(AudioBackend *be, SWVoiceIn *sw); =20 void audio_cleanup(void); =20 diff --git a/audio/audio-be.c b/audio/audio-be.c index 565b7a4cc5..9af4dbe5e9 100644 --- a/audio/audio-be.c +++ b/audio/audio-be.c @@ -5,7 +5,7 @@ #include "qemu/audio-capture.h" #include "qapi/error.h" =20 -bool AUD_backend_check(AudioBackend **be, Error **errp) +bool audio_be_backend_check(AudioBackend **be, Error **errp) { assert(be !=3D NULL); =20 @@ -19,7 +19,7 @@ bool AUD_backend_check(AudioBackend **be, Error **errp) return true; } =20 -SWVoiceIn *AUD_open_in( +SWVoiceIn *audio_be_open_in( AudioBackend *be, SWVoiceIn *sw, const char *name, @@ -32,7 +32,7 @@ SWVoiceIn *AUD_open_in( return klass->open_in(be, sw, name, callback_opaque, callback_fn, as); } =20 -SWVoiceOut *AUD_open_out( +SWVoiceOut *audio_be_open_out( AudioBackend *be, SWVoiceOut *sw, const char *name, @@ -45,84 +45,84 @@ SWVoiceOut *AUD_open_out( return klass->open_out(be, sw, name, callback_opaque, callback_fn, as); } =20 -void AUD_close_out(AudioBackend *be, SWVoiceOut *sw) +void audio_be_close_out(AudioBackend *be, SWVoiceOut *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->close_out(be, sw); } =20 -void AUD_close_in(AudioBackend *be, SWVoiceIn *sw) +void audio_be_close_in(AudioBackend *be, SWVoiceIn *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->close_in(be, sw); } =20 -bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw) +bool audio_be_is_active_out(AudioBackend *be, SWVoiceOut *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->is_active_out(be, sw); } =20 -bool AUD_is_active_in(AudioBackend *be, SWVoiceIn *sw) +bool audio_be_is_active_in(AudioBackend *be, SWVoiceIn *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->is_active_in(be, sw); } =20 -size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size) +size_t audio_be_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t = size) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->write(be, sw, buf, size); } =20 -size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size) +size_t audio_be_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t si= ze) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->read(be, sw, buf, size); } =20 -int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw) +int audio_be_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->get_buffer_size_out(be, sw); } =20 -void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on) +void audio_be_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->set_active_out(be, sw, on); } =20 -void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on) +void audio_be_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 return klass->set_active_in(be, sw, on); } =20 -void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol) +void audio_be_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 klass->set_volume_out(be, sw, vol); } =20 -void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol) +void audio_be_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 klass->set_volume_in(be, sw, vol); } =20 -CaptureVoiceOut *AUD_add_capture( +CaptureVoiceOut *audio_be_add_capture( AudioBackend *be, struct audsettings *as, struct audio_capture_ops *ops, @@ -133,7 +133,7 @@ CaptureVoiceOut *AUD_add_capture( return klass->add_capture(be, as, ops, cb_opaque); } =20 -void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaq= ue) +void audio_be_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb= _opaque) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 diff --git a/audio/audio.c b/audio/audio.c index 3d1c650cc0..da2a4da125 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1605,25 +1605,6 @@ static bool audio_be_driver_realize(AudioBackend *ab= e, Audiodev *dev, Error **er return true; } =20 -static AudioBackend *audio_be_new(Audiodev *dev, Error **errp) -{ - const char *drvname =3D AudiodevDriver_str(dev->driver); - g_autofree char *type =3D g_strconcat("audio-", drvname, NULL); - AudioBackend *be =3D AUDIO_BACKEND(object_new(type)); - - if (!be) { - error_setg(errp, "Unknown audio driver `%s'", drvname); - return NULL; - } - - if (!AUDIO_BACKEND_GET_CLASS(be)->realize(be, dev, errp)) { - object_unref(OBJECT(be)); - return NULL; - } - - return be; -} - static void audio_vm_change_state_handler (void *opaque, bool running, RunState state) { diff --git a/audio/wavcapture.c b/audio/wavcapture.c index 2950ceaf24..69aa91e35f 100644 --- a/audio/wavcapture.c +++ b/audio/wavcapture.c @@ -86,7 +86,7 @@ static void wav_capture_destroy (void *opaque) { WAVState *wav =3D opaque; =20 - AUD_del_capture(wav->audio_be, wav->cap, wav); + audio_be_del_capture(wav->audio_be, wav->cap, wav); g_free (wav); } =20 @@ -172,7 +172,7 @@ int wav_start_capture(AudioBackend *state, CaptureState= *s, const char *path, goto error_free; } =20 - cap =3D AUD_add_capture(wav->audio_be, &as, &ops, wav); + cap =3D audio_be_add_capture(wav->audio_be, &as, &ops, wav); if (!cap) { error_report("Failed to add audio capture"); goto error_free; diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index e9a1daf92a..78f53b977b 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -246,15 +246,15 @@ static void voice_set_active(AC97LinkState *s, int bm= _index, int on) { switch (bm_index) { case PI_INDEX: - AUD_set_active_in(s->audio_be, s->voice_pi, on); + audio_be_set_active_in(s->audio_be, s->voice_pi, on); break; =20 case PO_INDEX: - AUD_set_active_out(s->audio_be, s->voice_po, on); + audio_be_set_active_out(s->audio_be, s->voice_po, on); break; =20 case MC_INDEX: - AUD_set_active_in(s->audio_be, s->voice_mc, on); + audio_be_set_active_in(s->audio_be, s->voice_mc, on); break; =20 default: @@ -319,7 +319,7 @@ static void open_voice(AC97LinkState *s, int index, int= freq) s->invalid_freq[index] =3D 0; switch (index) { case PI_INDEX: - s->voice_pi =3D AUD_open_in( + s->voice_pi =3D audio_be_open_in( s->audio_be, s->voice_pi, "ac97.pi", @@ -330,7 +330,7 @@ static void open_voice(AC97LinkState *s, int index, int= freq) break; =20 case PO_INDEX: - s->voice_po =3D AUD_open_out( + s->voice_po =3D audio_be_open_out( s->audio_be, s->voice_po, "ac97.po", @@ -341,7 +341,7 @@ static void open_voice(AC97LinkState *s, int index, int= freq) break; =20 case MC_INDEX: - s->voice_mc =3D AUD_open_in( + s->voice_mc =3D audio_be_open_in( s->audio_be, s->voice_mc, "ac97.mc", @@ -355,17 +355,17 @@ static void open_voice(AC97LinkState *s, int index, i= nt freq) s->invalid_freq[index] =3D freq; switch (index) { case PI_INDEX: - AUD_close_in(s->audio_be, s->voice_pi); + audio_be_close_in(s->audio_be, s->voice_pi); s->voice_pi =3D NULL; break; =20 case PO_INDEX: - AUD_close_out(s->audio_be, s->voice_po); + audio_be_close_out(s->audio_be, s->voice_po); s->voice_po =3D NULL; break; =20 case MC_INDEX: - AUD_close_in(s->audio_be, s->voice_mc); + audio_be_close_in(s->audio_be, s->voice_mc); s->voice_mc =3D NULL; break; } @@ -378,15 +378,15 @@ static void reset_voices(AC97LinkState *s, uint8_t ac= tive[LAST_INDEX]) =20 freq =3D mixer_load(s, AC97_PCM_LR_ADC_Rate); open_voice(s, PI_INDEX, freq); - AUD_set_active_in(s->audio_be, s->voice_pi, active[PI_INDEX]); + audio_be_set_active_in(s->audio_be, s->voice_pi, active[PI_INDEX]); =20 freq =3D mixer_load(s, AC97_PCM_Front_DAC_Rate); open_voice(s, PO_INDEX, freq); - AUD_set_active_out(s->audio_be, s->voice_po, active[PO_INDEX]); + audio_be_set_active_out(s->audio_be, s->voice_po, active[PO_INDEX]); =20 freq =3D mixer_load(s, AC97_MIC_ADC_Rate); open_voice(s, MC_INDEX, freq); - AUD_set_active_in(s->audio_be, s->voice_mc, active[MC_INDEX]); + audio_be_set_active_in(s->audio_be, s->voice_mc, active[MC_INDEX]); } =20 static void get_volume(uint16_t vol, uint16_t mask, int inverse, @@ -416,7 +416,7 @@ static void update_combined_volume_out(AC97LinkState *s) lvol =3D (lvol * plvol) / 255; rvol =3D (rvol * prvol) / 255; =20 - AUD_set_volume_out_lr(s->audio_be, s->voice_po, mute, lvol, rvol); + audio_be_set_volume_out_lr(s->audio_be, s->voice_po, mute, lvol, rvol); } =20 static void update_volume_in(AC97LinkState *s) @@ -427,7 +427,7 @@ static void update_volume_in(AC97LinkState *s) get_volume(mixer_load(s, AC97_Record_Gain_Mute), 0x0f, 0, &mute, &lvol, &rvol); =20 - AUD_set_volume_in_lr(s->audio_be, s->voice_pi, mute, lvol, rvol); + audio_be_set_volume_in_lr(s->audio_be, s->voice_pi, mute, lvol, rvol); } =20 static void set_volume(AC97LinkState *s, int index, uint32_t val) @@ -904,7 +904,7 @@ static int write_audio(AC97LinkState *s, AC97BusMasterR= egs *r, int copied; to_copy =3D MIN(temp, sizeof(tmpbuf)); pci_dma_read(&s->dev, addr, tmpbuf, to_copy); - copied =3D AUD_write(s->audio_be, s->voice_po, tmpbuf, to_copy); + copied =3D audio_be_write(s->audio_be, s->voice_po, tmpbuf, to_cop= y); dolog("write_audio max=3D%x to_copy=3D%x copied=3D%x", max, to_copy, copied); if (!copied) { @@ -948,7 +948,7 @@ static void write_bup(AC97LinkState *s, int elapsed) while (elapsed) { int temp =3D MIN(elapsed, sizeof(s->silence)); while (temp) { - int copied =3D AUD_write(s->audio_be, s->voice_po, s->silence,= temp); + int copied =3D audio_be_write(s->audio_be, s->voice_po, s->sil= ence, temp); if (!copied) { return; } @@ -978,7 +978,7 @@ static int read_audio(AC97LinkState *s, AC97BusMasterRe= gs *r, while (temp) { int acquired; to_copy =3D MIN(temp, sizeof(tmpbuf)); - acquired =3D AUD_read(s->audio_be, voice, tmpbuf, to_copy); + acquired =3D audio_be_read(s->audio_be, voice, tmpbuf, to_copy); if (!acquired) { *stop =3D 1; break; @@ -1275,7 +1275,7 @@ static void ac97_realize(PCIDevice *dev, Error **errp) AC97LinkState *s =3D AC97(dev); uint8_t *c =3D s->dev.config; =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -1301,9 +1301,9 @@ static void ac97_exit(PCIDevice *dev) { AC97LinkState *s =3D AC97(dev); =20 - AUD_close_in(s->audio_be, s->voice_pi); - AUD_close_out(s->audio_be, s->voice_po); - AUD_close_in(s->audio_be, s->voice_mc); + audio_be_close_in(s->audio_be, s->voice_pi); + audio_be_close_out(s->audio_be, s->voice_po); + audio_be_close_in(s->audio_be, s->voice_mc); } =20 static const Property ac97_properties[] =3D { diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index d3677c1d7f..b1dd1f7638 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -96,7 +96,7 @@ static void adlib_write(void *opaque, uint32_t nport, uin= t32_t val) int a =3D nport & 3; =20 s->active =3D 1; - AUD_set_active_out(s->audio_be, s->voice, 1); + audio_be_set_active_out(s->audio_be, s->voice, 1); =20 adlib_kill_timers (s); =20 @@ -145,7 +145,7 @@ static int write_audio (AdlibState *s, int samples) int nbytes, wbytes, wsampl; =20 nbytes =3D samples << SHIFT; - wbytes =3D AUD_write( + wbytes =3D audio_be_write( s->audio_be, s->voice, s->mixbuf + (pos << (SHIFT - 1)), @@ -239,7 +239,7 @@ static void adlib_realizefn (DeviceState *dev, Error **= errp) AdlibState *s =3D ADLIB(dev); struct audsettings as; =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -258,7 +258,7 @@ static void adlib_realizefn (DeviceState *dev, Error **= errp) as.fmt =3D AUDIO_FORMAT_S16; as.endianness =3D HOST_BIG_ENDIAN; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "adlib", @@ -272,7 +272,7 @@ static void adlib_realizefn (DeviceState *dev, Error **= errp) return; } =20 - s->samples =3D AUD_get_buffer_size_out(s->audio_be, s->voice) >> SHIFT; + s->samples =3D audio_be_get_buffer_size_out(s->audio_be, s->voice) >> = SHIFT; s->mixbuf =3D g_malloc0 (s->samples << SHIFT); =20 adlib_portio_list[0].offset =3D s->port; diff --git a/hw/audio/asc.c b/hw/audio/asc.c index c7bb40df83..82a2990a9a 100644 --- a/hw/audio/asc.c +++ b/hw/audio/asc.c @@ -355,12 +355,12 @@ static void asc_out_cb(void *opaque, int free_b) * loop because the FIFO has run out of data, and the driver * reuses the stale content in its circular audio buffer. */ - AUD_write(s->audio_be, s->voice, s->silentbuf, samples << s->s= hift); + audio_be_write(s->audio_be, s->voice, s->silentbuf, samples <<= s->shift); } return; } =20 - AUD_write(s->audio_be, s->voice, s->mixbuf, generated << s->shift); + audio_be_write(s->audio_be, s->voice, s->mixbuf, generated << s->shift= ); } =20 static uint64_t asc_fifo_read(void *opaque, hwaddr addr, @@ -470,9 +470,9 @@ static void asc_write(void *opaque, hwaddr addr, uint64= _t value, asc_fifo_reset(&s->fifos[1]); asc_lower_irq(s); if (value !=3D 0) { - AUD_set_active_out(s->audio_be, s->voice, 1); + audio_be_set_active_out(s->audio_be, s->voice, 1); } else { - AUD_set_active_out(s->audio_be, s->voice, 0); + audio_be_set_active_out(s->audio_be, s->voice, 0); } } break; @@ -489,7 +489,7 @@ static void asc_write(void *opaque, hwaddr addr, uint64= _t value, { int vol =3D (value & 0xe0); =20 - AUD_set_volume_out_lr(s->audio_be, s->voice, 0, vol, vol); + audio_be_set_volume_out_lr(s->audio_be, s->voice, 0, vol, vol); break; } } @@ -545,7 +545,7 @@ static int asc_post_load(void *opaque, int version) ASCState *s =3D ASC(opaque); =20 if (s->regs[ASC_MODE] !=3D 0) { - AUD_set_active_out(s->audio_be, s->voice, 1); + audio_be_set_active_out(s->audio_be, s->voice, 1); } =20 return 0; @@ -614,7 +614,7 @@ static void asc_reset_hold(Object *obj, ResetType type) { ASCState *s =3D ASC(obj); =20 - AUD_set_active_out(s->audio_be, s->voice, 0); + audio_be_set_active_out(s->audio_be, s->voice, 0); =20 memset(s->regs, 0, sizeof(s->regs)); asc_fifo_reset(&s->fifos[0]); @@ -641,7 +641,7 @@ static void asc_realize(DeviceState *dev, Error **errp) ASCState *s =3D ASC(dev); struct audsettings as; =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -650,7 +650,7 @@ static void asc_realize(DeviceState *dev, Error **errp) as.fmt =3D AUDIO_FORMAT_U8; as.endianness =3D HOST_BIG_ENDIAN; =20 - s->voice =3D AUD_open_out(s->audio_be, s->voice, "asc.out", s, asc_out= _cb, + s->voice =3D audio_be_open_out(s->audio_be, s->voice, "asc.out", s, as= c_out_cb, &as); if (!s->voice) { error_setg(errp, "Initializing audio stream failed"); @@ -658,7 +658,7 @@ static void asc_realize(DeviceState *dev, Error **errp) } =20 s->shift =3D 1; - s->samples =3D AUD_get_buffer_size_out(s->audio_be, s->voice) >> s->sh= ift; + s->samples =3D audio_be_get_buffer_size_out(s->audio_be, s->voice) >> = s->shift; s->mixbuf =3D g_malloc0(s->samples << s->shift); =20 s->silentbuf =3D g_malloc(s->samples << s->shift); diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index ff68a9ccd9..fdfb536468 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -327,7 +327,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) goto error; } =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "cs4231a", @@ -339,7 +339,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) if (s->dregs[Interface_Configuration] & PEN) { if (!s->dma_running) { k->hold_DREQ(s->isa_dma, s->dma); - AUD_set_active_out(s->audio_be, s->voice, 1); + audio_be_set_active_out(s->audio_be, s->voice, 1); s->transferred =3D 0; } s->dma_running =3D 1; @@ -347,7 +347,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) else { if (s->dma_running) { k->release_DREQ(s->isa_dma, s->dma); - AUD_set_active_out(s->audio_be, s->voice, 0); + audio_be_set_active_out(s->audio_be, s->voice, 0); } s->dma_running =3D 0; } @@ -356,7 +356,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) error: if (s->dma_running) { k->release_DREQ(s->isa_dma, s->dma); - AUD_set_active_out(s->audio_be, s->voice, 0); + audio_be_set_active_out(s->audio_be, s->voice, 0); } } =20 @@ -465,7 +465,7 @@ static void cs_write (void *opaque, hwaddr addr, if (s->dma_running) { IsaDmaClass *k =3D ISADMA_GET_CLASS(s->isa_dma); k->release_DREQ(s->isa_dma, s->dma); - AUD_set_active_out(s->audio_be, s->voice, 0); + audio_be_set_active_out(s->audio_be, s->voice, 0); s->dma_running =3D 0; } } @@ -551,11 +551,11 @@ static int cs_write_audio (CSState *s, int nchan, int= dma_pos, =20 for (i =3D 0; i < copied; ++i) linbuf[i] =3D s->tab[tmpbuf[i]]; - copied =3D AUD_write(s->audio_be, s->voice, linbuf, copied << = 1); + copied =3D audio_be_write(s->audio_be, s->voice, linbuf, copie= d << 1); copied >>=3D 1; } else { - copied =3D AUD_write(s->audio_be, s->voice, tmpbuf, copied); + copied =3D audio_be_write(s->audio_be, s->voice, tmpbuf, copie= d); } =20 temp -=3D copied; @@ -614,7 +614,7 @@ static int cs4231a_pre_load (void *opaque) if (s->dma_running) { IsaDmaClass *k =3D ISADMA_GET_CLASS(s->isa_dma); k->release_DREQ(s->isa_dma, s->dma); - AUD_set_active_out(s->audio_be, s->voice, 0); + audio_be_set_active_out(s->audio_be, s->voice, 0); } s->dma_running =3D 0; return 0; @@ -678,7 +678,7 @@ static void cs4231a_realizefn (DeviceState *dev, Error = **errp) return; } =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 0422cf9836..37e80c6201 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -330,10 +330,10 @@ static void es1370_reset (ES1370State *s) d->scount =3D 0; d->leftover =3D 0; if (i =3D=3D ADC_CHANNEL) { - AUD_close_in(s->audio_be, s->adc_voice); + audio_be_close_in(s->audio_be, s->adc_voice); s->adc_voice =3D NULL; } else { - AUD_close_out(s->audio_be, s->dac_voice[i]); + audio_be_close_out(s->audio_be, s->dac_voice[i]); s->dac_voice[i] =3D NULL; } } @@ -411,7 +411,7 @@ static void es1370_update_voices (ES1370State *s, uint3= 2_t ctl, uint32_t sctl) =20 if (i =3D=3D ADC_CHANNEL) { s->adc_voice =3D - AUD_open_in( + audio_be_open_in( s->audio_be, s->adc_voice, "es1370.adc", @@ -421,7 +421,7 @@ static void es1370_update_voices (ES1370State *s, uint3= 2_t ctl, uint32_t sctl) ); } else { s->dac_voice[i] =3D - AUD_open_out( + audio_be_open_out( s->audio_be, s->dac_voice[i], i ? "es1370.dac2" : "es1370.dac1", @@ -438,9 +438,9 @@ static void es1370_update_voices (ES1370State *s, uint3= 2_t ctl, uint32_t sctl) int on =3D (ctl & b->ctl_en) && !(sctl & b->sctl_pause); =20 if (i =3D=3D ADC_CHANNEL) { - AUD_set_active_in(s->audio_be, s->adc_voice, on); + audio_be_set_active_in(s->audio_be, s->adc_voice, on); } else { - AUD_set_active_out(s->audio_be, s->dac_voice[i], on); + audio_be_set_active_out(s->audio_be, s->dac_voice[i], on); } } } @@ -627,7 +627,7 @@ static void es1370_transfer_audio (ES1370State *s, stru= ct chan *d, int loop_sel, int acquired, to_copy; =20 to_copy =3D MIN(to_transfer, sizeof(tmpbuf)); - acquired =3D AUD_read(s->audio_be, s->adc_voice, tmpbuf, to_co= py); + acquired =3D audio_be_read(s->audio_be, s->adc_voice, tmpbuf, = to_copy); if (!acquired) { break; } @@ -646,7 +646,7 @@ static void es1370_transfer_audio (ES1370State *s, stru= ct chan *d, int loop_sel, =20 to_copy =3D MIN(to_transfer, sizeof(tmpbuf)); pci_dma_read (&s->dev, addr, tmpbuf, to_copy); - copied =3D AUD_write(s->audio_be, voice, tmpbuf, to_copy); + copied =3D audio_be_write(s->audio_be, voice, tmpbuf, to_copy); if (!copied) { break; } @@ -784,12 +784,12 @@ static int es1370_post_load (void *opaque, int versio= n_id) for (i =3D 0; i < NB_CHANNELS; ++i) { if (i =3D=3D ADC_CHANNEL) { if (s->adc_voice) { - AUD_close_in(s->audio_be, s->adc_voice); + audio_be_close_in(s->audio_be, s->adc_voice); s->adc_voice =3D NULL; } } else { if (s->dac_voice[i]) { - AUD_close_out(s->audio_be, s->dac_voice[i]); + audio_be_close_out(s->audio_be, s->dac_voice[i]); s->dac_voice[i] =3D NULL; } } @@ -833,7 +833,7 @@ static void es1370_realize(PCIDevice *dev, Error **errp) ES1370State *s =3D ES1370(dev); uint8_t *c =3D s->dev.config; =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -861,10 +861,10 @@ static void es1370_exit(PCIDevice *dev) int i; =20 for (i =3D 0; i < 2; ++i) { - AUD_close_out(s->audio_be, s->dac_voice[i]); + audio_be_close_out(s->audio_be, s->dac_voice[i]); } =20 - AUD_close_in(s->audio_be, s->adc_voice); + audio_be_close_in(s->audio_be, s->adc_voice); } =20 static const Property es1370_properties[] =3D { diff --git a/hw/audio/gus.c b/hw/audio/gus.c index df069a19fc..ea759ae0f0 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -87,7 +87,7 @@ static int write_audio (GUSState *s, int samples) int nbytes, wbytes, wsampl; =20 nbytes =3D samples << s->shift; - wbytes =3D AUD_write( + wbytes =3D audio_be_write( s->audio_be, s->voice, s->mixbuf + (pos << (s->shift - 1)), @@ -243,7 +243,7 @@ static void gus_realizefn (DeviceState *dev, Error **er= rp) IsaDmaClass *k; struct audsettings as; =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -258,7 +258,7 @@ static void gus_realizefn (DeviceState *dev, Error **er= rp) as.fmt =3D AUDIO_FORMAT_S16; as.endianness =3D HOST_BIG_ENDIAN; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, NULL, "gus", @@ -273,7 +273,7 @@ static void gus_realizefn (DeviceState *dev, Error **er= rp) } =20 s->shift =3D 2; - s->samples =3D AUD_get_buffer_size_out(s->audio_be, s->voice) >> s->sh= ift; + s->samples =3D audio_be_get_buffer_size_out(s->audio_be, s->voice) >> = s->shift; s->mixbuf =3D g_malloc0 (s->samples << s->shift); =20 isa_register_portio_list(d, &s->portio_list1, s->port, @@ -288,7 +288,7 @@ static void gus_realizefn (DeviceState *dev, Error **er= rp) s->emu.opaque =3D s; s->pic =3D isa_bus_get_irq(bus, s->emu.gusirq); =20 - AUD_set_active_out(s->audio_be, s->voice, 1); + audio_be_set_active_out(s->audio_be, s->voice, 1); } =20 static const Property gus_properties[] =3D { diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index 1daa2c25c5..28167c00da 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -275,7 +275,7 @@ static void hda_audio_input_cb(void *opaque, int avail) while (to_transfer) { uint32_t start =3D (uint32_t) (wpos & B_MASK); uint32_t chunk =3D (uint32_t) MIN(B_SIZE - start, to_transfer); - uint32_t read =3D AUD_read(st->state->audio_be, st->voice.in, st->= buf + start, chunk); + uint32_t read =3D audio_be_read(st->state->audio_be, st->voice.in,= st->buf + start, chunk); wpos +=3D read; to_transfer -=3D read; st->wpos +=3D read; @@ -354,7 +354,7 @@ static void hda_audio_output_cb(void *opaque, int avail) while (to_transfer) { uint32_t start =3D (uint32_t) (rpos & B_MASK); uint32_t chunk =3D (uint32_t) MIN(B_SIZE - start, to_transfer); - uint32_t written =3D AUD_write(st->state->audio_be, st->voice.out,= st->buf + start, chunk); + uint32_t written =3D audio_be_write(st->state->audio_be, st->voice= .out, st->buf + start, chunk); rpos +=3D written; to_transfer -=3D written; st->rpos +=3D written; @@ -375,7 +375,7 @@ static void hda_audio_compat_input_cb(void *opaque, int= avail) =20 while (avail - recv >=3D sizeof(st->compat_buf)) { if (st->compat_bpos !=3D sizeof(st->compat_buf)) { - len =3D AUD_read(st->state->audio_be, st->voice.in, st->compat= _buf + st->compat_bpos, + len =3D audio_be_read(st->state->audio_be, st->voice.in, st->c= ompat_buf + st->compat_bpos, sizeof(st->compat_buf) - st->compat_bpos); st->compat_bpos +=3D len; recv +=3D len; @@ -408,7 +408,7 @@ static void hda_audio_compat_output_cb(void *opaque, in= t avail) } st->compat_bpos =3D 0; } - len =3D AUD_write(st->state->audio_be, st->voice.out, st->compat_b= uf + st->compat_bpos, + len =3D audio_be_write(st->state->audio_be, st->voice.out, st->com= pat_buf + st->compat_bpos, sizeof(st->compat_buf) - st->compat_bpos); st->compat_bpos +=3D len; sent +=3D len; @@ -440,9 +440,9 @@ static void hda_audio_set_running(HDAAudioStream *st, b= ool running) } } if (st->output) { - AUD_set_active_out(st->state->audio_be, st->voice.out, st->running= ); + audio_be_set_active_out(st->state->audio_be, st->voice.out, st->ru= nning); } else { - AUD_set_active_in(st->state->audio_be, st->voice.in, st->running); + audio_be_set_active_in(st->state->audio_be, st->voice.in, st->runn= ing); } } =20 @@ -466,9 +466,9 @@ static void hda_audio_set_amp(HDAAudioStream *st) return; } if (st->output) { - AUD_set_volume_out_lr(st->state->audio_be, st->voice.out, muted, l= eft, right); + audio_be_set_volume_out_lr(st->state->audio_be, st->voice.out, mut= ed, left, right); } else { - AUD_set_volume_in_lr(st->state->audio_be, st->voice.in, muted, lef= t, right); + audio_be_set_volume_in_lr(st->state->audio_be, st->voice.in, muted= , left, right); } } =20 @@ -491,7 +491,7 @@ static void hda_audio_setup(HDAAudioStream *st) } else { cb =3D hda_audio_compat_output_cb; } - st->voice.out =3D AUD_open_out(st->state->audio_be, st->voice.out, + st->voice.out =3D audio_be_open_out(st->state->audio_be, st->voice= .out, st->node->name, st, cb, &st->as); } else { if (use_timer) { @@ -500,7 +500,7 @@ static void hda_audio_setup(HDAAudioStream *st) } else { cb =3D hda_audio_compat_input_cb; } - st->voice.in =3D AUD_open_in(st->state->audio_be, st->voice.in, + st->voice.in =3D audio_be_open_in(st->state->audio_be, st->voice.i= n, st->node->name, st, cb, &st->as); } } @@ -696,7 +696,7 @@ static void hda_audio_init(HDACodecDevice *hda, const desc_param *param; uint32_t i, type; =20 - if (!AUD_backend_check(&a->audio_be, errp)) { + if (!audio_be_backend_check(&a->audio_be, errp)) { return; } =20 @@ -754,9 +754,9 @@ static void hda_audio_exit(HDACodecDevice *hda) } timer_free(st->buft); if (st->output) { - AUD_close_out(a->audio_be, st->voice.out); + audio_be_close_out(a->audio_be, st->voice.out); } else { - AUD_close_in(a->audio_be, st->voice.in); + audio_be_close_in(a->audio_be, st->voice.in); } } } diff --git a/hw/audio/lm4549.c b/hw/audio/lm4549.c index 4adf67f967..68ee5bdfa9 100644 --- a/hw/audio/lm4549.c +++ b/hw/audio/lm4549.c @@ -101,11 +101,11 @@ static void lm4549_audio_transfer(lm4549_state *s) uint32_t i; =20 /* Activate the voice */ - AUD_set_active_out(s->audio_be, s->voice, 1); + audio_be_set_active_out(s->audio_be, s->voice, 1); s->voice_is_active =3D 1; =20 /* Try to write the buffer content */ - written_bytes =3D AUD_write(s->audio_be, s->voice, s->buffer, + written_bytes =3D audio_be_write(s->audio_be, s->voice, s->buffer, s->buffer_level * sizeof(uint16_t)); written_samples =3D written_bytes >> 1; =20 @@ -129,14 +129,14 @@ static void lm4549_audio_out_callback(void *opaque, i= nt free) static uint32_t prev_buffer_level; =20 #ifdef LM4549_DEBUG - int size =3D AUD_get_buffer_size_out(s->audio_be, s->voice); + int size =3D audio_be_get_buffer_size_out(s->audio_be, s->voice); DPRINTF("audio_out_callback size =3D %i free =3D %i\n", size, free); #endif =20 /* Detect that no data are consumed =3D> disable the voice */ if (s->buffer_level =3D=3D prev_buffer_level) { - AUD_set_active_out(s->audio_be, s->voice, 0); + audio_be_set_active_out(s->audio_be, s->voice, 0); s->voice_is_active =3D 0; } prev_buffer_level =3D s->buffer_level; @@ -204,7 +204,7 @@ void lm4549_write(lm4549_state *s, as.fmt =3D AUDIO_FORMAT_S16; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "lm4549.out", @@ -274,7 +274,7 @@ static int lm4549_post_load(void *opaque, int version_i= d) as.fmt =3D AUDIO_FORMAT_S16; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "lm4549.out", @@ -285,7 +285,7 @@ static int lm4549_post_load(void *opaque, int version_i= d) =20 /* Request data */ if (s->voice_is_active =3D=3D 1) { - lm4549_audio_out_callback(s, AUD_get_buffer_size_out(s->audio_be, = s->voice)); + lm4549_audio_out_callback(s, audio_be_get_buffer_size_out(s->audio= _be, s->voice)); } =20 return 0; @@ -297,7 +297,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_= req_cb, void* opaque, struct audsettings as; =20 /* Register an audio card */ - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -314,7 +314,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_= req_cb, void* opaque, as.fmt =3D AUDIO_FORMAT_S16; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "lm4549.out", @@ -323,7 +323,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_= req_cb, void* opaque, &as ); =20 - AUD_set_volume_out_lr(s->audio_be, s->voice, 0, 255, 255); + audio_be_set_volume_out_lr(s->audio_be, s->voice, 0, 255, 255); =20 s->voice_is_active =3D 0; =20 diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index a74a263b37..1787fc2bc5 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -106,7 +106,7 @@ static void pcspk_callback(void *opaque, int free) =20 while (free > 0) { n =3D MIN(s->samples - s->play_pos, (unsigned int)free); - n =3D AUD_write(s->audio_be, s->voice, &s->sample_buf[s->play_pos]= , n); + n =3D audio_be_write(s->audio_be, s->voice, &s->sample_buf[s->play= _pos], n); if (!n) break; s->play_pos =3D (s->play_pos + n) % s->samples; @@ -123,7 +123,7 @@ static int pcspk_audio_init(PCSpkState *s) return 0; } =20 - s->voice =3D AUD_open_out(s->audio_be, s->voice, s_spk, s, pcspk_callb= ack, &as); + s->voice =3D audio_be_open_out(s->audio_be, s->voice, s_spk, s, pcspk_= callback, &as); if (!s->voice) { error_report("pcspk: Could not open voice"); return -1; @@ -164,7 +164,7 @@ static void pcspk_io_write(void *opaque, hwaddr addr, u= int64_t val, if (s->voice) { if (gate) /* restart */ s->play_pos =3D 0; - AUD_set_active_out(s->audio_be, s->voice, gate & s->data_on); + audio_be_set_active_out(s->audio_be, s->voice, gate & s->data_on); } } =20 @@ -196,7 +196,7 @@ static void pcspk_realizefn(DeviceState *dev, Error **e= rrp) =20 isa_register_ioport(isadev, &s->ioport, s->iobase); =20 - if (s->audio_be && AUD_backend_check(&s->audio_be, errp)) { + if (s->audio_be && audio_be_backend_check(&s->audio_be, errp)) { pcspk_audio_init(s); return; } diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 47b36dfc69..270f2075c9 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -171,7 +171,7 @@ static void log_dsp (SB16State *dsp) static void speaker (SB16State *s, int on) { s->speaker =3D on; - /* AUD_enable (s->voice, on); */ + /* audio_be_enable (s->voice, on); */ } =20 static void control (SB16State *s, int hold) @@ -185,11 +185,11 @@ static void control (SB16State *s, int hold) =20 if (hold) { k->hold_DREQ(isa_dma, dma); - AUD_set_active_out(s->audio_be, s->voice, 1); + audio_be_set_active_out(s->audio_be, s->voice, 1); } else { k->release_DREQ(isa_dma, dma); - AUD_set_active_out(s->audio_be, s->voice, 0); + audio_be_set_active_out(s->audio_be, s->voice, 0); } } =20 @@ -215,7 +215,7 @@ static void continue_dma8 (SB16State *s) as.fmt =3D s->fmt; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "sb16", @@ -378,7 +378,7 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t= d0, int dma_len) as.fmt =3D s->fmt; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "sb16", @@ -879,7 +879,7 @@ static void legacy_reset (SB16State *s) as.fmt =3D AUDIO_FORMAT_U8; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "sb16", @@ -889,7 +889,7 @@ static void legacy_reset (SB16State *s) ); =20 /* Not sure about that... */ - /* AUD_set_active_out (s->voice, 1); */ + /* audio_be_set_active_out (s->voice, 1); */ } =20 static void reset (SB16State *s) @@ -1196,7 +1196,7 @@ static int write_audio (SB16State *s, int nchan, int = dma_pos, } =20 copied =3D k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy= ); - copied =3D AUD_write(s->audio_be, s->voice, tmpbuf, copied); + copied =3D audio_be_write(s->audio_be, s->voice, tmpbuf, copied); =20 temp -=3D copied; dma_pos =3D (dma_pos + copied) % dma_len; @@ -1287,7 +1287,7 @@ static int sb16_post_load (void *opaque, int version_= id) SB16State *s =3D opaque; =20 if (s->voice) { - AUD_close_out(s->audio_be, s->voice); + audio_be_close_out(s->audio_be, s->voice); s->voice =3D NULL; } =20 @@ -1302,7 +1302,7 @@ static int sb16_post_load (void *opaque, int version_= id) as.fmt =3D s->fmt; as.endianness =3D 0; =20 - s->voice =3D AUD_open_out( + s->voice =3D audio_be_open_out( s->audio_be, s->voice, "sb16", @@ -1401,7 +1401,7 @@ static void sb16_realizefn (DeviceState *dev, Error *= *errp) SB16State *s =3D SB16 (dev); IsaDmaClass *k; =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c index 5b344d7a0f..c189322566 100644 --- a/hw/audio/via-ac97.c +++ b/hw/audio/via-ac97.c @@ -53,7 +53,7 @@ static void codec_volume_set_out(ViaAC97State *s) rvol /=3D 255; mute =3D CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT; mute |=3D CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> MUTE_SHIFT; - AUD_set_volume_out_lr(s->audio_be, s->vo, mute, lvol, rvol); + audio_be_set_volume_out_lr(s->audio_be, s->vo, mute, lvol, rvol); } =20 static void codec_reset(ViaAC97State *s) @@ -189,7 +189,7 @@ static void out_cb(void *opaque, int avail) while (temp) { to_copy =3D MIN(temp, sizeof(tmpbuf)); pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy); - copied =3D AUD_write(s->audio_be, s->vo, tmpbuf, to_copy); + copied =3D audio_be_write(s->audio_be, s->vo, tmpbuf, to_copy); if (!copied) { stop =3D true; break; @@ -208,7 +208,7 @@ static void out_cb(void *opaque, int avail) c->stat |=3D STAT_PAUSED; } else { c->stat &=3D ~STAT_ACTIVE; - AUD_set_active_out(s->audio_be, s->vo, 0); + audio_be_set_active_out(s->audio_be, s->vo, 0); } if (c->type & STAT_EOL) { via_isa_set_irq(&s->dev, 0, 1); @@ -239,7 +239,7 @@ static void open_voice_out(ViaAC97State *s) .fmt =3D s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8, .endianness =3D 0, }; - s->vo =3D AUD_open_out(s->audio_be, s->vo, "via-ac97.out", s, out_cb, = &as); + s->vo =3D audio_be_open_out(s->audio_be, s->vo, "via-ac97.out", s, out= _cb, &as); } =20 static uint64_t sgd_read(void *opaque, hwaddr addr, unsigned size) @@ -317,20 +317,20 @@ static void sgd_write(void *opaque, hwaddr addr, uint= 64_t val, unsigned size) break; case 1: if (val & CNTL_START) { - AUD_set_active_out(s->audio_be, s->vo, 1); + audio_be_set_active_out(s->audio_be, s->vo, 1); s->aur.stat =3D STAT_ACTIVE; } if (val & CNTL_TERM) { - AUD_set_active_out(s->audio_be, s->vo, 0); + audio_be_set_active_out(s->audio_be, s->vo, 0); s->aur.stat &=3D ~(STAT_ACTIVE | STAT_PAUSED); s->aur.clen =3D 0; } if (val & CNTL_PAUSE) { - AUD_set_active_out(s->audio_be, s->vo, 0); + audio_be_set_active_out(s->audio_be, s->vo, 0); s->aur.stat &=3D ~STAT_ACTIVE; s->aur.stat |=3D STAT_PAUSED; } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) { - AUD_set_active_out(s->audio_be, s->vo, 1); + audio_be_set_active_out(s->audio_be, s->vo, 1); s->aur.stat |=3D STAT_ACTIVE; s->aur.stat &=3D ~STAT_PAUSED; } @@ -426,7 +426,7 @@ static void via_ac97_realize(PCIDevice *pci_dev, Error = **errp) ViaAC97State *s =3D VIA_AC97(pci_dev); Object *o =3D OBJECT(s); =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -455,7 +455,7 @@ static void via_ac97_exit(PCIDevice *dev) { ViaAC97State *s =3D VIA_AC97(dev); =20 - AUD_close_out(s->audio_be, s->vo); + audio_be_close_out(s->audio_be, s->vo); } =20 static const Property via_ac97_properties[] =3D { diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 47fef61af8..19eab3a353 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -391,10 +391,10 @@ static void virtio_snd_pcm_close(VirtIOSoundPCMStream= *stream) if (stream) { virtio_snd_pcm_flush(stream); if (stream->info.direction =3D=3D VIRTIO_SND_D_OUTPUT) { - AUD_close_out(stream->pcm->snd->audio_be, stream->voice.out); + audio_be_close_out(stream->pcm->snd->audio_be, stream->voice.o= ut); stream->voice.out =3D NULL; } else if (stream->info.direction =3D=3D VIRTIO_SND_D_INPUT) { - AUD_close_in(stream->pcm->snd->audio_be, stream->voice.in); + audio_be_close_in(stream->pcm->snd->audio_be, stream->voice.in= ); stream->voice.in =3D NULL; } } @@ -457,21 +457,21 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s= , uint32_t stream_id) stream->as =3D as; =20 if (stream->info.direction =3D=3D VIRTIO_SND_D_OUTPUT) { - stream->voice.out =3D AUD_open_out(s->audio_be, + stream->voice.out =3D audio_be_open_out(s->audio_be, stream->voice.out, "virtio-sound.out", stream, virtio_snd_pcm_out_cb, &as); - AUD_set_volume_out_lr(s->audio_be, stream->voice.out, 0, 255, 255); + audio_be_set_volume_out_lr(s->audio_be, stream->voice.out, 0, 255,= 255); } else { - stream->voice.in =3D AUD_open_in(s->audio_be, + stream->voice.in =3D audio_be_open_in(s->audio_be, stream->voice.in, "virtio-sound.in", stream, virtio_snd_pcm_in_cb, &as); - AUD_set_volume_in_lr(s->audio_be, stream->voice.in, 0, 255, 255); + audio_be_set_volume_in_lr(s->audio_be, stream->voice.in, 0, 255, 2= 55); } =20 return cpu_to_le32(VIRTIO_SND_S_OK); @@ -561,9 +561,9 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSoun= d *s, stream->active =3D start; } if (stream->info.direction =3D=3D VIRTIO_SND_D_OUTPUT) { - AUD_set_active_out(s->audio_be, stream->voice.out, start); + audio_be_set_active_out(s->audio_be, stream->voice.out, start); } else { - AUD_set_active_in(s->audio_be, stream->voice.in, start); + audio_be_set_active_in(s->audio_be, stream->voice.in, start); } } else { error_report("Invalid stream id: %"PRIu32, stream_id); @@ -1053,7 +1053,7 @@ static void virtio_snd_realize(DeviceState *dev, Erro= r **errp) return; } =20 - if (!AUD_backend_check(&vsnd->audio_be, errp)) { + if (!audio_be_backend_check(&vsnd->audio_be, errp)) { return; } =20 @@ -1135,10 +1135,10 @@ static inline void return_tx_buffer(VirtIOSoundPCMS= tream *stream, } =20 /* - * AUD_* output callback. + * audio_be_* output callback. * * @data: VirtIOSoundPCMStream stream - * @available: number of bytes that can be written with AUD_write() + * @available: number of bytes that can be written with audio_be_write() */ static void virtio_snd_pcm_out_cb(void *data, int available) { @@ -1153,7 +1153,7 @@ static void virtio_snd_pcm_out_cb(void *data, int ava= ilable) return; } if (!stream->active) { - /* Stream has stopped, so do not perform AUD_write. */ + /* Stream has stopped, so do not perform audio_be_write. */ return_tx_buffer(stream, buffer); continue; } @@ -1166,7 +1166,7 @@ static void virtio_snd_pcm_out_cb(void *data, int ava= ilable) buffer->populated =3D true; } for (;;) { - size =3D AUD_write(stream->s->audio_be, + size =3D audio_be_write(stream->s->audio_be, stream->voice.out, buffer->data + buffer->offset, MIN(buffer->size, available)); @@ -1230,10 +1230,10 @@ static inline void return_rx_buffer(VirtIOSoundPCMS= tream *stream, =20 =20 /* - * AUD_* input callback. + * audio_be_* input callback. * * @data: VirtIOSoundPCMStream stream - * @available: number of bytes that can be read with AUD_read() + * @available: number of bytes that can be read with audio_be_read() */ static void virtio_snd_pcm_in_cb(void *data, int available) { @@ -1248,7 +1248,7 @@ static void virtio_snd_pcm_in_cb(void *data, int avai= lable) return; } if (!stream->active) { - /* Stream has stopped, so do not perform AUD_read. */ + /* Stream has stopped, so do not perform audio_be_read. */ return_rx_buffer(stream, buffer); continue; } @@ -1259,7 +1259,7 @@ static void virtio_snd_pcm_in_cb(void *data, int avai= lable) return_rx_buffer(stream, buffer); break; } - size =3D AUD_read(stream->s->audio_be, + size =3D audio_be_read(stream->s->audio_be, stream->voice.in, buffer->data + buffer->size, MIN(available, (stream->params.period_bytes - diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index bc347fe537..ee6a212b1f 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -72,7 +72,7 @@ static inline void wm8750_in_load(WM8750State *s) if (s->idx_in + s->req_in <=3D sizeof(s->data_in)) return; s->idx_in =3D MAX(0, (int) sizeof(s->data_in) - s->req_in); - AUD_read(s->audio_be, *s->in[0], s->data_in + s->idx_in, + audio_be_read(s->audio_be, *s->in[0], s->data_in + s->idx_in, sizeof(s->data_in) - s->idx_in); } =20 @@ -80,7 +80,7 @@ static inline void wm8750_out_flush(WM8750State *s) { int sent =3D 0; while (sent < s->idx_out) - sent +=3D AUD_write(s->audio_be, *s->out[0], s->data_out + sent, s= ->idx_out - sent) + sent +=3D audio_be_write(s->audio_be, *s->out[0], s->data_out + se= nt, s->idx_out - sent) ?: s->idx_out; s->idx_out =3D 0; } @@ -145,30 +145,30 @@ static void wm8750_vol_update(WM8750State *s) { /* FIXME: multiply all volumes by s->invol[2], s->invol[3] */ =20 - AUD_set_volume_in_lr(s->audio_be, s->adc_voice[0], s->mute, + audio_be_set_volume_in_lr(s->audio_be, s->adc_voice[0], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])= ); - AUD_set_volume_in_lr(s->audio_be, s->adc_voice[1], s->mute, + audio_be_set_volume_in_lr(s->audio_be, s->adc_voice[1], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])= ); - AUD_set_volume_in_lr(s->audio_be, s->adc_voice[2], s->mute, + audio_be_set_volume_in_lr(s->audio_be, s->adc_voice[2], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])= ); =20 /* FIXME: multiply all volumes by s->outvol[0], s->outvol[1] */ =20 /* Speaker: LOUT2VOL ROUT2VOL */ - AUD_set_volume_out_lr(s->audio_be, s->dac_voice[0], s->mute, + audio_be_set_volume_out_lr(s->audio_be, s->dac_voice[0], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 4]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 5])); =20 /* Headphone: LOUT1VOL ROUT1VOL */ - AUD_set_volume_out_lr(s->audio_be, s->dac_voice[1], s->mute, + audio_be_set_volume_out_lr(s->audio_be, s->dac_voice[1], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 2]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 3])); =20 /* MONOOUT: MONOVOL MONOVOL */ - AUD_set_volume_out_lr(s->audio_be, s->dac_voice[2], s->mute, + audio_be_set_volume_out_lr(s->audio_be, s->dac_voice[2], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 6]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[= 6])); } @@ -182,18 +182,18 @@ static void wm8750_set_format(WM8750State *s) wm8750_out_flush(s); =20 if (s->in[0] && *s->in[0]) - AUD_set_active_in(s->audio_be, *s->in[0], 0); + audio_be_set_active_in(s->audio_be, *s->in[0], 0); if (s->out[0] && *s->out[0]) - AUD_set_active_out(s->audio_be, *s->out[0], 0); + audio_be_set_active_out(s->audio_be, *s->out[0], 0); =20 for (i =3D 0; i < IN_PORT_N; i ++) if (s->adc_voice[i]) { - AUD_close_in(s->audio_be, s->adc_voice[i]); + audio_be_close_in(s->audio_be, s->adc_voice[i]); s->adc_voice[i] =3D NULL; } for (i =3D 0; i < OUT_PORT_N; i ++) if (s->dac_voice[i]) { - AUD_close_out(s->audio_be, s->dac_voice[i]); + audio_be_close_out(s->audio_be, s->dac_voice[i]); s->dac_voice[i] =3D NULL; } =20 @@ -206,11 +206,11 @@ static void wm8750_set_format(WM8750State *s) in_fmt.freq =3D s->adc_hz; in_fmt.fmt =3D AUDIO_FORMAT_S16; =20 - s->adc_voice[0] =3D AUD_open_in(s->audio_be, s->adc_voice[0], + s->adc_voice[0] =3D audio_be_open_in(s->audio_be, s->adc_voice[0], CODEC ".input1", s, wm8750_audio_in_cb, &in_fmt); - s->adc_voice[1] =3D AUD_open_in(s->audio_be, s->adc_voice[1], + s->adc_voice[1] =3D audio_be_open_in(s->audio_be, s->adc_voice[1], CODEC ".input2", s, wm8750_audio_in_cb, &in_fmt); - s->adc_voice[2] =3D AUD_open_in(s->audio_be, s->adc_voice[2], + s->adc_voice[2] =3D audio_be_open_in(s->audio_be, s->adc_voice[2], CODEC ".input3", s, wm8750_audio_in_cb, &in_fmt); =20 /* Setup output */ @@ -219,12 +219,12 @@ static void wm8750_set_format(WM8750State *s) out_fmt.freq =3D s->dac_hz; out_fmt.fmt =3D AUDIO_FORMAT_S16; =20 - s->dac_voice[0] =3D AUD_open_out(s->audio_be, s->dac_voice[0], + s->dac_voice[0] =3D audio_be_open_out(s->audio_be, s->dac_voice[0], CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt); - s->dac_voice[1] =3D AUD_open_out(s->audio_be, s->dac_voice[1], + s->dac_voice[1] =3D audio_be_open_out(s->audio_be, s->dac_voice[1], CODEC ".headphone", s, wm8750_audio_out_cb, &out_fmt); /* MONOMIX is also in stereo for simplicity */ - s->dac_voice[2] =3D AUD_open_out(s->audio_be, s->dac_voice[2], + s->dac_voice[2] =3D audio_be_open_out(s->audio_be, s->dac_voice[2], CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt); /* no sense emulating OUT3 which is a mix of other outputs */ =20 @@ -235,9 +235,9 @@ static void wm8750_set_format(WM8750State *s) * for mixing or combining paths to different ports, so we * connect both channels to where the left channel is routed. */ if (s->in[0] && *s->in[0]) - AUD_set_active_in(s->audio_be, *s->in[0], 1); + audio_be_set_active_in(s->audio_be, *s->in[0], 1); if (s->out[0] && *s->out[0]) - AUD_set_active_out(s->audio_be, *s->out[0], 1); + audio_be_set_active_out(s->audio_be, *s->out[0], 1); } =20 static void wm8750_clk_update(WM8750State *s, int ext) @@ -624,7 +624,7 @@ static void wm8750_realize(DeviceState *dev, Error **er= rp) { WM8750State *s =3D WM8750(dev); =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index e89f1ffaf6..0e6bd50c9d 100644 --- a/hw/display/xlnx_dp.c +++ b/hw/display/xlnx_dp.c @@ -331,7 +331,7 @@ static inline void xlnx_dp_audio_activate(XlnxDPState *= s) { bool activated =3D ((s->core_registers[DP_TX_AUDIO_CONTROL] & DP_TX_AUD_CTRL) !=3D 0); - AUD_set_active_out(s->audio_be, s->amixer_output_stream, activated); + audio_be_set_active_out(s->audio_be, s->amixer_output_stream, activate= d); xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(0), &s->audio_buffer_0); xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(1), @@ -401,7 +401,7 @@ static void xlnx_dp_audio_callback(void *opaque, int av= ail) /* Send the buffer through the audio. */ if (s->byte_left <=3D MAX_QEMU_BUFFER_SIZE) { if (s->byte_left !=3D 0) { - written =3D AUD_write(s->audio_be, s->amixer_output_stream, + written =3D audio_be_write(s->audio_be, s->amixer_output_strea= m, &s->out_buffer[s->data_ptr], s->byte_left); } else { int len_to_copy; @@ -413,12 +413,12 @@ static void xlnx_dp_audio_callback(void *opaque, int = avail) while (avail) { len_to_copy =3D MIN(AUD_CHBUF_MAX_DEPTH, avail); memset(s->out_buffer, 0, len_to_copy); - avail -=3D AUD_write(s->audio_be, s->amixer_output_stream,= s->out_buffer, + avail -=3D audio_be_write(s->audio_be, s->amixer_output_st= ream, s->out_buffer, len_to_copy); } } } else { - written =3D AUD_write(s->audio_be, s->amixer_output_stream, + written =3D audio_be_write(s->audio_be, s->amixer_output_stream, &s->out_buffer[s->data_ptr], MAX_QEMU_BUFFER_S= IZE); } s->byte_left -=3D written; @@ -1373,7 +1373,7 @@ static void xlnx_dp_realize(DeviceState *dev, Error *= *errp) DisplaySurface *surface; struct audsettings as; =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -1395,13 +1395,13 @@ static void xlnx_dp_realize(DeviceState *dev, Error= **errp) as.fmt =3D AUDIO_FORMAT_S16; as.endianness =3D 0; =20 - s->amixer_output_stream =3D AUD_open_out(s->audio_be, + s->amixer_output_stream =3D audio_be_open_out(s->audio_be, s->amixer_output_stream, "xlnx_dp.audio.out", s, xlnx_dp_audio_callback, &as); - AUD_set_volume_out_lr(s->audio_be, s->amixer_output_stream, 0, 255, 25= 5); + audio_be_set_volume_out_lr(s->audio_be, s->amixer_output_stream, 0, 25= 5, 255); xlnx_dp_audio_activate(s); s->vblank =3D ptimer_init(vblank_hit, s, DP_VBLANK_PTIMER_POLICY); ptimer_transaction_begin(s->vblank); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 189fd1df26..42aadcc4d8 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -669,7 +669,7 @@ static void output_callback(void *opaque, int avail) return; } =20 - written =3D AUD_write(s->audio_be, s->out.voice, data, len); + written =3D audio_be_write(s->audio_be, s->out.voice, data, len); avail -=3D written; s->out.buf.cons +=3D written; =20 @@ -683,7 +683,7 @@ static int usb_audio_set_output_altset(USBAudioState *s= , int altset) { switch (altset) { case ALTSET_OFF: - AUD_set_active_out(s->audio_be, s->out.voice, false); + audio_be_set_active_out(s->audio_be, s->out.voice, false); break; case ALTSET_STEREO: case ALTSET_51: @@ -692,7 +692,7 @@ static int usb_audio_set_output_altset(USBAudioState *s= , int altset) usb_audio_reinit(USB_DEVICE(s), altset_channels[altset]); } streambuf_init(&s->out.buf, s->buffer, s->out.channels); - AUD_set_active_out(s->audio_be, s->out.voice, true); + audio_be_set_active_out(s->audio_be, s->out.voice, true); break; default: return -1; @@ -805,7 +805,7 @@ static int usb_audio_set_control(USBAudioState *s, uint= 8_t attrib, } fprintf(stderr, "\n"); } - AUD_set_volume_out(s->audio_be, s->out.voice, &s->out.vol); + audio_be_set_volume_out(s->audio_be, s->out.voice, &s->out.vol); } =20 return ret; @@ -931,7 +931,7 @@ static void usb_audio_unrealize(USBDevice *dev) } =20 usb_audio_set_output_altset(s, ALTSET_OFF); - AUD_close_out(s->audio_be, s->out.voice); + audio_be_close_out(s->audio_be, s->out.voice); =20 streambuf_fini(&s->out.buf); } @@ -941,7 +941,7 @@ static void usb_audio_realize(USBDevice *dev, Error **e= rrp) USBAudioState *s =3D USB_AUDIO(dev); int i; =20 - if (!AUD_backend_check(&s->audio_be, errp)) { + if (!audio_be_backend_check(&s->audio_be, errp)) { return; } =20 @@ -978,10 +978,10 @@ static void usb_audio_reinit(USBDevice *dev, unsigned= channels) s->out.as.endianness =3D 0; streambuf_init(&s->out.buf, s->buffer, s->out.channels); =20 - s->out.voice =3D AUD_open_out(s->audio_be, s->out.voice, TYPE_USB_AUDI= O, + s->out.voice =3D audio_be_open_out(s->audio_be, s->out.voice, TYPE_USB= _AUDIO, s, output_callback, &s->out.as); - AUD_set_volume_out(s->audio_be, s->out.voice, &s->out.vol); - AUD_set_active_out(s->audio_be, s->out.voice, 0); + audio_be_set_volume_out(s->audio_be, s->out.voice, &s->out.vol); + audio_be_set_active_out(s->audio_be, s->out.voice, 0); } =20 static const VMStateDescription vmstate_usb_audio =3D { diff --git a/ui/vnc.c b/ui/vnc.c index 5c8af65202..ee337d729a 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1277,7 +1277,7 @@ static void audio_add(VncState *vs) ops.destroy =3D audio_capture_destroy; ops.capture =3D audio_capture; =20 - vs->audio_cap =3D AUD_add_capture(vs->vd->audio_be, &vs->as, &ops, vs); + vs->audio_cap =3D audio_be_add_capture(vs->vd->audio_be, &vs->as, &ops= , vs); if (!vs->audio_cap) { error_report("Failed to add audio capture"); } @@ -1286,7 +1286,7 @@ static void audio_add(VncState *vs) static void audio_del(VncState *vs) { if (vs->audio_cap) { - AUD_del_capture(vs->vd->audio_be, vs->audio_cap, vs); + audio_be_del_capture(vs->vd->audio_be, vs->audio_cap, vs); vs->audio_cap =3D NULL; } } --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588406; cv=none; d=zohomail.com; s=zohoarc; b=h1AqZjwGgYug3zPZOUtWJDLi2e5kvl0SZujF/hMpa4d5a4J7c5DbCPchwgvWvw9jlBqxLQqAfDkcQPhACgX7T9c9lkgJT1CI2c/i61ceRJeb5c6aKEz7iRgvjODi39/rCjHg5udI/JmeFWdhlzDZcix0mI6DapNuwz3PPCwT8w0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588406; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=EskV75Y54e3E5/mGlU6jvEyk2qKozy/nvG/DNwjyCUI=; b=X8GtOzY8V+MtujNiLq9PrdVgkj+Lr6Y2fS1+YVEoZ1hAZdbdSt6ZDsfafvJ1bLX4yahFcNzrOdV5jq/uqW97hZQt9ewGks03S9u5sXOaKXTWbJw0Zz/2lCl5UfuI5HFu32zPBXwGbAD9lm5gV/UHkPPh8fGIMMZqKX2h6cSlu9A= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588406936560.7726763143473; Mon, 1 Dec 2025 03:26:46 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22T-0005S2-87; Mon, 01 Dec 2025 06:25:53 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22L-0004xf-FZ for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:46 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22H-00072q-G0 for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:44 -0500 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-641-VGH5BHtgOvq3gKnbbXERaQ-1; Mon, 01 Dec 2025 06:25:37 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2765C195608F; Mon, 1 Dec 2025 11:25:36 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9831D180057F; Mon, 1 Dec 2025 11:25:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588340; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EskV75Y54e3E5/mGlU6jvEyk2qKozy/nvG/DNwjyCUI=; b=WDeSSHd+DiP+Yksqc2MfaRpBFyWZm8Y+U1P8wX1/CekX7d7JtwPkAoufb+Em1Y36dh5Vbh pq6IZJwwAfAIbXO9cxTwnjrpdIup21LIcsbrVy4Z4px4C72Kb6BQgprUavI20ZsnsK6jG5 lR6PlPYdQ37F6oWA+/bQeqnPqEtKZOA= X-MC-Unique: VGH5BHtgOvq3gKnbbXERaQ-1 X-Mimecast-MFC-AGG-ID: VGH5BHtgOvq3gKnbbXERaQ_1764588336 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 21/24] audio-be: add common pre-conditions Date: Mon, 1 Dec 2025 15:23:02 +0400 Message-ID: <20251201112309.4163921-22-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588408197019200 From: Marc-Andr=C3=A9 Lureau assert() on valid values, and handle acceptable NULL arguments gracefully. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio-be.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/audio/audio-be.c b/audio/audio-be.c index 9af4dbe5e9..fde9c20e12 100644 --- a/audio/audio-be.c +++ b/audio/audio-be.c @@ -29,6 +29,10 @@ SWVoiceIn *audio_be_open_in( { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + assert(name !=3D NULL); + assert(callback_fn !=3D NULL); + assert(as !=3D NULL); + return klass->open_in(be, sw, name, callback_opaque, callback_fn, as); } =20 @@ -42,6 +46,10 @@ SWVoiceOut *audio_be_open_out( { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + assert(name !=3D NULL); + assert(callback_fn !=3D NULL); + assert(as !=3D NULL); + return klass->open_out(be, sw, name, callback_opaque, callback_fn, as); } =20 @@ -49,6 +57,10 @@ void audio_be_close_out(AudioBackend *be, SWVoiceOut *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return; + } + return klass->close_out(be, sw); } =20 @@ -56,6 +68,10 @@ void audio_be_close_in(AudioBackend *be, SWVoiceIn *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return; + } + return klass->close_in(be, sw); } =20 @@ -63,6 +79,10 @@ bool audio_be_is_active_out(AudioBackend *be, SWVoiceOut= *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return false; + } + return klass->is_active_out(be, sw); } =20 @@ -70,6 +90,10 @@ bool audio_be_is_active_in(AudioBackend *be, SWVoiceIn *= sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return false; + } + return klass->is_active_in(be, sw); } =20 @@ -77,6 +101,10 @@ size_t audio_be_write(AudioBackend *be, SWVoiceOut *sw,= void *buf, size_t size) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return 0; + } + return klass->write(be, sw, buf, size); } =20 @@ -84,6 +112,10 @@ size_t audio_be_read(AudioBackend *be, SWVoiceIn *sw, v= oid *buf, size_t size) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return 0; + } + return klass->read(be, sw, buf, size); } =20 @@ -91,6 +123,10 @@ int audio_be_get_buffer_size_out(AudioBackend *be, SWVo= iceOut *sw) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return 0; + } + return klass->get_buffer_size_out(be, sw); } =20 @@ -98,6 +134,10 @@ void audio_be_set_active_out(AudioBackend *be, SWVoiceO= ut *sw, bool on) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return; + } + return klass->set_active_out(be, sw, on); } =20 @@ -105,6 +145,10 @@ void audio_be_set_active_in(AudioBackend *be, SWVoiceI= n *sw, bool on) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return; + } + return klass->set_active_in(be, sw, on); } =20 @@ -112,6 +156,10 @@ void audio_be_set_volume_out(AudioBackend *be, SWVoice= Out *sw, Volume *vol) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return; + } + klass->set_volume_out(be, sw, vol); } =20 @@ -119,6 +167,10 @@ void audio_be_set_volume_in(AudioBackend *be, SWVoiceI= n *sw, Volume *vol) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!sw) { + return; + } + klass->set_volume_in(be, sw, vol); } =20 @@ -130,6 +182,9 @@ CaptureVoiceOut *audio_be_add_capture( { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + assert(as !=3D NULL); + assert(ops !=3D NULL); + return klass->add_capture(be, as, ops, cb_opaque); } =20 @@ -137,6 +192,10 @@ void audio_be_del_capture(AudioBackend *be, CaptureVoi= ceOut *cap, void *cb_opaqu { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + if (!cap) { + return; + } + klass->del_capture(be, cap, cb_opaque); } =20 @@ -155,6 +214,8 @@ bool audio_be_set_dbus_server(AudioBackend *be, { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + assert(server !=3D NULL); + if (!audio_be_can_set_dbus_server(be)) { error_setg(errp, "Audiodev '%s' is not compatible with DBus", audio_be_get_id(be)); --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588377; cv=none; d=zohomail.com; s=zohoarc; b=UvLTglz71MAv+XEZ9AZIvY3d2cskXcxYQ8Gy8IaWo0QewLyvNqHNDZyW7PHMtlr23si1DX9NsTAlGucc6ruv//hOFLAMKufsVsO7CMSO1UAPrx+PdrGHAlAeNeTrT9WfEOb9x8Qy6dPSIGb/DSzazalYrh0CkpgmzMaIi43lWJM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588377; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ZyvGm2cHLXm+YFmwtjHyM7NXD0+QEkLy407SaQIYwGQ=; b=YG3XJRo8o38zKvAnF9jEgux1uhOZs2b1jWJ9JYtwnp9KghHgDPlSIMhdkUreXvzlHwojLR8h8J1b+PCG5OhxT901wpAzYCMV4Z0PzV7+lxQ8PJOiMWNcge+D1oSwBL4D1CtzE3gUWVZzUvfF9vqL/F8N5pAUb3d0//AGOeLA6sI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588377190248.48443883728214; Mon, 1 Dec 2025 03:26:17 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22X-0005mV-IQ; Mon, 01 Dec 2025 06:25:57 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22P-0005Hs-6r for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:50 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22M-00074H-Vv for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:48 -0500 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-629-aUkngF9NPFKIjMNOOEs4Fg-1; Mon, 01 Dec 2025 06:25:43 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0FE591956053; Mon, 1 Dec 2025 11:25:42 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9304118004A3; Mon, 1 Dec 2025 11:25:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588345; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZyvGm2cHLXm+YFmwtjHyM7NXD0+QEkLy407SaQIYwGQ=; b=MKYaAnBPAp9q0t7y06oTj8GQsAzeW6xx/s0oT5cMwKAfQzOUMiQ2DIPjOlYhJbKF8I0BLt ujCWIyr30bCDDU18fLnuiLMA5LpVezWYRR1Um5NQ5YdsLYLFQxasswTgHAV9Me0jr4AHEj /br5g4ePSC5pV41Bh2TenPAFo85YoL0= X-MC-Unique: aUkngF9NPFKIjMNOOEs4Fg-1 X-Mimecast-MFC-AGG-ID: aUkngF9NPFKIjMNOOEs4Fg_1764588342 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 22/24] audio-be: add some state trace Date: Mon, 1 Dec 2025 15:23:03 +0400 Message-ID: <20251201112309.4163921-23-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588379682019200 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio-be.c | 9 +++++++-- audio/trace-events | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/audio/audio-be.c b/audio/audio-be.c index fde9c20e12..7b141566bc 100644 --- a/audio/audio-be.c +++ b/audio/audio-be.c @@ -1,9 +1,10 @@ /* SPDX-License-Identifier: MIT */ =20 #include "qemu/osdep.h" -#include "qemu/audio.h" -#include "qemu/audio-capture.h" #include "qapi/error.h" +#include "qemu/audio-capture.h" +#include "qemu/audio.h" +#include "trace-audio.h" =20 bool audio_be_backend_check(AudioBackend **be, Error **errp) { @@ -134,6 +135,8 @@ void audio_be_set_active_out(AudioBackend *be, SWVoiceO= ut *sw, bool on) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + trace_audio_be_set_active_out(sw, on); + if (!sw) { return; } @@ -145,6 +148,8 @@ void audio_be_set_active_in(AudioBackend *be, SWVoiceIn= *sw, bool on) { AudioBackendClass *klass =3D AUDIO_BACKEND_GET_CLASS(be); =20 + trace_audio_be_set_active_in(sw, on); + if (!sw) { return; } diff --git a/audio/trace-events b/audio/trace-events index 7e3f1593c8..f7f639d960 100644 --- a/audio/trace-events +++ b/audio/trace-events @@ -26,6 +26,10 @@ pw_vol(const char *ret) "set volume: %s" pw_period(uint64_t quantum, uint32_t rate) "period =3D%" PRIu64 "/%u" pw_audio_init(void) "Initialize PipeWire context" =20 +# audio-be.c +audio_be_set_active_in(void *sw, bool on) "sw=3D%p, on=3D%d" +audio_be_set_active_out(void *sw, bool on) "sw=3D%p, on=3D%d" + # audio.c audio_timer_start(int interval) "interval %d ms" audio_timer_stop(void) "" --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588400; cv=none; d=zohomail.com; s=zohoarc; b=N0nf0MOQfBGPWQEa4sFmhjuInla40rb10wH/oP4nzRm7QULdCIGM1DCQP4F7NYtVKxndtFqiN9ImjyPHIi7tL+7SNs2Jawh+IzvMSzStDbzxcUTgaXXtyI602jOeZlXCZPryNFV4M5/ta38ICIl2KFUv+fGsWN857ggPdbADP1k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588400; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=IhMu2FMCV4qYVg7a8eiNYI95RM1ZIdwW5Rbv6pgjAPs=; b=Mczlq/vJYjlgTu8tHfwjot7XWhSWCENyeIA2mbua0CG9GNHmWEVKaPXFbGcjjZB9YGo2aRXo4bxKSV6i9Mq3Vi8q5TEOZWQXeguBjuy4jFi5S2bHTMGJfwq5QkYcPPd5FNLQBoMa6XG7AdfMvrVjcuzjKPKeLm12hdrA+KxnOaQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588400061807.5682254956072; Mon, 1 Dec 2025 03:26:40 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22d-0006gE-1T; Mon, 01 Dec 2025 06:26:03 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22a-0006HI-0X for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:26:00 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22U-00075p-8n for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:25:58 -0500 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-171-CJCtJLvpORWpSOsN4623CQ-1; Mon, 01 Dec 2025 06:25:51 -0500 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2E64A1800576; Mon, 1 Dec 2025 11:25:50 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CF352195608E; Mon, 1 Dec 2025 11:25:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588353; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IhMu2FMCV4qYVg7a8eiNYI95RM1ZIdwW5Rbv6pgjAPs=; b=buwrxy7WBqA4GYoUX3LH4fEPcZFccJ7qokt+X+7Pku2x/xdIGWhc45AyqxWSINfZqrpn5o tiUhbXdEPnI0/rm1qyPUajxGuDOZCKe1+9MGaQYCXOBeANZxNu/qqybNnq5iTLagZ9zLR8 790dYV0MTipbDWUc3uWNJQ3Oq6Pd6sk= X-MC-Unique: CJCtJLvpORWpSOsN4623CQ-1 X-Mimecast-MFC-AGG-ID: CJCtJLvpORWpSOsN4623CQ_1764588350 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [RFC 23/24] audio: split AudioDriver code in audio-driver.c Date: Mon, 1 Dec 2025 15:23:04 +0400 Message-ID: <20251201112309.4163921-24-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588403245019200 From: Marc-Andr=C3=A9 Lureau Allow to build the audio base infra without the rest of QEMU resampling/mixing/queuing code. Signed-off-by: Marc-Andr=C3=A9 Lureau --- ...dio_template.h =3D> audio-driver_template.h} | 0 audio/audio_int.h | 2 - include/qemu/audio.h | 2 + audio/audio-driver.c | 1988 +++++++++++++++ audio/audio.c | 2218 ++--------------- audio/meson.build | 1 + 6 files changed, 2167 insertions(+), 2044 deletions(-) rename audio/{audio_template.h =3D> audio-driver_template.h} (100%) create mode 100644 audio/audio-driver.c diff --git a/audio/audio_template.h b/audio/audio-driver_template.h similarity index 100% rename from audio/audio_template.h rename to audio/audio-driver_template.h diff --git a/audio/audio_int.h b/audio/audio_int.h index 79e54fd60a..e19ca96b01 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -273,8 +273,6 @@ int audio_bug (const char *funcname, int cond); =20 void audio_run(AudioDriver *s, const char *msg); =20 -const char *audio_application_name(void); - typedef struct RateCtl { int64_t start_ticks; int64_t bytes_sent; diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 1794702c30..414dd89f9c 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -188,6 +188,8 @@ bool audio_be_set_dbus_server(AudioBackend *be, Error **errp); #endif =20 +const char *audio_application_name(void); + #define DEFINE_AUDIO_PROPERTIES(_s, _f) \ DEFINE_PROP_AUDIODEV("audiodev", _s, _f) =20 diff --git a/audio/audio-driver.c b/audio/audio-driver.c new file mode 100644 index 0000000000..65e2bf2f38 --- /dev/null +++ b/audio/audio-driver.c @@ -0,0 +1,1988 @@ +/* + * QEMU Audio subsystem + * + * Copyright (c) 2003-2005 Vassili Karpov (malc) + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/audio.h" +#include "migration/vmstate.h" +#include "qemu/timer.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qom/object.h" +#include "system/replay.h" +#include "system/runstate.h" +#include "trace.h" + +#define AUDIO_CAP "audio" +#include "audio_int.h" + +/* #define DEBUG_LIVE */ +/* #define DEBUG_OUT */ +/* #define DEBUG_CAPTURE */ +/* #define DEBUG_POLL */ + +#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown" + + +const struct mixeng_volume nominal_volume =3D { + .mute =3D 0, +#ifdef FLOAT_MIXENG + .r =3D 1.0, + .l =3D 1.0, +#else + .r =3D 1ULL << 32, + .l =3D 1ULL << 32, +#endif +}; + +int audio_bug (const char *funcname, int cond) +{ + if (cond) { + static int shown; + + AUD_log (NULL, "A bug was just triggered in %s\n", funcname); + if (!shown) { + shown =3D 1; + AUD_log (NULL, "Save all your work and restart without audio\n= "); + AUD_log (NULL, "I am sorry\n"); + } + AUD_log (NULL, "Context:\n"); + } + + return cond; +} + +static inline int audio_bits_to_index (int bits) +{ + switch (bits) { + case 8: + return 0; + + case 16: + return 1; + + case 32: + return 2; + + default: + audio_bug ("bits_to_index", 1); + AUD_log (NULL, "invalid bits %d\n", bits); + return 0; + } +} + +void AUD_vlog (const char *cap, const char *fmt, va_list ap) +{ + if (cap) { + fprintf(stderr, "%s: ", cap); + } + + vfprintf(stderr, fmt, ap); +} + +void AUD_log (const char *cap, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + AUD_vlog (cap, fmt, ap); + va_end (ap); +} + +static void audio_print_settings (struct audsettings *as) +{ + dolog ("frequency=3D%d nchannels=3D%d fmt=3D", as->freq, as->nchannels= ); + + switch (as->fmt) { + case AUDIO_FORMAT_S8: + AUD_log (NULL, "S8"); + break; + case AUDIO_FORMAT_U8: + AUD_log (NULL, "U8"); + break; + case AUDIO_FORMAT_S16: + AUD_log (NULL, "S16"); + break; + case AUDIO_FORMAT_U16: + AUD_log (NULL, "U16"); + break; + case AUDIO_FORMAT_S32: + AUD_log (NULL, "S32"); + break; + case AUDIO_FORMAT_U32: + AUD_log (NULL, "U32"); + break; + case AUDIO_FORMAT_F32: + AUD_log (NULL, "F32"); + break; + default: + AUD_log (NULL, "invalid(%d)", as->fmt); + break; + } + + AUD_log (NULL, " endianness=3D"); + switch (as->endianness) { + case 0: + AUD_log (NULL, "little"); + break; + case 1: + AUD_log (NULL, "big"); + break; + default: + AUD_log (NULL, "invalid"); + break; + } + AUD_log (NULL, "\n"); +} + +static int audio_validate_settings (struct audsettings *as) +{ + int invalid; + + invalid =3D as->nchannels < 1; + invalid |=3D as->endianness !=3D 0 && as->endianness !=3D 1; + + switch (as->fmt) { + case AUDIO_FORMAT_S8: + case AUDIO_FORMAT_U8: + case AUDIO_FORMAT_S16: + case AUDIO_FORMAT_U16: + case AUDIO_FORMAT_S32: + case AUDIO_FORMAT_U32: + case AUDIO_FORMAT_F32: + break; + default: + invalid =3D 1; + break; + } + + invalid |=3D as->freq <=3D 0; + return invalid ? -1 : 0; +} + +static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsetti= ngs *as) +{ + int bits =3D 8; + bool is_signed =3D false, is_float =3D false; + + switch (as->fmt) { + case AUDIO_FORMAT_S8: + is_signed =3D true; + /* fall through */ + case AUDIO_FORMAT_U8: + break; + + case AUDIO_FORMAT_S16: + is_signed =3D true; + /* fall through */ + case AUDIO_FORMAT_U16: + bits =3D 16; + break; + + case AUDIO_FORMAT_F32: + is_float =3D true; + /* fall through */ + case AUDIO_FORMAT_S32: + is_signed =3D true; + /* fall through */ + case AUDIO_FORMAT_U32: + bits =3D 32; + break; + + default: + abort(); + } + return info->freq =3D=3D as->freq + && info->nchannels =3D=3D as->nchannels + && info->is_signed =3D=3D is_signed + && info->is_float =3D=3D is_float + && info->bits =3D=3D bits + && info->swap_endianness =3D=3D (as->endianness !=3D HOST_BIG_ENDI= AN); +} + +void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings = *as) +{ + int bits =3D 8, mul; + bool is_signed =3D false, is_float =3D false; + + switch (as->fmt) { + case AUDIO_FORMAT_S8: + is_signed =3D true; + /* fall through */ + case AUDIO_FORMAT_U8: + mul =3D 1; + break; + + case AUDIO_FORMAT_S16: + is_signed =3D true; + /* fall through */ + case AUDIO_FORMAT_U16: + bits =3D 16; + mul =3D 2; + break; + + case AUDIO_FORMAT_F32: + is_float =3D true; + /* fall through */ + case AUDIO_FORMAT_S32: + is_signed =3D true; + /* fall through */ + case AUDIO_FORMAT_U32: + bits =3D 32; + mul =3D 4; + break; + + default: + abort(); + } + + info->freq =3D as->freq; + info->bits =3D bits; + info->is_signed =3D is_signed; + info->is_float =3D is_float; + info->nchannels =3D as->nchannels; + info->bytes_per_frame =3D as->nchannels * mul; + info->bytes_per_second =3D info->freq * info->bytes_per_frame; + info->swap_endianness =3D (as->endianness !=3D HOST_BIG_ENDIAN); +} + +void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int= len) +{ + if (!len) { + return; + } + + if (info->is_signed || info->is_float) { + memset(buf, 0x00, len * info->bytes_per_frame); + } else { + switch (info->bits) { + case 8: + memset(buf, 0x80, len * info->bytes_per_frame); + break; + + case 16: + { + int i; + uint16_t *p =3D buf; + short s =3D INT16_MAX; + + if (info->swap_endianness) { + s =3D bswap16 (s); + } + + for (i =3D 0; i < len * info->nchannels; i++) { + p[i] =3D s; + } + } + break; + + case 32: + { + int i; + uint32_t *p =3D buf; + int32_t s =3D INT32_MAX; + + if (info->swap_endianness) { + s =3D bswap32 (s); + } + + for (i =3D 0; i < len * info->nchannels; i++) { + p[i] =3D s; + } + } + break; + + default: + AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n", + info->bits); + break; + } + } +} + +/* + * Capture + */ +static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioDriver *s, + struct audsettings= *as) +{ + CaptureVoiceOut *cap; + + for (cap =3D s->cap_head.lh_first; cap; cap =3D cap->entries.le_next) { + if (audio_pcm_info_eq (&cap->hw.info, as)) { + return cap; + } + } + return NULL; +} + +static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e= cmd) +{ + struct capture_callback *cb; + +#ifdef DEBUG_CAPTURE + dolog ("notification %d sent\n", cmd); +#endif + for (cb =3D cap->cb_head.lh_first; cb; cb =3D cb->entries.le_next) { + cb->ops.notify (cb->opaque, cmd); + } +} + +static void audio_capture_maybe_changed(CaptureVoiceOut *cap, bool enabled) +{ + if (cap->hw.enabled !=3D enabled) { + audcnotification_e cmd; + cap->hw.enabled =3D enabled; + cmd =3D enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE; + audio_notify_capture (cap, cmd); + } +} + +static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap) +{ + HWVoiceOut *hw =3D &cap->hw; + SWVoiceOut *sw; + bool enabled =3D false; + + for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { + if (sw->active) { + enabled =3D true; + break; + } + } + audio_capture_maybe_changed (cap, enabled); +} + +static void audio_detach_capture (HWVoiceOut *hw) +{ + SWVoiceCap *sc =3D hw->cap_head.lh_first; + + while (sc) { + SWVoiceCap *sc1 =3D sc->entries.le_next; + SWVoiceOut *sw =3D &sc->sw; + CaptureVoiceOut *cap =3D sc->cap; + int was_active =3D sw->active; + + if (sw->rate) { + st_rate_stop (sw->rate); + sw->rate =3D NULL; + } + + QLIST_REMOVE (sw, entries); + QLIST_REMOVE (sc, entries); + g_free (sc); + if (was_active) { + /* We have removed soft voice from the capture: + this might have changed the overall status of the capture + since this might have been the only active voice */ + audio_recalc_and_notify_capture (cap); + } + sc =3D sc1; + } +} + +static int audio_attach_capture (HWVoiceOut *hw) +{ + AudioDriver *s =3D hw->s; + CaptureVoiceOut *cap; + + audio_detach_capture (hw); + for (cap =3D s->cap_head.lh_first; cap; cap =3D cap->entries.le_next) { + SWVoiceCap *sc; + SWVoiceOut *sw; + HWVoiceOut *hw_cap =3D &cap->hw; + + sc =3D g_malloc0(sizeof(*sc)); + + sc->cap =3D cap; + sw =3D &sc->sw; + sw->hw =3D hw_cap; + sw->info =3D hw->info; + sw->empty =3D true; + sw->active =3D hw->enabled; + sw->vol =3D nominal_volume; + sw->rate =3D st_rate_start (sw->info.freq, hw_cap->info.freq); + QLIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries); + QLIST_INSERT_HEAD (&hw->cap_head, sc, entries); +#ifdef DEBUG_CAPTURE + sw->name =3D g_strdup_printf ("for %p %d,%d,%d", + hw, sw->info.freq, sw->info.bits, + sw->info.nchannels); + dolog ("Added %s active =3D %d\n", sw->name, sw->active); +#endif + if (sw->active) { + audio_capture_maybe_changed (cap, 1); + } + } + return 0; +} + +/* + * Hard voice (capture) + */ +static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) +{ + SWVoiceIn *sw; + size_t m =3D hw->total_samples_captured; + + for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { + if (sw->active) { + m =3D MIN (m, sw->total_hw_samples_acquired); + } + } + return m; +} + +static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) +{ + size_t live =3D hw->total_samples_captured - audio_pcm_hw_find_min_in = (hw); + if (audio_bug(__func__, live > hw->conv_buf.size)) { + dolog("live=3D%zu hw->conv_buf.size=3D%zu\n", live, hw->conv_buf.s= ize); + return 0; + } + return live; +} + +static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t sa= mples) +{ + size_t conv =3D 0; + STSampleBuffer *conv_buf =3D &hw->conv_buf; + + while (samples) { + uint8_t *src =3D advance(pcm_buf, conv * hw->info.bytes_per_frame); + size_t proc =3D MIN(samples, conv_buf->size - conv_buf->pos); + + hw->conv(conv_buf->buffer + conv_buf->pos, src, proc); + conv_buf->pos =3D (conv_buf->pos + proc) % conv_buf->size; + samples -=3D proc; + conv +=3D proc; + } + + return conv; +} + +/* + * Soft voice (capture) + */ +static void audio_pcm_sw_resample_in(SWVoiceIn *sw, + size_t frames_in_max, size_t frames_out_max, + size_t *total_in, size_t *total_out) +{ + HWVoiceIn *hw =3D sw->hw; + struct st_sample *src, *dst; + size_t live, rpos, frames_in, frames_out; + + live =3D hw->total_samples_captured - sw->total_hw_samples_acquired; + rpos =3D audio_ring_posb(hw->conv_buf.pos, live, hw->conv_buf.size); + + /* resample conv_buf from rpos to end of buffer */ + src =3D hw->conv_buf.buffer + rpos; + frames_in =3D MIN(frames_in_max, hw->conv_buf.size - rpos); + dst =3D sw->resample_buf.buffer; + frames_out =3D frames_out_max; + st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out); + rpos +=3D frames_in; + *total_in =3D frames_in; + *total_out =3D frames_out; + + /* resample conv_buf from start of buffer if there are input frames le= ft */ + if (frames_in_max - frames_in && rpos =3D=3D hw->conv_buf.size) { + src =3D hw->conv_buf.buffer; + frames_in =3D frames_in_max - frames_in; + dst +=3D frames_out; + frames_out =3D frames_out_max - frames_out; + st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out); + *total_in +=3D frames_in; + *total_out +=3D frames_out; + } +} + +static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t buf_len) +{ + HWVoiceIn *hw =3D sw->hw; + size_t live, frames_out_max, total_in, total_out; + + live =3D hw->total_samples_captured - sw->total_hw_samples_acquired; + if (!live) { + return 0; + } + if (audio_bug(__func__, live > hw->conv_buf.size)) { + dolog("live_in=3D%zu hw->conv_buf.size=3D%zu\n", live, hw->conv_bu= f.size); + return 0; + } + + frames_out_max =3D MIN(buf_len / sw->info.bytes_per_frame, + sw->resample_buf.size); + + audio_pcm_sw_resample_in(sw, live, frames_out_max, &total_in, &total_o= ut); + + if (!hw->pcm_ops->volume_in) { + mixeng_volume(sw->resample_buf.buffer, total_out, &sw->vol); + } + sw->clip(buf, sw->resample_buf.buffer, total_out); + + sw->total_hw_samples_acquired +=3D total_in; + return total_out * sw->info.bytes_per_frame; +} + +/* + * Hard voice (playback) + */ +static size_t audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep) +{ + SWVoiceOut *sw; + size_t m =3D SIZE_MAX; + int nb_live =3D 0; + + for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { + if (sw->active || !sw->empty) { + m =3D MIN (m, sw->total_hw_samples_mixed); + nb_live +=3D 1; + } + } + + *nb_livep =3D nb_live; + return m; +} + +static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live) +{ + size_t smin; + int nb_live1; + + smin =3D audio_pcm_hw_find_min_out (hw, &nb_live1); + if (nb_live) { + *nb_live =3D nb_live1; + } + + if (nb_live1) { + size_t live =3D smin; + + if (audio_bug(__func__, live > hw->mix_buf.size)) { + dolog("live=3D%zu hw->mix_buf.size=3D%zu\n", live, hw->mix_buf= .size); + return 0; + } + return live; + } + return 0; +} + +static size_t audio_pcm_hw_get_free(HWVoiceOut *hw) +{ + return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw= ) : + INT_MAX) / hw->info.bytes_per_frame; +} + +static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t le= n) +{ + size_t clipped =3D 0; + size_t pos =3D hw->mix_buf.pos; + + while (len) { + st_sample *src =3D hw->mix_buf.buffer + pos; + uint8_t *dst =3D advance(pcm_buf, clipped * hw->info.bytes_per_fra= me); + size_t samples_till_end_of_buf =3D hw->mix_buf.size - pos; + size_t samples_to_clip =3D MIN(len, samples_till_end_of_buf); + + hw->clip(dst, src, samples_to_clip); + + pos =3D (pos + samples_to_clip) % hw->mix_buf.size; + len -=3D samples_to_clip; + clipped +=3D samples_to_clip; + } +} + +/* + * Soft voice (playback) + */ +static void audio_pcm_sw_resample_out(SWVoiceOut *sw, + size_t frames_in_max, size_t frames_out_max, + size_t *total_in, size_t *total_out) +{ + HWVoiceOut *hw =3D sw->hw; + struct st_sample *src, *dst; + size_t live, wpos, frames_in, frames_out; + + live =3D sw->total_hw_samples_mixed; + wpos =3D (hw->mix_buf.pos + live) % hw->mix_buf.size; + + /* write to mix_buf from wpos to end of buffer */ + src =3D sw->resample_buf.buffer; + frames_in =3D frames_in_max; + dst =3D hw->mix_buf.buffer + wpos; + frames_out =3D MIN(frames_out_max, hw->mix_buf.size - wpos); + st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out); + wpos +=3D frames_out; + *total_in =3D frames_in; + *total_out =3D frames_out; + + /* write to mix_buf from start of buffer if there are input frames lef= t */ + if (frames_in_max - frames_in > 0 && wpos =3D=3D hw->mix_buf.size) { + src +=3D frames_in; + frames_in =3D frames_in_max - frames_in; + dst =3D hw->mix_buf.buffer; + frames_out =3D frames_out_max - frames_out; + st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out); + *total_in +=3D frames_in; + *total_out +=3D frames_out; + } +} + +static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len) +{ + HWVoiceOut *hw =3D sw->hw; + size_t live, dead, hw_free, sw_max, fe_max; + size_t frames_in_max, frames_out_max, total_in, total_out; + + live =3D sw->total_hw_samples_mixed; + if (audio_bug(__func__, live > hw->mix_buf.size)) { + dolog("live=3D%zu hw->mix_buf.size=3D%zu\n", live, hw->mix_buf.siz= e); + return 0; + } + + if (live =3D=3D hw->mix_buf.size) { +#ifdef DEBUG_OUT + dolog ("%s is full %zu\n", sw->name, live); +#endif + return 0; + } + + dead =3D hw->mix_buf.size - live; + hw_free =3D audio_pcm_hw_get_free(hw); + hw_free =3D hw_free > live ? hw_free - live : 0; + frames_out_max =3D MIN(dead, hw_free); + sw_max =3D st_rate_frames_in(sw->rate, frames_out_max); + fe_max =3D MIN(buf_len / sw->info.bytes_per_frame + sw->resample_buf.p= os, + sw->resample_buf.size); + frames_in_max =3D MIN(sw_max, fe_max); + + if (!frames_in_max) { + return 0; + } + + if (frames_in_max > sw->resample_buf.pos) { + sw->conv(sw->resample_buf.buffer + sw->resample_buf.pos, + buf, frames_in_max - sw->resample_buf.pos); + if (!sw->hw->pcm_ops->volume_out) { + mixeng_volume(sw->resample_buf.buffer + sw->resample_buf.pos, + frames_in_max - sw->resample_buf.pos, &sw->vol); + } + } + + audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max, + &total_in, &total_out); + + sw->total_hw_samples_mixed +=3D total_out; + sw->empty =3D sw->total_hw_samples_mixed =3D=3D 0; + + /* + * Upsampling may leave one audio frame in the resample buffer. Decrem= ent + * total_in by one if there was a leftover frame from the previous res= ample + * pass in the resample buffer. Increment total_in by one if the curre= nt + * resample pass left one frame in the resample buffer. + */ + if (frames_in_max - total_in =3D=3D 1) { + /* copy one leftover audio frame to the beginning of the buffer */ + *sw->resample_buf.buffer =3D *(sw->resample_buf.buffer + total_in); + total_in +=3D 1 - sw->resample_buf.pos; + sw->resample_buf.pos =3D 1; + } else if (total_in >=3D sw->resample_buf.pos) { + total_in -=3D sw->resample_buf.pos; + sw->resample_buf.pos =3D 0; + } + +#ifdef DEBUG_OUT + dolog ( + "%s: write size %zu written %zu total mixed %zu\n", + SW_NAME(sw), + buf_len / sw->info.bytes_per_frame, + total_in, + sw->total_hw_samples_mixed + ); +#endif + + return total_in * sw->info.bytes_per_frame; +} + +#ifdef DEBUG_AUDIO +static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *= info) +{ + dolog("%s: bits %d, sign %d, float %d, freq %d, nchan %d\n", + cap, info->bits, info->is_signed, info->is_float, info->freq, + info->nchannels); +} +#endif + +#define DAC +#include "audio-driver_template.h" +#undef DAC +#include "audio-driver_template.h" + +/* + * Timer + */ +static int audio_is_timer_needed(AudioDriver *s) +{ + HWVoiceIn *hwi =3D NULL; + HWVoiceOut *hwo =3D NULL; + + while ((hwo =3D audio_pcm_hw_find_any_enabled_out(s, hwo))) { + if (!hwo->poll_mode) { + return 1; + } + } + while ((hwi =3D audio_pcm_hw_find_any_enabled_in(s, hwi))) { + if (!hwi->poll_mode) { + return 1; + } + } + return 0; +} + +static void audio_reset_timer(AudioDriver *s) +{ + if (audio_is_timer_needed(s)) { + timer_mod_anticipate_ns(s->ts, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->period_ticks); + if (!s->timer_running) { + s->timer_running =3D true; + s->timer_last =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + trace_audio_timer_start(s->period_ticks / SCALE_MS); + } + } else { + timer_del(s->ts); + if (s->timer_running) { + s->timer_running =3D false; + trace_audio_timer_stop(); + } + } +} + +static void audio_timer (void *opaque) +{ + int64_t now, diff; + AudioDriver *s =3D opaque; + + now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + diff =3D now - s->timer_last; + if (diff > s->period_ticks * 3 / 2) { + trace_audio_timer_delayed(diff / SCALE_MS); + } + s->timer_last =3D now; + + audio_run(s, "timer"); + audio_reset_timer(s); +} + +/* + * Public API + */ + static size_t audio_driver_write(AudioBackend *be, SWVoiceOut *sw, void *= buf, size_t size) + { + HWVoiceOut *hw; + + if (!sw) { + /* XXX: Consider options */ + return size; + } + hw =3D sw->hw; + + if (!hw->enabled) { + dolog ("Writing to disabled voice %s\n", SW_NAME (sw)); + return 0; + } + + if (audio_get_pdo_out(hw->s->dev)->mixing_engine) { + return audio_pcm_sw_write(sw, buf, size); + } else { + return hw->pcm_ops->write(hw, buf, size); + } + } + +static size_t audio_driver_read(AudioBackend *be, SWVoiceIn *sw, void *buf= , size_t size) +{ + HWVoiceIn *hw; + + if (!sw) { + /* XXX: Consider options */ + return size; + } + hw =3D sw->hw; + + if (!hw->enabled) { + dolog ("Reading from disabled voice %s\n", SW_NAME (sw)); + return 0; + } + + if (audio_get_pdo_in(hw->s->dev)->mixing_engine) { + return audio_pcm_sw_read(sw, buf, size); + } else { + return hw->pcm_ops->read(hw, buf, size); + } + +} + +static int audio_driver_get_buffer_size_out(AudioBackend *be, SWVoiceOut *= sw) +{ + if (!sw) { + return 0; + } + + if (audio_get_pdo_out(sw->s->dev)->mixing_engine) { + return sw->resample_buf.size * sw->info.bytes_per_frame; + } + + return sw->hw->samples * sw->hw->info.bytes_per_frame; +} + +static void audio_driver_set_active_out(AudioBackend *be, SWVoiceOut *sw, = bool on) +{ + HWVoiceOut *hw; + + if (!sw) { + return; + } + + hw =3D sw->hw; + if (sw->active !=3D on) { + AudioDriver *s =3D sw->s; + SWVoiceOut *temp_sw; + SWVoiceCap *sc; + + if (on) { + hw->pending_disable =3D 0; + if (!hw->enabled) { + hw->enabled =3D true; + if (s->vm_running) { + if (hw->pcm_ops->enable_out) { + hw->pcm_ops->enable_out(hw, true); + } + audio_reset_timer (s); + } + } + } else { + if (hw->enabled) { + int nb_active =3D 0; + + for (temp_sw =3D hw->sw_head.lh_first; temp_sw; + temp_sw =3D temp_sw->entries.le_next) { + nb_active +=3D temp_sw->active !=3D 0; + } + + hw->pending_disable =3D nb_active =3D=3D 1; + } + } + + for (sc =3D hw->cap_head.lh_first; sc; sc =3D sc->entries.le_next)= { + sc->sw.active =3D hw->enabled; + if (hw->enabled) { + audio_capture_maybe_changed (sc->cap, 1); + } + } + sw->active =3D on; + } + +} + +static void audio_driver_set_active_in(AudioBackend *be, SWVoiceIn *sw, bo= ol on) +{ + HWVoiceIn *hw; + + if (!sw) { + return; + } + + hw =3D sw->hw; + if (sw->active !=3D on) { + AudioDriver *s =3D sw->s; + SWVoiceIn *temp_sw; + + if (on) { + if (!hw->enabled) { + hw->enabled =3D true; + if (s->vm_running) { + if (hw->pcm_ops->enable_in) { + hw->pcm_ops->enable_in(hw, true); + } + audio_reset_timer (s); + } + } + sw->total_hw_samples_acquired =3D hw->total_samples_captured; + } else { + if (hw->enabled) { + int nb_active =3D 0; + + for (temp_sw =3D hw->sw_head.lh_first; temp_sw; + temp_sw =3D temp_sw->entries.le_next) { + nb_active +=3D temp_sw->active !=3D 0; + } + + if (nb_active =3D=3D 1) { + hw->enabled =3D false; + if (hw->pcm_ops->enable_in) { + hw->pcm_ops->enable_in(hw, false); + } + } + } + } + sw->active =3D on; + } +} + +static size_t audio_get_avail(SWVoiceIn *sw) +{ + size_t live; + + if (!sw) { + return 0; + } + + live =3D sw->hw->total_samples_captured - sw->total_hw_samples_acquire= d; + if (audio_bug(__func__, live > sw->hw->conv_buf.size)) { + dolog("live=3D%zu sw->hw->conv_buf.size=3D%zu\n", live, + sw->hw->conv_buf.size); + return 0; + } + + ldebug ( + "%s: get_avail live %zu frontend frames %u\n", + SW_NAME (sw), + live, st_rate_frames_out(sw->rate, live) + ); + + return live; +} + +static size_t audio_get_free(SWVoiceOut *sw) +{ + size_t live, dead; + + if (!sw) { + return 0; + } + + live =3D sw->total_hw_samples_mixed; + + if (audio_bug(__func__, live > sw->hw->mix_buf.size)) { + dolog("live=3D%zu sw->hw->mix_buf.size=3D%zu\n", live, + sw->hw->mix_buf.size); + return 0; + } + + dead =3D sw->hw->mix_buf.size - live; + +#ifdef DEBUG_OUT + dolog("%s: get_free live %zu dead %zu frontend frames %u\n", + SW_NAME(sw), live, dead, st_rate_frames_in(sw->rate, dead)); +#endif + + return dead; +} + +static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, + size_t samples) +{ + size_t n; + + if (hw->enabled) { + SWVoiceCap *sc; + + for (sc =3D hw->cap_head.lh_first; sc; sc =3D sc->entries.le_next)= { + SWVoiceOut *sw =3D &sc->sw; + size_t rpos2 =3D rpos; + + n =3D samples; + while (n) { + size_t till_end_of_hw =3D hw->mix_buf.size - rpos2; + size_t to_read =3D MIN(till_end_of_hw, n); + size_t live, frames_in, frames_out; + + sw->resample_buf.buffer =3D hw->mix_buf.buffer + rpos2; + sw->resample_buf.size =3D to_read; + live =3D sw->total_hw_samples_mixed; + + audio_pcm_sw_resample_out(sw, + to_read, sw->hw->mix_buf.size - = live, + &frames_in, &frames_out); + + sw->total_hw_samples_mixed +=3D frames_out; + sw->empty =3D sw->total_hw_samples_mixed =3D=3D 0; + + if (to_read - frames_in) { + dolog("Could not mix %zu frames into a capture " + "buffer, mixed %zu\n", + to_read, frames_in); + break; + } + n -=3D to_read; + rpos2 =3D (rpos2 + to_read) % hw->mix_buf.size; + } + } + } + + n =3D MIN(samples, hw->mix_buf.size - rpos); + mixeng_clear(hw->mix_buf.buffer + rpos, n); + mixeng_clear(hw->mix_buf.buffer, samples - n); +} + +static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) +{ + size_t clipped =3D 0; + + while (live) { + size_t size =3D live * hw->info.bytes_per_frame; + size_t decr, proc; + void *buf =3D hw->pcm_ops->get_buffer_out(hw, &size); + + if (size =3D=3D 0) { + break; + } + + decr =3D MIN(size / hw->info.bytes_per_frame, live); + if (buf) { + audio_pcm_hw_clip_out(hw, buf, decr); + } + proc =3D hw->pcm_ops->put_buffer_out(hw, buf, + decr * hw->info.bytes_per_frame= ) / + hw->info.bytes_per_frame; + + live -=3D proc; + clipped +=3D proc; + hw->mix_buf.pos =3D (hw->mix_buf.pos + proc) % hw->mix_buf.size; + + if (proc =3D=3D 0 || proc < decr) { + break; + } + } + + if (hw->pcm_ops->run_buffer_out) { + hw->pcm_ops->run_buffer_out(hw); + } + + return clipped; +} + +static void audio_run_out(AudioDriver *s) +{ + HWVoiceOut *hw =3D NULL; + SWVoiceOut *sw; + + while ((hw =3D audio_pcm_hw_find_any_enabled_out(s, hw))) { + size_t played, live, prev_rpos; + size_t hw_free =3D audio_pcm_hw_get_free(hw); + int nb_live; + + if (!audio_get_pdo_out(s->dev)->mixing_engine) { + /* there is exactly 1 sw for each hw with no mixeng */ + sw =3D hw->sw_head.lh_first; + + if (hw->pending_disable) { + hw->enabled =3D false; + hw->pending_disable =3D false; + if (hw->pcm_ops->enable_out) { + hw->pcm_ops->enable_out(hw, false); + } + } + + if (sw->active) { + sw->callback.fn(sw->callback.opaque, + hw_free * sw->info.bytes_per_frame); + } + + if (hw->pcm_ops->run_buffer_out) { + hw->pcm_ops->run_buffer_out(hw); + } + + continue; + } + + for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { + if (sw->active) { + size_t sw_free =3D audio_get_free(sw); + size_t free; + + if (hw_free > sw->total_hw_samples_mixed) { + free =3D st_rate_frames_in(sw->rate, + MIN(sw_free, hw_free - sw->total_hw_samples_mixed)= ); + } else { + free =3D 0; + } + if (free > sw->resample_buf.pos) { + free =3D MIN(free, sw->resample_buf.size) + - sw->resample_buf.pos; + sw->callback.fn(sw->callback.opaque, + free * sw->info.bytes_per_frame); + } + } + } + + live =3D audio_pcm_hw_get_live_out (hw, &nb_live); + if (!nb_live) { + live =3D 0; + } + + if (audio_bug(__func__, live > hw->mix_buf.size)) { + dolog("live=3D%zu hw->mix_buf.size=3D%zu\n", live, hw->mix_buf= .size); + continue; + } + + if (hw->pending_disable && !nb_live) { + SWVoiceCap *sc; +#ifdef DEBUG_OUT + dolog ("Disabling voice\n"); +#endif + hw->enabled =3D false; + hw->pending_disable =3D false; + if (hw->pcm_ops->enable_out) { + hw->pcm_ops->enable_out(hw, false); + } + for (sc =3D hw->cap_head.lh_first; sc; sc =3D sc->entries.le_n= ext) { + sc->sw.active =3D false; + audio_recalc_and_notify_capture (sc->cap); + } + continue; + } + + if (!live) { + if (hw->pcm_ops->run_buffer_out) { + hw->pcm_ops->run_buffer_out(hw); + } + continue; + } + + prev_rpos =3D hw->mix_buf.pos; + played =3D audio_pcm_hw_run_out(hw, live); + replay_audio_out(&played); + if (audio_bug(__func__, hw->mix_buf.pos >=3D hw->mix_buf.size)) { + dolog("hw->mix_buf.pos=3D%zu hw->mix_buf.size=3D%zu played=3D%= zu\n", + hw->mix_buf.pos, hw->mix_buf.size, played); + hw->mix_buf.pos =3D 0; + } + +#ifdef DEBUG_OUT + dolog("played=3D%zu\n", played); +#endif + + if (played) { + hw->ts_helper +=3D played; + audio_capture_mix_and_clear (hw, prev_rpos, played); + } + + for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { + if (!sw->active && sw->empty) { + continue; + } + + if (audio_bug(__func__, played > sw->total_hw_samples_mixed)) { + dolog("played=3D%zu sw->total_hw_samples_mixed=3D%zu\n", + played, sw->total_hw_samples_mixed); + played =3D sw->total_hw_samples_mixed; + } + + sw->total_hw_samples_mixed -=3D played; + + if (!sw->total_hw_samples_mixed) { + sw->empty =3D true; + } + } + } +} + +static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) +{ + size_t conv =3D 0; + + if (hw->pcm_ops->run_buffer_in) { + hw->pcm_ops->run_buffer_in(hw); + } + + while (samples) { + size_t proc; + size_t size =3D samples * hw->info.bytes_per_frame; + void *buf =3D hw->pcm_ops->get_buffer_in(hw, &size); + + assert(size % hw->info.bytes_per_frame =3D=3D 0); + if (size =3D=3D 0) { + break; + } + + proc =3D audio_pcm_hw_conv_in(hw, buf, size / hw->info.bytes_per_f= rame); + + samples -=3D proc; + conv +=3D proc; + hw->pcm_ops->put_buffer_in(hw, buf, proc * hw->info.bytes_per_fram= e); + } + + return conv; +} + +static void audio_run_in(AudioDriver *s) +{ + HWVoiceIn *hw =3D NULL; + + if (!audio_get_pdo_in(s->dev)->mixing_engine) { + while ((hw =3D audio_pcm_hw_find_any_enabled_in(s, hw))) { + /* there is exactly 1 sw for each hw with no mixeng */ + SWVoiceIn *sw =3D hw->sw_head.lh_first; + if (sw->active) { + sw->callback.fn(sw->callback.opaque, INT_MAX); + } + } + return; + } + + while ((hw =3D audio_pcm_hw_find_any_enabled_in(s, hw))) { + SWVoiceIn *sw; + size_t captured =3D 0, min; + int pos; + + if (replay_mode !=3D REPLAY_MODE_PLAY) { + captured =3D audio_pcm_hw_run_in( + hw, hw->conv_buf.size - audio_pcm_hw_get_live_in(hw)); + } + + replay_audio_in_start(&captured); + assert(captured <=3D hw->conv_buf.size); + if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + hw->conv_buf.pos =3D (hw->conv_buf.pos + captured) % hw->conv_= buf.size; + } + for (pos =3D (hw->conv_buf.pos - captured + hw->conv_buf.size) % h= w->conv_buf.size; + pos !=3D hw->conv_buf.pos; + pos =3D (pos + 1) % hw->conv_buf.size) { + uint64_t left, right; + + if (replay_mode =3D=3D REPLAY_MODE_RECORD) { + audio_sample_to_uint64(hw->conv_buf.buffer, pos, &left= , &right); + } + replay_audio_in_sample_lr(&left, &right); + if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + audio_sample_from_uint64(hw->conv_buf.buffer, pos, lef= t, right); + } + } + replay_audio_in_finish(); + + min =3D audio_pcm_hw_find_min_in (hw); + hw->total_samples_captured +=3D captured - min; + hw->ts_helper +=3D captured; + + for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { + sw->total_hw_samples_acquired -=3D min; + + if (sw->active) { + size_t sw_avail =3D audio_get_avail(sw); + size_t avail; + + avail =3D st_rate_frames_out(sw->rate, sw_avail); + if (avail > 0) { + avail =3D MIN(avail, sw->resample_buf.size); + sw->callback.fn(sw->callback.opaque, + avail * sw->info.bytes_per_frame); + } + } + } + } +} + +static void audio_run_capture(AudioDriver *s) +{ + CaptureVoiceOut *cap; + + for (cap =3D s->cap_head.lh_first; cap; cap =3D cap->entries.le_next) { + size_t live, rpos, captured; + HWVoiceOut *hw =3D &cap->hw; + SWVoiceOut *sw; + + captured =3D live =3D audio_pcm_hw_get_live_out (hw, NULL); + rpos =3D hw->mix_buf.pos; + while (live) { + size_t left =3D hw->mix_buf.size - rpos; + size_t to_capture =3D MIN(live, left); + struct st_sample *src; + struct capture_callback *cb; + + src =3D hw->mix_buf.buffer + rpos; + hw->clip (cap->buf, src, to_capture); + mixeng_clear (src, to_capture); + + for (cb =3D cap->cb_head.lh_first; cb; cb =3D cb->entries.le_n= ext) { + cb->ops.capture (cb->opaque, cap->buf, + to_capture * hw->info.bytes_per_frame); + } + rpos =3D (rpos + to_capture) % hw->mix_buf.size; + live -=3D to_capture; + } + hw->mix_buf.pos =3D rpos; + + for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { + if (!sw->active && sw->empty) { + continue; + } + + if (audio_bug(__func__, captured > sw->total_hw_samples_mixed)= ) { + dolog("captured=3D%zu sw->total_hw_samples_mixed=3D%zu\n", + captured, sw->total_hw_samples_mixed); + captured =3D sw->total_hw_samples_mixed; + } + + sw->total_hw_samples_mixed -=3D captured; + sw->empty =3D sw->total_hw_samples_mixed =3D=3D 0; + } + } +} + +void audio_run(AudioDriver *s, const char *msg) +{ + audio_run_out(s); + audio_run_in(s); + audio_run_capture(s); + +#ifdef DEBUG_POLL + { + static double prevtime; + double currtime; + struct timeval tv; + + if (gettimeofday (&tv, NULL)) { + perror ("audio_run: gettimeofday"); + return; + } + + currtime =3D tv.tv_sec + tv.tv_usec * 1e-6; + dolog ("Elapsed since last %s: %f\n", msg, currtime - prevtime); + prevtime =3D currtime; + } +#endif +} + +void audio_generic_run_buffer_in(HWVoiceIn *hw) +{ + if (unlikely(!hw->buf_emul)) { + hw->size_emul =3D hw->samples * hw->info.bytes_per_frame; + hw->buf_emul =3D g_malloc(hw->size_emul); + hw->pos_emul =3D hw->pending_emul =3D 0; + } + + while (hw->pending_emul < hw->size_emul) { + size_t read_len =3D MIN(hw->size_emul - hw->pos_emul, + hw->size_emul - hw->pending_emul); + size_t read =3D hw->pcm_ops->read(hw, hw->buf_emul + hw->pos_emul, + read_len); + hw->pending_emul +=3D read; + hw->pos_emul =3D (hw->pos_emul + read) % hw->size_emul; + if (read < read_len) { + break; + } + } +} + +void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size) +{ + size_t start; + + start =3D audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emu= l); + assert(start < hw->size_emul); + + *size =3D MIN(*size, hw->pending_emul); + *size =3D MIN(*size, hw->size_emul - start); + return hw->buf_emul + start; +} + +void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size) +{ + assert(size <=3D hw->pending_emul); + hw->pending_emul -=3D size; +} + +size_t audio_generic_buffer_get_free(HWVoiceOut *hw) +{ + if (hw->buf_emul) { + return hw->size_emul - hw->pending_emul; + } else { + return hw->samples * hw->info.bytes_per_frame; + } +} + +void audio_generic_run_buffer_out(HWVoiceOut *hw) +{ + while (hw->pending_emul) { + size_t write_len, written, start; + + start =3D audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size= _emul); + assert(start < hw->size_emul); + + write_len =3D MIN(hw->pending_emul, hw->size_emul - start); + + written =3D hw->pcm_ops->write(hw, hw->buf_emul + start, write_len= ); + hw->pending_emul -=3D written; + + if (written < write_len) { + break; + } + } +} + +void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ + if (unlikely(!hw->buf_emul)) { + hw->size_emul =3D hw->samples * hw->info.bytes_per_frame; + hw->buf_emul =3D g_malloc(hw->size_emul); + hw->pos_emul =3D hw->pending_emul =3D 0; + } + + *size =3D MIN(hw->size_emul - hw->pending_emul, + hw->size_emul - hw->pos_emul); + return hw->buf_emul + hw->pos_emul; +} + +size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) +{ + assert(buf =3D=3D hw->buf_emul + hw->pos_emul && + size + hw->pending_emul <=3D hw->size_emul); + + hw->pending_emul +=3D size; + hw->pos_emul =3D (hw->pos_emul + size) % hw->size_emul; + + return size; +} + +size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size) +{ + size_t total =3D 0; + + if (hw->pcm_ops->buffer_get_free) { + size_t free =3D hw->pcm_ops->buffer_get_free(hw); + + size =3D MIN(size, free); + } + + while (total < size) { + size_t dst_size =3D size - total; + size_t copy_size, proc; + void *dst =3D hw->pcm_ops->get_buffer_out(hw, &dst_size); + + if (dst_size =3D=3D 0) { + break; + } + + copy_size =3D MIN(size - total, dst_size); + if (dst) { + memcpy(dst, (char *)buf + total, copy_size); + } + proc =3D hw->pcm_ops->put_buffer_out(hw, dst, copy_size); + total +=3D proc; + + if (proc =3D=3D 0 || proc < copy_size) { + break; + } + } + + return total; +} + +size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) +{ + size_t total =3D 0; + + if (hw->pcm_ops->run_buffer_in) { + hw->pcm_ops->run_buffer_in(hw); + } + + while (total < size) { + size_t src_size =3D size - total; + void *src =3D hw->pcm_ops->get_buffer_in(hw, &src_size); + + if (src_size =3D=3D 0) { + break; + } + + memcpy((char *)buf + total, src, src_size); + hw->pcm_ops->put_buffer_in(hw, src, src_size); + total +=3D src_size; + } + + return total; +} + +static bool audio_be_driver_realize(AudioBackend *abe, Audiodev *dev, Erro= r **errp) +{ + AudioDriver *d =3D AUDIO_DRIVER(abe); + audio_driver *drv =3D AUDIO_DRIVER_GET_CLASS(d)->driver; + + d->dev =3D dev; + d->drv_opaque =3D drv->init(d->dev, errp); + if (!d->drv_opaque) { + return false; + } + + if (!drv->pcm_ops->get_buffer_in) { + drv->pcm_ops->get_buffer_in =3D audio_generic_get_buffer_in; + drv->pcm_ops->put_buffer_in =3D audio_generic_put_buffer_in; + } + if (!drv->pcm_ops->get_buffer_out) { + drv->pcm_ops->get_buffer_out =3D audio_generic_get_buffer_out; + drv->pcm_ops->put_buffer_out =3D audio_generic_put_buffer_out; + } + + audio_init_nb_voices_out(d, drv, 1); + audio_init_nb_voices_in(d, drv, 0); + d->drv =3D drv; + + if (d->dev->timer_period <=3D 0) { + d->period_ticks =3D 1; + } else { + d->period_ticks =3D d->dev->timer_period * (int64_t)SCALE_US; + } + + return true; +} + +static void audio_vm_change_state_handler (void *opaque, bool running, + RunState state) +{ + AudioDriver *s =3D opaque; + HWVoiceOut *hwo =3D NULL; + HWVoiceIn *hwi =3D NULL; + + s->vm_running =3D running; + while ((hwo =3D audio_pcm_hw_find_any_enabled_out(s, hwo))) { + if (hwo->pcm_ops->enable_out) { + hwo->pcm_ops->enable_out(hwo, running); + } + } + + while ((hwi =3D audio_pcm_hw_find_any_enabled_in(s, hwi))) { + if (hwi->pcm_ops->enable_in) { + hwi->pcm_ops->enable_in(hwi, running); + } + } + audio_reset_timer (s); +} + +static const VMStateDescription vmstate_audio; + +static const char *audio_driver_get_id(AudioBackend *be) +{ + return AUDIO_DRIVER(be)->dev->id; +} + +static CaptureVoiceOut *audio_driver_add_capture( + AudioBackend *be, + struct audsettings *as, + struct audio_capture_ops *ops, + void *cb_opaque); + +static void audio_driver_del_capture( + AudioBackend *be, + CaptureVoiceOut *cap, + void *cb_opaque); + +static void audio_driver_set_volume_out(AudioBackend *be, SWVoiceOut *sw, = Volume *vol); +static void audio_driver_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Vo= lume *vol); + +static void audio_driver_class_init(ObjectClass *klass, const void *data) +{ + AudioBackendClass *be =3D AUDIO_BACKEND_CLASS(klass); + + be->realize =3D audio_be_driver_realize; + be->get_id =3D audio_driver_get_id; + be->open_in =3D audio_driver_open_in; + be->open_out =3D audio_driver_open_out; + be->close_in =3D audio_driver_close_in; + be->close_out =3D audio_driver_close_out; + be->is_active_out =3D audio_driver_is_active_out; + be->is_active_in =3D audio_driver_is_active_in; + be->set_active_out =3D audio_driver_set_active_out; + be->set_active_in =3D audio_driver_set_active_in; + be->set_volume_out =3D audio_driver_set_volume_out; + be->set_volume_in =3D audio_driver_set_volume_in; + be->read =3D audio_driver_read; + be->write =3D audio_driver_write; + be->get_buffer_size_out =3D audio_driver_get_buffer_size_out; + be->add_capture =3D audio_driver_add_capture; + be->del_capture =3D audio_driver_del_capture; +} + +static void audio_driver_init(Object *obj) +{ + AudioDriver *s =3D AUDIO_DRIVER(obj); + + QLIST_INIT(&s->hw_head_out); + QLIST_INIT(&s->hw_head_in); + QLIST_INIT(&s->cap_head); + s->ts =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); + + s->vmse =3D qemu_add_vm_change_state_handler(audio_vm_change_state_han= dler, s); + assert(s->vmse !=3D NULL); + + vmstate_register_any(NULL, &vmstate_audio, s); +} + +static void audio_driver_finalize(Object *obj) +{ + AudioDriver *s =3D AUDIO_DRIVER(obj); + HWVoiceOut *hwo, *hwon; + HWVoiceIn *hwi, *hwin; + + QLIST_FOREACH_SAFE(hwo, &s->hw_head_out, entries, hwon) { + SWVoiceCap *sc; + + if (hwo->enabled && hwo->pcm_ops->enable_out) { + hwo->pcm_ops->enable_out(hwo, false); + } + hwo->pcm_ops->fini_out (hwo); + + for (sc =3D hwo->cap_head.lh_first; sc; sc =3D sc->entries.le_next= ) { + CaptureVoiceOut *cap =3D sc->cap; + struct capture_callback *cb; + + for (cb =3D cap->cb_head.lh_first; cb; cb =3D cb->entries.le_n= ext) { + cb->ops.destroy (cb->opaque); + } + } + QLIST_REMOVE(hwo, entries); + } + + QLIST_FOREACH_SAFE(hwi, &s->hw_head_in, entries, hwin) { + if (hwi->enabled && hwi->pcm_ops->enable_in) { + hwi->pcm_ops->enable_in(hwi, false); + } + hwi->pcm_ops->fini_in (hwi); + QLIST_REMOVE(hwi, entries); + } + + if (s->drv) { + s->drv->fini (s->drv_opaque); + s->drv =3D NULL; + } + + if (s->dev) { + qapi_free_Audiodev(s->dev); + s->dev =3D NULL; + } + + if (s->ts) { + timer_free(s->ts); + s->ts =3D NULL; + } + + if (s->vmse) { + qemu_del_vm_change_state_handler(s->vmse); + s->vmse =3D NULL; + } + + vmstate_unregister(NULL, &vmstate_audio, s); +} + +static bool vmstate_audio_needed(void *opaque) +{ + /* + * Never needed, this vmstate only exists in case + * an old qemu sends it to us. + */ + return false; +} + +static const VMStateDescription vmstate_audio =3D { + .name =3D "audio", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D vmstate_audio_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static struct audio_pcm_ops capture_pcm_ops; + +static CaptureVoiceOut *audio_driver_add_capture( + AudioBackend *be, + struct audsettings *as, + struct audio_capture_ops *ops, + void *cb_opaque) +{ + AudioDriver *s =3D AUDIO_DRIVER(be); + CaptureVoiceOut *cap; + struct capture_callback *cb; + + if (!s) { + /* TODO: implement an interface instead (or drop capture support) = */ + error_report("Capturing without setting an audiodev driver is not = supported"); + abort(); + } + + if (!audio_get_pdo_out(s->dev)->mixing_engine) { + dolog("Can't capture with mixeng disabled\n"); + return NULL; + } + + if (audio_validate_settings (as)) { + dolog ("Invalid settings were passed when trying to add capture\n"= ); + audio_print_settings (as); + return NULL; + } + + cb =3D g_malloc0(sizeof(*cb)); + cb->ops =3D *ops; + cb->opaque =3D cb_opaque; + + cap =3D audio_pcm_capture_find_specific(s, as); + if (cap) { + QLIST_INSERT_HEAD (&cap->cb_head, cb, entries); + } else { + HWVoiceOut *hw; + + cap =3D g_malloc0(sizeof(*cap)); + + hw =3D &cap->hw; + hw->s =3D s; + hw->pcm_ops =3D &capture_pcm_ops; + QLIST_INIT (&hw->sw_head); + QLIST_INIT (&cap->cb_head); + + /* XXX find a more elegant way */ + hw->samples =3D 4096 * 4; + audio_pcm_hw_alloc_resources_out(hw); + + audio_pcm_init_info (&hw->info, as); + + cap->buf =3D g_malloc0_n(hw->mix_buf.size, hw->info.bytes_per_fram= e); + + if (hw->info.is_float) { + hw->clip =3D mixeng_clip_float[hw->info.nchannels =3D=3D 2] + [hw->info.swap_endianness]; + } else { + hw->clip =3D mixeng_clip + [hw->info.nchannels =3D=3D 2] + [hw->info.is_signed] + [hw->info.swap_endianness] + [audio_bits_to_index(hw->info.bits)]; + } + + QLIST_INSERT_HEAD (&s->cap_head, cap, entries); + QLIST_INSERT_HEAD (&cap->cb_head, cb, entries); + + QLIST_FOREACH(hw, &s->hw_head_out, entries) { + audio_attach_capture (hw); + } + } + + return cap; +} + +static void audio_driver_del_capture( + AudioBackend *be, + CaptureVoiceOut *cap, + void *cb_opaque) +{ + struct capture_callback *cb; + + for (cb =3D cap->cb_head.lh_first; cb; cb =3D cb->entries.le_next) { + if (cb->opaque =3D=3D cb_opaque) { + cb->ops.destroy (cb_opaque); + QLIST_REMOVE (cb, entries); + g_free (cb); + + if (!cap->cb_head.lh_first) { + SWVoiceOut *sw =3D cap->hw.sw_head.lh_first, *sw1; + + while (sw) { + SWVoiceCap *sc =3D (SWVoiceCap *) sw; +#ifdef DEBUG_CAPTURE + dolog ("freeing %s\n", sw->name); +#endif + + sw1 =3D sw->entries.le_next; + if (sw->rate) { + st_rate_stop (sw->rate); + sw->rate =3D NULL; + } + QLIST_REMOVE (sw, entries); + QLIST_REMOVE (sc, entries); + g_free (sc); + sw =3D sw1; + } + QLIST_REMOVE (cap, entries); + g_free(cap->hw.mix_buf.buffer); + g_free (cap->buf); + g_free (cap); + } + return; + } + } +} + +static void audio_driver_set_volume_out(AudioBackend *be, SWVoiceOut *sw, = Volume *vol) +{ + if (sw) { + HWVoiceOut *hw =3D sw->hw; + + sw->vol.mute =3D vol->mute; + sw->vol.l =3D nominal_volume.l * vol->vol[0] / 255; + sw->vol.r =3D nominal_volume.l * vol->vol[vol->channels > 1 ? 1 : = 0] / + 255; + + if (hw->pcm_ops->volume_out) { + hw->pcm_ops->volume_out(hw, vol); + } + } +} + +static void audio_driver_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Vo= lume *vol) +{ + if (sw) { + HWVoiceIn *hw =3D sw->hw; + + sw->vol.mute =3D vol->mute; + sw->vol.l =3D nominal_volume.l * vol->vol[0] / 255; + sw->vol.r =3D nominal_volume.r * vol->vol[vol->channels > 1 ? 1 : = 0] / + 255; + + if (hw->pcm_ops->volume_in) { + hw->pcm_ops->volume_in(hw, vol); + } + } +} + +audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo) +{ + return (audsettings) { + .freq =3D pdo->frequency, + .nchannels =3D pdo->channels, + .fmt =3D pdo->format, + .endianness =3D HOST_BIG_ENDIAN, + }; +} + +int audioformat_bytes_per_sample(AudioFormat fmt) +{ + switch (fmt) { + case AUDIO_FORMAT_U8: + case AUDIO_FORMAT_S8: + return 1; + + case AUDIO_FORMAT_U16: + case AUDIO_FORMAT_S16: + return 2; + + case AUDIO_FORMAT_U32: + case AUDIO_FORMAT_S32: + case AUDIO_FORMAT_F32: + return 4; + + case AUDIO_FORMAT__MAX: + ; + } + abort(); +} + + +/* frames =3D freq * usec / 1e6 */ +int audio_buffer_frames(AudiodevPerDirectionOptions *pdo, + audsettings *as, int def_usecs) +{ + uint64_t usecs =3D pdo->has_buffer_length ? pdo->buffer_length : def_u= secs; + return (as->freq * usecs + 500000) / 1000000; +} + +/* samples =3D channels * frames =3D channels * freq * usec / 1e6 */ +int audio_buffer_samples(AudiodevPerDirectionOptions *pdo, + audsettings *as, int def_usecs) +{ + return as->nchannels * audio_buffer_frames(pdo, as, def_usecs); +} + +/* + * bytes =3D bytes_per_sample * samples =3D + * bytes_per_sample * channels * freq * usec / 1e6 + */ +int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo, + audsettings *as, int def_usecs) +{ + return audio_buffer_samples(pdo, as, def_usecs) * + audioformat_bytes_per_sample(as->fmt); +} + +void audio_rate_start(RateCtl *rate) +{ + memset(rate, 0, sizeof(RateCtl)); + rate->start_ticks =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info) +{ + int64_t now; + int64_t ticks; + int64_t bytes; + int64_t frames; + + now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ticks =3D now - rate->start_ticks; + bytes =3D muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECO= ND); + frames =3D (bytes - rate->bytes_sent) / info->bytes_per_frame; + rate->peeked_frames =3D frames; + + return frames < 0 ? 0 : frames * info->bytes_per_frame; +} + +void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used) +{ + if (rate->peeked_frames < 0 || rate->peeked_frames > 65536) { + AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n", + rate->peeked_frames); + audio_rate_start(rate); + } + + rate->bytes_sent +=3D bytes_used; +} + +size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info, + size_t bytes_avail) +{ + size_t bytes; + + bytes =3D audio_rate_peek_bytes(rate, info); + bytes =3D MIN(bytes, bytes_avail); + audio_rate_add_bytes(rate, bytes); + + return bytes; +} + +static const TypeInfo audio_driver_info =3D { + .name =3D TYPE_AUDIO_DRIVER, + .parent =3D TYPE_AUDIO_BACKEND, + .instance_size =3D sizeof(AudioDriver), + .instance_init =3D audio_driver_init, + .instance_finalize =3D audio_driver_finalize, + .abstract =3D false, + .class_size =3D sizeof(AudioDriverClass), + .class_init =3D audio_driver_class_init, +}; + +static void register_types(void) +{ + type_register_static(&audio_driver_info); +} + +type_init(register_types); diff --git a/audio/audio.c b/audio/audio.c index da2a4da125..ccb16ae3b2 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1,1747 +1,55 @@ -/* - * QEMU Audio subsystem - * - * Copyright (c) 2003-2005 Vassili Karpov (malc) - * - * Permission is hereby granted, free of charge, to any person obtaining a= copy - * of this software and associated documentation files (the "Software"), t= o deal - * in the Software without restriction, including without limitation the r= ights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included= in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "qemu/audio.h" -#include "migration/vmstate.h" -#include "qemu/timer.h" -#include "qapi/error.h" -#include "qapi/clone-visitor.h" -#include "qapi/qobject-input-visitor.h" -#include "qapi/qapi-visit-audio.h" -#include "qapi/qapi-commands-audio.h" -#include "qobject/qdict.h" -#include "qemu/error-report.h" -#include "qemu/log.h" -#include "qemu/module.h" -#include "qemu/help_option.h" -#include "qom/object.h" -#include "system/system.h" -#include "system/replay.h" -#include "system/runstate.h" -#include "trace.h" - -#define AUDIO_CAP "audio" -#include "audio_int.h" - -/* #define DEBUG_LIVE */ -/* #define DEBUG_OUT */ -/* #define DEBUG_CAPTURE */ -/* #define DEBUG_POLL */ - -#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown" - - -/* Order of CONFIG_AUDIO_DRIVERS is import. - The 1st one is the one used by default, that is the reason - that we generate the list. -*/ -const char *audio_prio_list[] =3D { -#ifdef CONFIG_GIO - "dbus", -#endif - "spice", - CONFIG_AUDIO_DRIVERS - "none", - NULL -}; - -typedef struct AudiodevListEntry { - Audiodev *dev; - QSIMPLEQ_ENTRY(AudiodevListEntry) next; -} AudiodevListEntry; - -typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead; - -static AudiodevListHead audiodevs =3D - QSIMPLEQ_HEAD_INITIALIZER(audiodevs); -static AudiodevListHead default_audiodevs =3D - QSIMPLEQ_HEAD_INITIALIZER(default_audiodevs); - -static AudioBackendClass *audio_be_class_by_name(const char *name) -{ - g_autofree char *tname =3D g_strconcat("audio-", name, NULL); - ObjectClass *oc =3D module_object_class_by_name(tname); - - if (!oc || !object_class_dynamic_cast(oc, TYPE_AUDIO_BACKEND)) { - return NULL; - } - - return AUDIO_BACKEND_CLASS(oc); -} - -static AudioBackend *default_audio_be; - -const struct mixeng_volume nominal_volume =3D { - .mute =3D 0, -#ifdef FLOAT_MIXENG - .r =3D 1.0, - .l =3D 1.0, -#else - .r =3D 1ULL << 32, - .l =3D 1ULL << 32, -#endif -}; - -int audio_bug (const char *funcname, int cond) -{ - if (cond) { - static int shown; - - AUD_log (NULL, "A bug was just triggered in %s\n", funcname); - if (!shown) { - shown =3D 1; - AUD_log (NULL, "Save all your work and restart without audio\n= "); - AUD_log (NULL, "I am sorry\n"); - } - AUD_log (NULL, "Context:\n"); - } - - return cond; -} - -static inline int audio_bits_to_index (int bits) -{ - switch (bits) { - case 8: - return 0; - - case 16: - return 1; - - case 32: - return 2; - - default: - audio_bug ("bits_to_index", 1); - AUD_log (NULL, "invalid bits %d\n", bits); - return 0; - } -} - -void AUD_vlog (const char *cap, const char *fmt, va_list ap) -{ - if (cap) { - fprintf(stderr, "%s: ", cap); - } - - vfprintf(stderr, fmt, ap); -} - -void AUD_log (const char *cap, const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - AUD_vlog (cap, fmt, ap); - va_end (ap); -} - -static void audio_print_settings (struct audsettings *as) -{ - dolog ("frequency=3D%d nchannels=3D%d fmt=3D", as->freq, as->nchannels= ); - - switch (as->fmt) { - case AUDIO_FORMAT_S8: - AUD_log (NULL, "S8"); - break; - case AUDIO_FORMAT_U8: - AUD_log (NULL, "U8"); - break; - case AUDIO_FORMAT_S16: - AUD_log (NULL, "S16"); - break; - case AUDIO_FORMAT_U16: - AUD_log (NULL, "U16"); - break; - case AUDIO_FORMAT_S32: - AUD_log (NULL, "S32"); - break; - case AUDIO_FORMAT_U32: - AUD_log (NULL, "U32"); - break; - case AUDIO_FORMAT_F32: - AUD_log (NULL, "F32"); - break; - default: - AUD_log (NULL, "invalid(%d)", as->fmt); - break; - } - - AUD_log (NULL, " endianness=3D"); - switch (as->endianness) { - case 0: - AUD_log (NULL, "little"); - break; - case 1: - AUD_log (NULL, "big"); - break; - default: - AUD_log (NULL, "invalid"); - break; - } - AUD_log (NULL, "\n"); -} - -static int audio_validate_settings (struct audsettings *as) -{ - int invalid; - - invalid =3D as->nchannels < 1; - invalid |=3D as->endianness !=3D 0 && as->endianness !=3D 1; - - switch (as->fmt) { - case AUDIO_FORMAT_S8: - case AUDIO_FORMAT_U8: - case AUDIO_FORMAT_S16: - case AUDIO_FORMAT_U16: - case AUDIO_FORMAT_S32: - case AUDIO_FORMAT_U32: - case AUDIO_FORMAT_F32: - break; - default: - invalid =3D 1; - break; - } - - invalid |=3D as->freq <=3D 0; - return invalid ? -1 : 0; -} - -static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsetti= ngs *as) -{ - int bits =3D 8; - bool is_signed =3D false, is_float =3D false; - - switch (as->fmt) { - case AUDIO_FORMAT_S8: - is_signed =3D true; - /* fall through */ - case AUDIO_FORMAT_U8: - break; - - case AUDIO_FORMAT_S16: - is_signed =3D true; - /* fall through */ - case AUDIO_FORMAT_U16: - bits =3D 16; - break; - - case AUDIO_FORMAT_F32: - is_float =3D true; - /* fall through */ - case AUDIO_FORMAT_S32: - is_signed =3D true; - /* fall through */ - case AUDIO_FORMAT_U32: - bits =3D 32; - break; - - default: - abort(); - } - return info->freq =3D=3D as->freq - && info->nchannels =3D=3D as->nchannels - && info->is_signed =3D=3D is_signed - && info->is_float =3D=3D is_float - && info->bits =3D=3D bits - && info->swap_endianness =3D=3D (as->endianness !=3D HOST_BIG_ENDI= AN); -} - -void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings = *as) -{ - int bits =3D 8, mul; - bool is_signed =3D false, is_float =3D false; - - switch (as->fmt) { - case AUDIO_FORMAT_S8: - is_signed =3D true; - /* fall through */ - case AUDIO_FORMAT_U8: - mul =3D 1; - break; - - case AUDIO_FORMAT_S16: - is_signed =3D true; - /* fall through */ - case AUDIO_FORMAT_U16: - bits =3D 16; - mul =3D 2; - break; - - case AUDIO_FORMAT_F32: - is_float =3D true; - /* fall through */ - case AUDIO_FORMAT_S32: - is_signed =3D true; - /* fall through */ - case AUDIO_FORMAT_U32: - bits =3D 32; - mul =3D 4; - break; - - default: - abort(); - } - - info->freq =3D as->freq; - info->bits =3D bits; - info->is_signed =3D is_signed; - info->is_float =3D is_float; - info->nchannels =3D as->nchannels; - info->bytes_per_frame =3D as->nchannels * mul; - info->bytes_per_second =3D info->freq * info->bytes_per_frame; - info->swap_endianness =3D (as->endianness !=3D HOST_BIG_ENDIAN); -} - -void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int= len) -{ - if (!len) { - return; - } - - if (info->is_signed || info->is_float) { - memset(buf, 0x00, len * info->bytes_per_frame); - } else { - switch (info->bits) { - case 8: - memset(buf, 0x80, len * info->bytes_per_frame); - break; - - case 16: - { - int i; - uint16_t *p =3D buf; - short s =3D INT16_MAX; - - if (info->swap_endianness) { - s =3D bswap16 (s); - } - - for (i =3D 0; i < len * info->nchannels; i++) { - p[i] =3D s; - } - } - break; - - case 32: - { - int i; - uint32_t *p =3D buf; - int32_t s =3D INT32_MAX; - - if (info->swap_endianness) { - s =3D bswap32 (s); - } - - for (i =3D 0; i < len * info->nchannels; i++) { - p[i] =3D s; - } - } - break; - - default: - AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n", - info->bits); - break; - } - } -} - -/* - * Capture - */ -static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioDriver *s, - struct audsettings= *as) -{ - CaptureVoiceOut *cap; - - for (cap =3D s->cap_head.lh_first; cap; cap =3D cap->entries.le_next) { - if (audio_pcm_info_eq (&cap->hw.info, as)) { - return cap; - } - } - return NULL; -} - -static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e= cmd) -{ - struct capture_callback *cb; - -#ifdef DEBUG_CAPTURE - dolog ("notification %d sent\n", cmd); -#endif - for (cb =3D cap->cb_head.lh_first; cb; cb =3D cb->entries.le_next) { - cb->ops.notify (cb->opaque, cmd); - } -} - -static void audio_capture_maybe_changed(CaptureVoiceOut *cap, bool enabled) -{ - if (cap->hw.enabled !=3D enabled) { - audcnotification_e cmd; - cap->hw.enabled =3D enabled; - cmd =3D enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE; - audio_notify_capture (cap, cmd); - } -} - -static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap) -{ - HWVoiceOut *hw =3D &cap->hw; - SWVoiceOut *sw; - bool enabled =3D false; - - for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { - if (sw->active) { - enabled =3D true; - break; - } - } - audio_capture_maybe_changed (cap, enabled); -} - -static void audio_detach_capture (HWVoiceOut *hw) -{ - SWVoiceCap *sc =3D hw->cap_head.lh_first; - - while (sc) { - SWVoiceCap *sc1 =3D sc->entries.le_next; - SWVoiceOut *sw =3D &sc->sw; - CaptureVoiceOut *cap =3D sc->cap; - int was_active =3D sw->active; - - if (sw->rate) { - st_rate_stop (sw->rate); - sw->rate =3D NULL; - } - - QLIST_REMOVE (sw, entries); - QLIST_REMOVE (sc, entries); - g_free (sc); - if (was_active) { - /* We have removed soft voice from the capture: - this might have changed the overall status of the capture - since this might have been the only active voice */ - audio_recalc_and_notify_capture (cap); - } - sc =3D sc1; - } -} - -static int audio_attach_capture (HWVoiceOut *hw) -{ - AudioDriver *s =3D hw->s; - CaptureVoiceOut *cap; - - audio_detach_capture (hw); - for (cap =3D s->cap_head.lh_first; cap; cap =3D cap->entries.le_next) { - SWVoiceCap *sc; - SWVoiceOut *sw; - HWVoiceOut *hw_cap =3D &cap->hw; - - sc =3D g_malloc0(sizeof(*sc)); - - sc->cap =3D cap; - sw =3D &sc->sw; - sw->hw =3D hw_cap; - sw->info =3D hw->info; - sw->empty =3D true; - sw->active =3D hw->enabled; - sw->vol =3D nominal_volume; - sw->rate =3D st_rate_start (sw->info.freq, hw_cap->info.freq); - QLIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries); - QLIST_INSERT_HEAD (&hw->cap_head, sc, entries); -#ifdef DEBUG_CAPTURE - sw->name =3D g_strdup_printf ("for %p %d,%d,%d", - hw, sw->info.freq, sw->info.bits, - sw->info.nchannels); - dolog ("Added %s active =3D %d\n", sw->name, sw->active); -#endif - if (sw->active) { - audio_capture_maybe_changed (cap, 1); - } - } - return 0; -} - -/* - * Hard voice (capture) - */ -static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) -{ - SWVoiceIn *sw; - size_t m =3D hw->total_samples_captured; - - for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { - if (sw->active) { - m =3D MIN (m, sw->total_hw_samples_acquired); - } - } - return m; -} - -static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) -{ - size_t live =3D hw->total_samples_captured - audio_pcm_hw_find_min_in = (hw); - if (audio_bug(__func__, live > hw->conv_buf.size)) { - dolog("live=3D%zu hw->conv_buf.size=3D%zu\n", live, hw->conv_buf.s= ize); - return 0; - } - return live; -} - -static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t sa= mples) -{ - size_t conv =3D 0; - STSampleBuffer *conv_buf =3D &hw->conv_buf; - - while (samples) { - uint8_t *src =3D advance(pcm_buf, conv * hw->info.bytes_per_frame); - size_t proc =3D MIN(samples, conv_buf->size - conv_buf->pos); - - hw->conv(conv_buf->buffer + conv_buf->pos, src, proc); - conv_buf->pos =3D (conv_buf->pos + proc) % conv_buf->size; - samples -=3D proc; - conv +=3D proc; - } - - return conv; -} - -/* - * Soft voice (capture) - */ -static void audio_pcm_sw_resample_in(SWVoiceIn *sw, - size_t frames_in_max, size_t frames_out_max, - size_t *total_in, size_t *total_out) -{ - HWVoiceIn *hw =3D sw->hw; - struct st_sample *src, *dst; - size_t live, rpos, frames_in, frames_out; - - live =3D hw->total_samples_captured - sw->total_hw_samples_acquired; - rpos =3D audio_ring_posb(hw->conv_buf.pos, live, hw->conv_buf.size); - - /* resample conv_buf from rpos to end of buffer */ - src =3D hw->conv_buf.buffer + rpos; - frames_in =3D MIN(frames_in_max, hw->conv_buf.size - rpos); - dst =3D sw->resample_buf.buffer; - frames_out =3D frames_out_max; - st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out); - rpos +=3D frames_in; - *total_in =3D frames_in; - *total_out =3D frames_out; - - /* resample conv_buf from start of buffer if there are input frames le= ft */ - if (frames_in_max - frames_in && rpos =3D=3D hw->conv_buf.size) { - src =3D hw->conv_buf.buffer; - frames_in =3D frames_in_max - frames_in; - dst +=3D frames_out; - frames_out =3D frames_out_max - frames_out; - st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out); - *total_in +=3D frames_in; - *total_out +=3D frames_out; - } -} - -static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t buf_len) -{ - HWVoiceIn *hw =3D sw->hw; - size_t live, frames_out_max, total_in, total_out; - - live =3D hw->total_samples_captured - sw->total_hw_samples_acquired; - if (!live) { - return 0; - } - if (audio_bug(__func__, live > hw->conv_buf.size)) { - dolog("live_in=3D%zu hw->conv_buf.size=3D%zu\n", live, hw->conv_bu= f.size); - return 0; - } - - frames_out_max =3D MIN(buf_len / sw->info.bytes_per_frame, - sw->resample_buf.size); - - audio_pcm_sw_resample_in(sw, live, frames_out_max, &total_in, &total_o= ut); - - if (!hw->pcm_ops->volume_in) { - mixeng_volume(sw->resample_buf.buffer, total_out, &sw->vol); - } - sw->clip(buf, sw->resample_buf.buffer, total_out); - - sw->total_hw_samples_acquired +=3D total_in; - return total_out * sw->info.bytes_per_frame; -} - -/* - * Hard voice (playback) - */ -static size_t audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep) -{ - SWVoiceOut *sw; - size_t m =3D SIZE_MAX; - int nb_live =3D 0; - - for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { - if (sw->active || !sw->empty) { - m =3D MIN (m, sw->total_hw_samples_mixed); - nb_live +=3D 1; - } - } - - *nb_livep =3D nb_live; - return m; -} - -static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live) -{ - size_t smin; - int nb_live1; - - smin =3D audio_pcm_hw_find_min_out (hw, &nb_live1); - if (nb_live) { - *nb_live =3D nb_live1; - } - - if (nb_live1) { - size_t live =3D smin; - - if (audio_bug(__func__, live > hw->mix_buf.size)) { - dolog("live=3D%zu hw->mix_buf.size=3D%zu\n", live, hw->mix_buf= .size); - return 0; - } - return live; - } - return 0; -} - -static size_t audio_pcm_hw_get_free(HWVoiceOut *hw) -{ - return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw= ) : - INT_MAX) / hw->info.bytes_per_frame; -} - -static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t le= n) -{ - size_t clipped =3D 0; - size_t pos =3D hw->mix_buf.pos; - - while (len) { - st_sample *src =3D hw->mix_buf.buffer + pos; - uint8_t *dst =3D advance(pcm_buf, clipped * hw->info.bytes_per_fra= me); - size_t samples_till_end_of_buf =3D hw->mix_buf.size - pos; - size_t samples_to_clip =3D MIN(len, samples_till_end_of_buf); - - hw->clip(dst, src, samples_to_clip); - - pos =3D (pos + samples_to_clip) % hw->mix_buf.size; - len -=3D samples_to_clip; - clipped +=3D samples_to_clip; - } -} - -/* - * Soft voice (playback) - */ -static void audio_pcm_sw_resample_out(SWVoiceOut *sw, - size_t frames_in_max, size_t frames_out_max, - size_t *total_in, size_t *total_out) -{ - HWVoiceOut *hw =3D sw->hw; - struct st_sample *src, *dst; - size_t live, wpos, frames_in, frames_out; - - live =3D sw->total_hw_samples_mixed; - wpos =3D (hw->mix_buf.pos + live) % hw->mix_buf.size; - - /* write to mix_buf from wpos to end of buffer */ - src =3D sw->resample_buf.buffer; - frames_in =3D frames_in_max; - dst =3D hw->mix_buf.buffer + wpos; - frames_out =3D MIN(frames_out_max, hw->mix_buf.size - wpos); - st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out); - wpos +=3D frames_out; - *total_in =3D frames_in; - *total_out =3D frames_out; - - /* write to mix_buf from start of buffer if there are input frames lef= t */ - if (frames_in_max - frames_in > 0 && wpos =3D=3D hw->mix_buf.size) { - src +=3D frames_in; - frames_in =3D frames_in_max - frames_in; - dst =3D hw->mix_buf.buffer; - frames_out =3D frames_out_max - frames_out; - st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out); - *total_in +=3D frames_in; - *total_out +=3D frames_out; - } -} - -static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len) -{ - HWVoiceOut *hw =3D sw->hw; - size_t live, dead, hw_free, sw_max, fe_max; - size_t frames_in_max, frames_out_max, total_in, total_out; - - live =3D sw->total_hw_samples_mixed; - if (audio_bug(__func__, live > hw->mix_buf.size)) { - dolog("live=3D%zu hw->mix_buf.size=3D%zu\n", live, hw->mix_buf.siz= e); - return 0; - } - - if (live =3D=3D hw->mix_buf.size) { -#ifdef DEBUG_OUT - dolog ("%s is full %zu\n", sw->name, live); -#endif - return 0; - } - - dead =3D hw->mix_buf.size - live; - hw_free =3D audio_pcm_hw_get_free(hw); - hw_free =3D hw_free > live ? hw_free - live : 0; - frames_out_max =3D MIN(dead, hw_free); - sw_max =3D st_rate_frames_in(sw->rate, frames_out_max); - fe_max =3D MIN(buf_len / sw->info.bytes_per_frame + sw->resample_buf.p= os, - sw->resample_buf.size); - frames_in_max =3D MIN(sw_max, fe_max); - - if (!frames_in_max) { - return 0; - } - - if (frames_in_max > sw->resample_buf.pos) { - sw->conv(sw->resample_buf.buffer + sw->resample_buf.pos, - buf, frames_in_max - sw->resample_buf.pos); - if (!sw->hw->pcm_ops->volume_out) { - mixeng_volume(sw->resample_buf.buffer + sw->resample_buf.pos, - frames_in_max - sw->resample_buf.pos, &sw->vol); - } - } - - audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max, - &total_in, &total_out); - - sw->total_hw_samples_mixed +=3D total_out; - sw->empty =3D sw->total_hw_samples_mixed =3D=3D 0; - - /* - * Upsampling may leave one audio frame in the resample buffer. Decrem= ent - * total_in by one if there was a leftover frame from the previous res= ample - * pass in the resample buffer. Increment total_in by one if the curre= nt - * resample pass left one frame in the resample buffer. - */ - if (frames_in_max - total_in =3D=3D 1) { - /* copy one leftover audio frame to the beginning of the buffer */ - *sw->resample_buf.buffer =3D *(sw->resample_buf.buffer + total_in); - total_in +=3D 1 - sw->resample_buf.pos; - sw->resample_buf.pos =3D 1; - } else if (total_in >=3D sw->resample_buf.pos) { - total_in -=3D sw->resample_buf.pos; - sw->resample_buf.pos =3D 0; - } - -#ifdef DEBUG_OUT - dolog ( - "%s: write size %zu written %zu total mixed %zu\n", - SW_NAME(sw), - buf_len / sw->info.bytes_per_frame, - total_in, - sw->total_hw_samples_mixed - ); -#endif - - return total_in * sw->info.bytes_per_frame; -} - -#ifdef DEBUG_AUDIO -static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *= info) -{ - dolog("%s: bits %d, sign %d, float %d, freq %d, nchan %d\n", - cap, info->bits, info->is_signed, info->is_float, info->freq, - info->nchannels); -} -#endif - -#define DAC -#include "audio_template.h" -#undef DAC -#include "audio_template.h" - -/* - * Timer - */ -static int audio_is_timer_needed(AudioDriver *s) -{ - HWVoiceIn *hwi =3D NULL; - HWVoiceOut *hwo =3D NULL; - - while ((hwo =3D audio_pcm_hw_find_any_enabled_out(s, hwo))) { - if (!hwo->poll_mode) { - return 1; - } - } - while ((hwi =3D audio_pcm_hw_find_any_enabled_in(s, hwi))) { - if (!hwi->poll_mode) { - return 1; - } - } - return 0; -} - -static void audio_reset_timer(AudioDriver *s) -{ - if (audio_is_timer_needed(s)) { - timer_mod_anticipate_ns(s->ts, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->period_ticks); - if (!s->timer_running) { - s->timer_running =3D true; - s->timer_last =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - trace_audio_timer_start(s->period_ticks / SCALE_MS); - } - } else { - timer_del(s->ts); - if (s->timer_running) { - s->timer_running =3D false; - trace_audio_timer_stop(); - } - } -} - -static void audio_timer (void *opaque) -{ - int64_t now, diff; - AudioDriver *s =3D opaque; - - now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - diff =3D now - s->timer_last; - if (diff > s->period_ticks * 3 / 2) { - trace_audio_timer_delayed(diff / SCALE_MS); - } - s->timer_last =3D now; - - audio_run(s, "timer"); - audio_reset_timer(s); -} - -/* - * Public API - */ - static size_t audio_driver_write(AudioBackend *be, SWVoiceOut *sw, void *= buf, size_t size) - { - HWVoiceOut *hw; - - if (!sw) { - /* XXX: Consider options */ - return size; - } - hw =3D sw->hw; - - if (!hw->enabled) { - dolog ("Writing to disabled voice %s\n", SW_NAME (sw)); - return 0; - } - - if (audio_get_pdo_out(hw->s->dev)->mixing_engine) { - return audio_pcm_sw_write(sw, buf, size); - } else { - return hw->pcm_ops->write(hw, buf, size); - } - } - -static size_t audio_driver_read(AudioBackend *be, SWVoiceIn *sw, void *buf= , size_t size) -{ - HWVoiceIn *hw; - - if (!sw) { - /* XXX: Consider options */ - return size; - } - hw =3D sw->hw; - - if (!hw->enabled) { - dolog ("Reading from disabled voice %s\n", SW_NAME (sw)); - return 0; - } - - if (audio_get_pdo_in(hw->s->dev)->mixing_engine) { - return audio_pcm_sw_read(sw, buf, size); - } else { - return hw->pcm_ops->read(hw, buf, size); - } - -} - -static int audio_driver_get_buffer_size_out(AudioBackend *be, SWVoiceOut *= sw) -{ - if (!sw) { - return 0; - } - - if (audio_get_pdo_out(sw->s->dev)->mixing_engine) { - return sw->resample_buf.size * sw->info.bytes_per_frame; - } - - return sw->hw->samples * sw->hw->info.bytes_per_frame; -} - -static void audio_driver_set_active_out(AudioBackend *be, SWVoiceOut *sw, = bool on) -{ - HWVoiceOut *hw; - - if (!sw) { - return; - } - - hw =3D sw->hw; - if (sw->active !=3D on) { - AudioDriver *s =3D sw->s; - SWVoiceOut *temp_sw; - SWVoiceCap *sc; - - if (on) { - hw->pending_disable =3D 0; - if (!hw->enabled) { - hw->enabled =3D true; - if (s->vm_running) { - if (hw->pcm_ops->enable_out) { - hw->pcm_ops->enable_out(hw, true); - } - audio_reset_timer (s); - } - } - } else { - if (hw->enabled) { - int nb_active =3D 0; - - for (temp_sw =3D hw->sw_head.lh_first; temp_sw; - temp_sw =3D temp_sw->entries.le_next) { - nb_active +=3D temp_sw->active !=3D 0; - } - - hw->pending_disable =3D nb_active =3D=3D 1; - } - } - - for (sc =3D hw->cap_head.lh_first; sc; sc =3D sc->entries.le_next)= { - sc->sw.active =3D hw->enabled; - if (hw->enabled) { - audio_capture_maybe_changed (sc->cap, 1); - } - } - sw->active =3D on; - } - -} - -static void audio_driver_set_active_in(AudioBackend *be, SWVoiceIn *sw, bo= ol on) -{ - HWVoiceIn *hw; - - if (!sw) { - return; - } - - hw =3D sw->hw; - if (sw->active !=3D on) { - AudioDriver *s =3D sw->s; - SWVoiceIn *temp_sw; - - if (on) { - if (!hw->enabled) { - hw->enabled =3D true; - if (s->vm_running) { - if (hw->pcm_ops->enable_in) { - hw->pcm_ops->enable_in(hw, true); - } - audio_reset_timer (s); - } - } - sw->total_hw_samples_acquired =3D hw->total_samples_captured; - } else { - if (hw->enabled) { - int nb_active =3D 0; - - for (temp_sw =3D hw->sw_head.lh_first; temp_sw; - temp_sw =3D temp_sw->entries.le_next) { - nb_active +=3D temp_sw->active !=3D 0; - } - - if (nb_active =3D=3D 1) { - hw->enabled =3D false; - if (hw->pcm_ops->enable_in) { - hw->pcm_ops->enable_in(hw, false); - } - } - } - } - sw->active =3D on; - } -} - -static size_t audio_get_avail(SWVoiceIn *sw) -{ - size_t live; - - if (!sw) { - return 0; - } - - live =3D sw->hw->total_samples_captured - sw->total_hw_samples_acquire= d; - if (audio_bug(__func__, live > sw->hw->conv_buf.size)) { - dolog("live=3D%zu sw->hw->conv_buf.size=3D%zu\n", live, - sw->hw->conv_buf.size); - return 0; - } - - ldebug ( - "%s: get_avail live %zu frontend frames %u\n", - SW_NAME (sw), - live, st_rate_frames_out(sw->rate, live) - ); - - return live; -} - -static size_t audio_get_free(SWVoiceOut *sw) -{ - size_t live, dead; - - if (!sw) { - return 0; - } - - live =3D sw->total_hw_samples_mixed; - - if (audio_bug(__func__, live > sw->hw->mix_buf.size)) { - dolog("live=3D%zu sw->hw->mix_buf.size=3D%zu\n", live, - sw->hw->mix_buf.size); - return 0; - } - - dead =3D sw->hw->mix_buf.size - live; - -#ifdef DEBUG_OUT - dolog("%s: get_free live %zu dead %zu frontend frames %u\n", - SW_NAME(sw), live, dead, st_rate_frames_in(sw->rate, dead)); -#endif - - return dead; -} - -static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, - size_t samples) -{ - size_t n; - - if (hw->enabled) { - SWVoiceCap *sc; - - for (sc =3D hw->cap_head.lh_first; sc; sc =3D sc->entries.le_next)= { - SWVoiceOut *sw =3D &sc->sw; - size_t rpos2 =3D rpos; - - n =3D samples; - while (n) { - size_t till_end_of_hw =3D hw->mix_buf.size - rpos2; - size_t to_read =3D MIN(till_end_of_hw, n); - size_t live, frames_in, frames_out; - - sw->resample_buf.buffer =3D hw->mix_buf.buffer + rpos2; - sw->resample_buf.size =3D to_read; - live =3D sw->total_hw_samples_mixed; - - audio_pcm_sw_resample_out(sw, - to_read, sw->hw->mix_buf.size - = live, - &frames_in, &frames_out); - - sw->total_hw_samples_mixed +=3D frames_out; - sw->empty =3D sw->total_hw_samples_mixed =3D=3D 0; - - if (to_read - frames_in) { - dolog("Could not mix %zu frames into a capture " - "buffer, mixed %zu\n", - to_read, frames_in); - break; - } - n -=3D to_read; - rpos2 =3D (rpos2 + to_read) % hw->mix_buf.size; - } - } - } - - n =3D MIN(samples, hw->mix_buf.size - rpos); - mixeng_clear(hw->mix_buf.buffer + rpos, n); - mixeng_clear(hw->mix_buf.buffer, samples - n); -} - -static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) -{ - size_t clipped =3D 0; - - while (live) { - size_t size =3D live * hw->info.bytes_per_frame; - size_t decr, proc; - void *buf =3D hw->pcm_ops->get_buffer_out(hw, &size); - - if (size =3D=3D 0) { - break; - } - - decr =3D MIN(size / hw->info.bytes_per_frame, live); - if (buf) { - audio_pcm_hw_clip_out(hw, buf, decr); - } - proc =3D hw->pcm_ops->put_buffer_out(hw, buf, - decr * hw->info.bytes_per_frame= ) / - hw->info.bytes_per_frame; - - live -=3D proc; - clipped +=3D proc; - hw->mix_buf.pos =3D (hw->mix_buf.pos + proc) % hw->mix_buf.size; - - if (proc =3D=3D 0 || proc < decr) { - break; - } - } - - if (hw->pcm_ops->run_buffer_out) { - hw->pcm_ops->run_buffer_out(hw); - } - - return clipped; -} - -static void audio_run_out(AudioDriver *s) -{ - HWVoiceOut *hw =3D NULL; - SWVoiceOut *sw; - - while ((hw =3D audio_pcm_hw_find_any_enabled_out(s, hw))) { - size_t played, live, prev_rpos; - size_t hw_free =3D audio_pcm_hw_get_free(hw); - int nb_live; - - if (!audio_get_pdo_out(s->dev)->mixing_engine) { - /* there is exactly 1 sw for each hw with no mixeng */ - sw =3D hw->sw_head.lh_first; - - if (hw->pending_disable) { - hw->enabled =3D false; - hw->pending_disable =3D false; - if (hw->pcm_ops->enable_out) { - hw->pcm_ops->enable_out(hw, false); - } - } - - if (sw->active) { - sw->callback.fn(sw->callback.opaque, - hw_free * sw->info.bytes_per_frame); - } - - if (hw->pcm_ops->run_buffer_out) { - hw->pcm_ops->run_buffer_out(hw); - } - - continue; - } - - for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { - if (sw->active) { - size_t sw_free =3D audio_get_free(sw); - size_t free; - - if (hw_free > sw->total_hw_samples_mixed) { - free =3D st_rate_frames_in(sw->rate, - MIN(sw_free, hw_free - sw->total_hw_samples_mixed)= ); - } else { - free =3D 0; - } - if (free > sw->resample_buf.pos) { - free =3D MIN(free, sw->resample_buf.size) - - sw->resample_buf.pos; - sw->callback.fn(sw->callback.opaque, - free * sw->info.bytes_per_frame); - } - } - } - - live =3D audio_pcm_hw_get_live_out (hw, &nb_live); - if (!nb_live) { - live =3D 0; - } - - if (audio_bug(__func__, live > hw->mix_buf.size)) { - dolog("live=3D%zu hw->mix_buf.size=3D%zu\n", live, hw->mix_buf= .size); - continue; - } - - if (hw->pending_disable && !nb_live) { - SWVoiceCap *sc; -#ifdef DEBUG_OUT - dolog ("Disabling voice\n"); -#endif - hw->enabled =3D false; - hw->pending_disable =3D false; - if (hw->pcm_ops->enable_out) { - hw->pcm_ops->enable_out(hw, false); - } - for (sc =3D hw->cap_head.lh_first; sc; sc =3D sc->entries.le_n= ext) { - sc->sw.active =3D false; - audio_recalc_and_notify_capture (sc->cap); - } - continue; - } - - if (!live) { - if (hw->pcm_ops->run_buffer_out) { - hw->pcm_ops->run_buffer_out(hw); - } - continue; - } - - prev_rpos =3D hw->mix_buf.pos; - played =3D audio_pcm_hw_run_out(hw, live); - replay_audio_out(&played); - if (audio_bug(__func__, hw->mix_buf.pos >=3D hw->mix_buf.size)) { - dolog("hw->mix_buf.pos=3D%zu hw->mix_buf.size=3D%zu played=3D%= zu\n", - hw->mix_buf.pos, hw->mix_buf.size, played); - hw->mix_buf.pos =3D 0; - } - -#ifdef DEBUG_OUT - dolog("played=3D%zu\n", played); -#endif - - if (played) { - hw->ts_helper +=3D played; - audio_capture_mix_and_clear (hw, prev_rpos, played); - } - - for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { - if (!sw->active && sw->empty) { - continue; - } - - if (audio_bug(__func__, played > sw->total_hw_samples_mixed)) { - dolog("played=3D%zu sw->total_hw_samples_mixed=3D%zu\n", - played, sw->total_hw_samples_mixed); - played =3D sw->total_hw_samples_mixed; - } - - sw->total_hw_samples_mixed -=3D played; - - if (!sw->total_hw_samples_mixed) { - sw->empty =3D true; - } - } - } -} - -static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) -{ - size_t conv =3D 0; - - if (hw->pcm_ops->run_buffer_in) { - hw->pcm_ops->run_buffer_in(hw); - } - - while (samples) { - size_t proc; - size_t size =3D samples * hw->info.bytes_per_frame; - void *buf =3D hw->pcm_ops->get_buffer_in(hw, &size); - - assert(size % hw->info.bytes_per_frame =3D=3D 0); - if (size =3D=3D 0) { - break; - } - - proc =3D audio_pcm_hw_conv_in(hw, buf, size / hw->info.bytes_per_f= rame); - - samples -=3D proc; - conv +=3D proc; - hw->pcm_ops->put_buffer_in(hw, buf, proc * hw->info.bytes_per_fram= e); - } - - return conv; -} - -static void audio_run_in(AudioDriver *s) -{ - HWVoiceIn *hw =3D NULL; - - if (!audio_get_pdo_in(s->dev)->mixing_engine) { - while ((hw =3D audio_pcm_hw_find_any_enabled_in(s, hw))) { - /* there is exactly 1 sw for each hw with no mixeng */ - SWVoiceIn *sw =3D hw->sw_head.lh_first; - if (sw->active) { - sw->callback.fn(sw->callback.opaque, INT_MAX); - } - } - return; - } - - while ((hw =3D audio_pcm_hw_find_any_enabled_in(s, hw))) { - SWVoiceIn *sw; - size_t captured =3D 0, min; - int pos; - - if (replay_mode !=3D REPLAY_MODE_PLAY) { - captured =3D audio_pcm_hw_run_in( - hw, hw->conv_buf.size - audio_pcm_hw_get_live_in(hw)); - } - - replay_audio_in_start(&captured); - assert(captured <=3D hw->conv_buf.size); - if (replay_mode =3D=3D REPLAY_MODE_PLAY) { - hw->conv_buf.pos =3D (hw->conv_buf.pos + captured) % hw->conv_= buf.size; - } - for (pos =3D (hw->conv_buf.pos - captured + hw->conv_buf.size) % h= w->conv_buf.size; - pos !=3D hw->conv_buf.pos; - pos =3D (pos + 1) % hw->conv_buf.size) { - uint64_t left, right; - - if (replay_mode =3D=3D REPLAY_MODE_RECORD) { - audio_sample_to_uint64(hw->conv_buf.buffer, pos, &left= , &right); - } - replay_audio_in_sample_lr(&left, &right); - if (replay_mode =3D=3D REPLAY_MODE_PLAY) { - audio_sample_from_uint64(hw->conv_buf.buffer, pos, lef= t, right); - } - } - replay_audio_in_finish(); - - min =3D audio_pcm_hw_find_min_in (hw); - hw->total_samples_captured +=3D captured - min; - hw->ts_helper +=3D captured; - - for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { - sw->total_hw_samples_acquired -=3D min; - - if (sw->active) { - size_t sw_avail =3D audio_get_avail(sw); - size_t avail; - - avail =3D st_rate_frames_out(sw->rate, sw_avail); - if (avail > 0) { - avail =3D MIN(avail, sw->resample_buf.size); - sw->callback.fn(sw->callback.opaque, - avail * sw->info.bytes_per_frame); - } - } - } - } -} - -static void audio_run_capture(AudioDriver *s) -{ - CaptureVoiceOut *cap; - - for (cap =3D s->cap_head.lh_first; cap; cap =3D cap->entries.le_next) { - size_t live, rpos, captured; - HWVoiceOut *hw =3D &cap->hw; - SWVoiceOut *sw; - - captured =3D live =3D audio_pcm_hw_get_live_out (hw, NULL); - rpos =3D hw->mix_buf.pos; - while (live) { - size_t left =3D hw->mix_buf.size - rpos; - size_t to_capture =3D MIN(live, left); - struct st_sample *src; - struct capture_callback *cb; - - src =3D hw->mix_buf.buffer + rpos; - hw->clip (cap->buf, src, to_capture); - mixeng_clear (src, to_capture); - - for (cb =3D cap->cb_head.lh_first; cb; cb =3D cb->entries.le_n= ext) { - cb->ops.capture (cb->opaque, cap->buf, - to_capture * hw->info.bytes_per_frame); - } - rpos =3D (rpos + to_capture) % hw->mix_buf.size; - live -=3D to_capture; - } - hw->mix_buf.pos =3D rpos; - - for (sw =3D hw->sw_head.lh_first; sw; sw =3D sw->entries.le_next) { - if (!sw->active && sw->empty) { - continue; - } - - if (audio_bug(__func__, captured > sw->total_hw_samples_mixed)= ) { - dolog("captured=3D%zu sw->total_hw_samples_mixed=3D%zu\n", - captured, sw->total_hw_samples_mixed); - captured =3D sw->total_hw_samples_mixed; - } - - sw->total_hw_samples_mixed -=3D captured; - sw->empty =3D sw->total_hw_samples_mixed =3D=3D 0; - } - } -} - -void audio_run(AudioDriver *s, const char *msg) -{ - audio_run_out(s); - audio_run_in(s); - audio_run_capture(s); - -#ifdef DEBUG_POLL - { - static double prevtime; - double currtime; - struct timeval tv; - - if (gettimeofday (&tv, NULL)) { - perror ("audio_run: gettimeofday"); - return; - } - - currtime =3D tv.tv_sec + tv.tv_usec * 1e-6; - dolog ("Elapsed since last %s: %f\n", msg, currtime - prevtime); - prevtime =3D currtime; - } -#endif -} - -void audio_generic_run_buffer_in(HWVoiceIn *hw) -{ - if (unlikely(!hw->buf_emul)) { - hw->size_emul =3D hw->samples * hw->info.bytes_per_frame; - hw->buf_emul =3D g_malloc(hw->size_emul); - hw->pos_emul =3D hw->pending_emul =3D 0; - } - - while (hw->pending_emul < hw->size_emul) { - size_t read_len =3D MIN(hw->size_emul - hw->pos_emul, - hw->size_emul - hw->pending_emul); - size_t read =3D hw->pcm_ops->read(hw, hw->buf_emul + hw->pos_emul, - read_len); - hw->pending_emul +=3D read; - hw->pos_emul =3D (hw->pos_emul + read) % hw->size_emul; - if (read < read_len) { - break; - } - } -} - -void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size) -{ - size_t start; - - start =3D audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emu= l); - assert(start < hw->size_emul); - - *size =3D MIN(*size, hw->pending_emul); - *size =3D MIN(*size, hw->size_emul - start); - return hw->buf_emul + start; -} - -void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size) -{ - assert(size <=3D hw->pending_emul); - hw->pending_emul -=3D size; -} - -size_t audio_generic_buffer_get_free(HWVoiceOut *hw) -{ - if (hw->buf_emul) { - return hw->size_emul - hw->pending_emul; - } else { - return hw->samples * hw->info.bytes_per_frame; - } -} - -void audio_generic_run_buffer_out(HWVoiceOut *hw) -{ - while (hw->pending_emul) { - size_t write_len, written, start; - - start =3D audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size= _emul); - assert(start < hw->size_emul); - - write_len =3D MIN(hw->pending_emul, hw->size_emul - start); - - written =3D hw->pcm_ops->write(hw, hw->buf_emul + start, write_len= ); - hw->pending_emul -=3D written; - - if (written < write_len) { - break; - } - } -} - -void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size) -{ - if (unlikely(!hw->buf_emul)) { - hw->size_emul =3D hw->samples * hw->info.bytes_per_frame; - hw->buf_emul =3D g_malloc(hw->size_emul); - hw->pos_emul =3D hw->pending_emul =3D 0; - } - - *size =3D MIN(hw->size_emul - hw->pending_emul, - hw->size_emul - hw->pos_emul); - return hw->buf_emul + hw->pos_emul; -} - -size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) -{ - assert(buf =3D=3D hw->buf_emul + hw->pos_emul && - size + hw->pending_emul <=3D hw->size_emul); - - hw->pending_emul +=3D size; - hw->pos_emul =3D (hw->pos_emul + size) % hw->size_emul; - - return size; -} - -size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size) -{ - size_t total =3D 0; - - if (hw->pcm_ops->buffer_get_free) { - size_t free =3D hw->pcm_ops->buffer_get_free(hw); - - size =3D MIN(size, free); - } - - while (total < size) { - size_t dst_size =3D size - total; - size_t copy_size, proc; - void *dst =3D hw->pcm_ops->get_buffer_out(hw, &dst_size); - - if (dst_size =3D=3D 0) { - break; - } - - copy_size =3D MIN(size - total, dst_size); - if (dst) { - memcpy(dst, (char *)buf + total, copy_size); - } - proc =3D hw->pcm_ops->put_buffer_out(hw, dst, copy_size); - total +=3D proc; - - if (proc =3D=3D 0 || proc < copy_size) { - break; - } - } - - return total; -} - -size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) -{ - size_t total =3D 0; - - if (hw->pcm_ops->run_buffer_in) { - hw->pcm_ops->run_buffer_in(hw); - } - - while (total < size) { - size_t src_size =3D size - total; - void *src =3D hw->pcm_ops->get_buffer_in(hw, &src_size); - - if (src_size =3D=3D 0) { - break; - } - - memcpy((char *)buf + total, src, src_size); - hw->pcm_ops->put_buffer_in(hw, src, src_size); - total +=3D src_size; - } - - return total; -} - -static bool audio_be_driver_realize(AudioBackend *abe, Audiodev *dev, Erro= r **errp) -{ - AudioDriver *d =3D AUDIO_DRIVER(abe); - audio_driver *drv =3D AUDIO_DRIVER_GET_CLASS(d)->driver; - - d->dev =3D dev; - d->drv_opaque =3D drv->init(d->dev, errp); - if (!d->drv_opaque) { - return false; - } - - if (!drv->pcm_ops->get_buffer_in) { - drv->pcm_ops->get_buffer_in =3D audio_generic_get_buffer_in; - drv->pcm_ops->put_buffer_in =3D audio_generic_put_buffer_in; - } - if (!drv->pcm_ops->get_buffer_out) { - drv->pcm_ops->get_buffer_out =3D audio_generic_get_buffer_out; - drv->pcm_ops->put_buffer_out =3D audio_generic_put_buffer_out; - } - - audio_init_nb_voices_out(d, drv, 1); - audio_init_nb_voices_in(d, drv, 0); - d->drv =3D drv; - - if (d->dev->timer_period <=3D 0) { - d->period_ticks =3D 1; - } else { - d->period_ticks =3D d->dev->timer_period * (int64_t)SCALE_US; - } - - return true; -} - -static void audio_vm_change_state_handler (void *opaque, bool running, - RunState state) -{ - AudioDriver *s =3D opaque; - HWVoiceOut *hwo =3D NULL; - HWVoiceIn *hwi =3D NULL; - - s->vm_running =3D running; - while ((hwo =3D audio_pcm_hw_find_any_enabled_out(s, hwo))) { - if (hwo->pcm_ops->enable_out) { - hwo->pcm_ops->enable_out(hwo, running); - } - } - - while ((hwi =3D audio_pcm_hw_find_any_enabled_in(s, hwi))) { - if (hwi->pcm_ops->enable_in) { - hwi->pcm_ops->enable_in(hwi, running); - } - } - audio_reset_timer (s); -} - -static const VMStateDescription vmstate_audio; - -static const char *audio_driver_get_id(AudioBackend *be) -{ - return AUDIO_DRIVER(be)->dev->id; -} - -static CaptureVoiceOut *audio_driver_add_capture( - AudioBackend *be, - struct audsettings *as, - struct audio_capture_ops *ops, - void *cb_opaque); - -static void audio_driver_del_capture( - AudioBackend *be, - CaptureVoiceOut *cap, - void *cb_opaque); - -static void audio_driver_set_volume_out(AudioBackend *be, SWVoiceOut *sw, = Volume *vol); -static void audio_driver_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Vo= lume *vol); - -static void audio_driver_class_init(ObjectClass *klass, const void *data) -{ - AudioBackendClass *be =3D AUDIO_BACKEND_CLASS(klass); - - be->realize =3D audio_be_driver_realize; - be->get_id =3D audio_driver_get_id; - be->open_in =3D audio_driver_open_in; - be->open_out =3D audio_driver_open_out; - be->close_in =3D audio_driver_close_in; - be->close_out =3D audio_driver_close_out; - be->is_active_out =3D audio_driver_is_active_out; - be->is_active_in =3D audio_driver_is_active_in; - be->set_active_out =3D audio_driver_set_active_out; - be->set_active_in =3D audio_driver_set_active_in; - be->set_volume_out =3D audio_driver_set_volume_out; - be->set_volume_in =3D audio_driver_set_volume_in; - be->read =3D audio_driver_read; - be->write =3D audio_driver_write; - be->get_buffer_size_out =3D audio_driver_get_buffer_size_out; - be->add_capture =3D audio_driver_add_capture; - be->del_capture =3D audio_driver_del_capture; -} - -static void audio_driver_init(Object *obj) -{ - AudioDriver *s =3D AUDIO_DRIVER(obj); - - QLIST_INIT(&s->hw_head_out); - QLIST_INIT(&s->hw_head_in); - QLIST_INIT(&s->cap_head); - s->ts =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); - - s->vmse =3D qemu_add_vm_change_state_handler(audio_vm_change_state_han= dler, s); - assert(s->vmse !=3D NULL); - - vmstate_register_any(NULL, &vmstate_audio, s); -} +/* SPDX-License-Identifier: MIT */ =20 -static void audio_driver_finalize(Object *obj) -{ - AudioDriver *s =3D AUDIO_DRIVER(obj); - HWVoiceOut *hwo, *hwon; - HWVoiceIn *hwi, *hwin; - - QLIST_FOREACH_SAFE(hwo, &s->hw_head_out, entries, hwon) { - SWVoiceCap *sc; - - if (hwo->enabled && hwo->pcm_ops->enable_out) { - hwo->pcm_ops->enable_out(hwo, false); - } - hwo->pcm_ops->fini_out (hwo); - - for (sc =3D hwo->cap_head.lh_first; sc; sc =3D sc->entries.le_next= ) { - CaptureVoiceOut *cap =3D sc->cap; - struct capture_callback *cb; +#include "qemu/osdep.h" +#include "qemu/audio.h" +#include "qemu/help_option.h" +#include "qapi/clone-visitor.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qapi-visit-audio.h" +#include "qapi/qapi-commands-audio.h" +#include "qobject/qdict.h" +#include "system/system.h" =20 - for (cb =3D cap->cb_head.lh_first; cb; cb =3D cb->entries.le_n= ext) { - cb->ops.destroy (cb->opaque); - } - } - QLIST_REMOVE(hwo, entries); - } +/* Order of CONFIG_AUDIO_DRIVERS is import. + The 1st one is the one used by default, that is the reason + that we generate the list. +*/ +const char *audio_prio_list[] =3D { +#ifdef CONFIG_GIO + "dbus", +#endif + "spice", + CONFIG_AUDIO_DRIVERS + "none", + NULL +}; =20 - QLIST_FOREACH_SAFE(hwi, &s->hw_head_in, entries, hwin) { - if (hwi->enabled && hwi->pcm_ops->enable_in) { - hwi->pcm_ops->enable_in(hwi, false); - } - hwi->pcm_ops->fini_in (hwi); - QLIST_REMOVE(hwi, entries); - } +typedef struct AudiodevListEntry { + Audiodev *dev; + QSIMPLEQ_ENTRY(AudiodevListEntry) next; +} AudiodevListEntry; =20 - if (s->drv) { - s->drv->fini (s->drv_opaque); - s->drv =3D NULL; - } +typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead; =20 - if (s->dev) { - qapi_free_Audiodev(s->dev); - s->dev =3D NULL; - } +static AudiodevListHead audiodevs =3D + QSIMPLEQ_HEAD_INITIALIZER(audiodevs); +static AudiodevListHead default_audiodevs =3D + QSIMPLEQ_HEAD_INITIALIZER(default_audiodevs); =20 - if (s->ts) { - timer_free(s->ts); - s->ts =3D NULL; - } +static AudioBackendClass *audio_be_class_by_name(const char *name) +{ + g_autofree char *tname =3D g_strconcat("audio-", name, NULL); + ObjectClass *oc =3D module_object_class_by_name(tname); =20 - if (s->vmse) { - qemu_del_vm_change_state_handler(s->vmse); - s->vmse =3D NULL; + if (!oc || !object_class_dynamic_cast(oc, TYPE_AUDIO_BACKEND)) { + return NULL; } =20 - vmstate_unregister(NULL, &vmstate_audio, s); + return AUDIO_BACKEND_CLASS(oc); } =20 +static AudioBackend *default_audio_be; + static Object *get_audiodevs_root(void) { return object_get_container("audiodevs"); @@ -1754,25 +62,6 @@ void audio_cleanup(void) object_unparent(get_audiodevs_root()); } =20 -static bool vmstate_audio_needed(void *opaque) -{ - /* - * Never needed, this vmstate only exists in case - * an old qemu sends it to us. - */ - return false; -} - -static const VMStateDescription vmstate_audio =3D { - .name =3D "audio", - .version_id =3D 1, - .minimum_version_id =3D 1, - .needed =3D vmstate_audio_needed, - .fields =3D (const VMStateField[]) { - VMSTATE_END_OF_LIST() - } -}; - void audio_create_default_audiodevs(void) { for (int i =3D 0; audio_prio_list[i]; i++) { @@ -1850,155 +139,35 @@ AudioBackend *audio_get_default_audio_be(Error **er= rp) return default_audio_be; } =20 -static struct audio_pcm_ops capture_pcm_ops; - -static CaptureVoiceOut *audio_driver_add_capture( - AudioBackend *be, - struct audsettings *as, - struct audio_capture_ops *ops, - void *cb_opaque) -{ - AudioDriver *s =3D AUDIO_DRIVER(be); - CaptureVoiceOut *cap; - struct capture_callback *cb; - - if (!s) { - /* TODO: implement an interface instead (or drop capture support) = */ - error_report("Capturing without setting an audiodev driver is not = supported"); - abort(); - } - - if (!audio_get_pdo_out(s->dev)->mixing_engine) { - dolog("Can't capture with mixeng disabled\n"); - return NULL; - } - - if (audio_validate_settings (as)) { - dolog ("Invalid settings were passed when trying to add capture\n"= ); - audio_print_settings (as); - return NULL; - } - - cb =3D g_malloc0(sizeof(*cb)); - cb->ops =3D *ops; - cb->opaque =3D cb_opaque; - - cap =3D audio_pcm_capture_find_specific(s, as); - if (cap) { - QLIST_INSERT_HEAD (&cap->cb_head, cb, entries); - } else { - HWVoiceOut *hw; - - cap =3D g_malloc0(sizeof(*cap)); - - hw =3D &cap->hw; - hw->s =3D s; - hw->pcm_ops =3D &capture_pcm_ops; - QLIST_INIT (&hw->sw_head); - QLIST_INIT (&cap->cb_head); - - /* XXX find a more elegant way */ - hw->samples =3D 4096 * 4; - audio_pcm_hw_alloc_resources_out(hw); - - audio_pcm_init_info (&hw->info, as); - - cap->buf =3D g_malloc0_n(hw->mix_buf.size, hw->info.bytes_per_fram= e); - - if (hw->info.is_float) { - hw->clip =3D mixeng_clip_float[hw->info.nchannels =3D=3D 2] - [hw->info.swap_endianness]; - } else { - hw->clip =3D mixeng_clip - [hw->info.nchannels =3D=3D 2] - [hw->info.is_signed] - [hw->info.swap_endianness] - [audio_bits_to_index(hw->info.bits)]; - } - - QLIST_INSERT_HEAD (&s->cap_head, cap, entries); - QLIST_INSERT_HEAD (&cap->cb_head, cb, entries); - - QLIST_FOREACH(hw, &s->hw_head_out, entries) { - audio_attach_capture (hw); - } - } - - return cap; -} - -static void audio_driver_del_capture( - AudioBackend *be, - CaptureVoiceOut *cap, - void *cb_opaque) +void audio_help(void) { - struct capture_callback *cb; - - for (cb =3D cap->cb_head.lh_first; cb; cb =3D cb->entries.le_next) { - if (cb->opaque =3D=3D cb_opaque) { - cb->ops.destroy (cb_opaque); - QLIST_REMOVE (cb, entries); - g_free (cb); + int i; =20 - if (!cap->cb_head.lh_first) { - SWVoiceOut *sw =3D cap->hw.sw_head.lh_first, *sw1; + printf("Available audio drivers:\n"); =20 - while (sw) { - SWVoiceCap *sc =3D (SWVoiceCap *) sw; -#ifdef DEBUG_CAPTURE - dolog ("freeing %s\n", sw->name); -#endif + for (i =3D 0; i < AUDIODEV_DRIVER__MAX; i++) { + const char *name =3D AudiodevDriver_str(i); + AudioBackendClass *be =3D audio_be_class_by_name(name); =20 - sw1 =3D sw->entries.le_next; - if (sw->rate) { - st_rate_stop (sw->rate); - sw->rate =3D NULL; - } - QLIST_REMOVE (sw, entries); - QLIST_REMOVE (sc, entries); - g_free (sc); - sw =3D sw1; - } - QLIST_REMOVE (cap, entries); - g_free(cap->hw.mix_buf.buffer); - g_free (cap->buf); - g_free (cap); - } - return; + if (be) { + printf("%s\n", name); } } } =20 -static void audio_driver_set_volume_out(AudioBackend *be, SWVoiceOut *sw, = Volume *vol) +void audio_parse_option(const char *opt) { - if (sw) { - HWVoiceOut *hw =3D sw->hw; - - sw->vol.mute =3D vol->mute; - sw->vol.l =3D nominal_volume.l * vol->vol[0] / 255; - sw->vol.r =3D nominal_volume.l * vol->vol[vol->channels > 1 ? 1 : = 0] / - 255; + Audiodev *dev =3D NULL; =20 - if (hw->pcm_ops->volume_out) { - hw->pcm_ops->volume_out(hw, vol); - } + if (is_help_option(opt)) { + audio_help(); + exit(EXIT_SUCCESS); } -} - -static void audio_driver_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Vo= lume *vol) -{ - if (sw) { - HWVoiceIn *hw =3D sw->hw; - - sw->vol.mute =3D vol->mute; - sw->vol.l =3D nominal_volume.l * vol->vol[0] / 255; - sw->vol.r =3D nominal_volume.r * vol->vol[vol->channels > 1 ? 1 : = 0] / - 255; + Visitor *v =3D qobject_input_visitor_new_str(opt, "driver", &error_fat= al); + visit_type_Audiodev(v, NULL, &dev, &error_fatal); + visit_free(v); =20 - if (hw->pcm_ops->volume_in) { - hw->pcm_ops->volume_in(hw, vol); - } - } + audio_add_audiodev(dev); } =20 static void audio_create_pdos(Audiodev *dev) @@ -2097,6 +266,124 @@ static void audio_validate_per_direction_opts( } } =20 +static AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev) +{ + switch (dev->driver) { + case AUDIODEV_DRIVER_NONE: + return dev->u.none.out; +#ifdef CONFIG_AUDIO_ALSA + case AUDIODEV_DRIVER_ALSA: + return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.out); +#endif +#ifdef CONFIG_AUDIO_COREAUDIO + case AUDIODEV_DRIVER_COREAUDIO: + return qapi_AudiodevCoreaudioPerDirectionOptions_base( + dev->u.coreaudio.out); +#endif +#ifdef CONFIG_DBUS_DISPLAY + case AUDIODEV_DRIVER_DBUS: + return dev->u.dbus.out; +#endif +#ifdef CONFIG_AUDIO_DSOUND + case AUDIODEV_DRIVER_DSOUND: + return dev->u.dsound.out; +#endif +#ifdef CONFIG_AUDIO_JACK + case AUDIODEV_DRIVER_JACK: + return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.out); +#endif +#ifdef CONFIG_AUDIO_OSS + case AUDIODEV_DRIVER_OSS: + return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.out); +#endif +#ifdef CONFIG_AUDIO_PA + case AUDIODEV_DRIVER_PA: + return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.out); +#endif +#ifdef CONFIG_AUDIO_PIPEWIRE + case AUDIODEV_DRIVER_PIPEWIRE: + return qapi_AudiodevPipewirePerDirectionOptions_base(dev->u.pipewi= re.out); +#endif +#ifdef CONFIG_AUDIO_SDL + case AUDIODEV_DRIVER_SDL: + return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.out); +#endif +#ifdef CONFIG_AUDIO_SNDIO + case AUDIODEV_DRIVER_SNDIO: + return dev->u.sndio.out; +#endif +#ifdef CONFIG_SPICE + case AUDIODEV_DRIVER_SPICE: + return dev->u.spice.out; +#endif + case AUDIODEV_DRIVER_WAV: + return dev->u.wav.out; + + case AUDIODEV_DRIVER__MAX: + break; + } + abort(); +} + +static AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev) +{ + switch (dev->driver) { + case AUDIODEV_DRIVER_NONE: + return dev->u.none.in; +#ifdef CONFIG_AUDIO_ALSA + case AUDIODEV_DRIVER_ALSA: + return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.in); +#endif +#ifdef CONFIG_AUDIO_COREAUDIO + case AUDIODEV_DRIVER_COREAUDIO: + return qapi_AudiodevCoreaudioPerDirectionOptions_base( + dev->u.coreaudio.in); +#endif +#ifdef CONFIG_DBUS_DISPLAY + case AUDIODEV_DRIVER_DBUS: + return dev->u.dbus.in; +#endif +#ifdef CONFIG_AUDIO_DSOUND + case AUDIODEV_DRIVER_DSOUND: + return dev->u.dsound.in; +#endif +#ifdef CONFIG_AUDIO_JACK + case AUDIODEV_DRIVER_JACK: + return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.in); +#endif +#ifdef CONFIG_AUDIO_OSS + case AUDIODEV_DRIVER_OSS: + return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.in); +#endif +#ifdef CONFIG_AUDIO_PA + case AUDIODEV_DRIVER_PA: + return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.in); +#endif +#ifdef CONFIG_AUDIO_PIPEWIRE + case AUDIODEV_DRIVER_PIPEWIRE: + return qapi_AudiodevPipewirePerDirectionOptions_base(dev->u.pipewi= re.in); +#endif +#ifdef CONFIG_AUDIO_SDL + case AUDIODEV_DRIVER_SDL: + return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.in); +#endif +#ifdef CONFIG_AUDIO_SNDIO + case AUDIODEV_DRIVER_SNDIO: + return dev->u.sndio.in; +#endif +#ifdef CONFIG_SPICE + case AUDIODEV_DRIVER_SPICE: + return dev->u.spice.in; +#endif + case AUDIODEV_DRIVER_WAV: + return dev->u.wav.in; + + case AUDIODEV_DRIVER__MAX: + break; + } + abort(); +} + static void audio_validate_opts(Audiodev *dev, Error **errp) { Error *err =3D NULL; @@ -2121,37 +408,6 @@ static void audio_validate_opts(Audiodev *dev, Error = **errp) } } =20 -void audio_help(void) -{ - int i; - - printf("Available audio drivers:\n"); - - for (i =3D 0; i < AUDIODEV_DRIVER__MAX; i++) { - const char *name =3D AudiodevDriver_str(i); - AudioBackendClass *be =3D audio_be_class_by_name(name); - - if (be) { - printf("%s\n", name); - } - } -} - -void audio_parse_option(const char *opt) -{ - Audiodev *dev =3D NULL; - - if (is_help_option(opt)) { - audio_help(); - exit(EXIT_SUCCESS); - } - Visitor *v =3D qobject_input_visitor_new_str(opt, "driver", &error_fat= al); - visit_type_Audiodev(v, NULL, &dev, &error_fatal); - visit_free(v); - - audio_add_audiodev(dev); -} - void audio_add_audiodev(Audiodev *dev) { AudiodevListEntry *e; @@ -2183,65 +439,6 @@ void audio_init_audiodevs(void) } } =20 -audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo) -{ - return (audsettings) { - .freq =3D pdo->frequency, - .nchannels =3D pdo->channels, - .fmt =3D pdo->format, - .endianness =3D HOST_BIG_ENDIAN, - }; -} - -int audioformat_bytes_per_sample(AudioFormat fmt) -{ - switch (fmt) { - case AUDIO_FORMAT_U8: - case AUDIO_FORMAT_S8: - return 1; - - case AUDIO_FORMAT_U16: - case AUDIO_FORMAT_S16: - return 2; - - case AUDIO_FORMAT_U32: - case AUDIO_FORMAT_S32: - case AUDIO_FORMAT_F32: - return 4; - - case AUDIO_FORMAT__MAX: - ; - } - abort(); -} - - -/* frames =3D freq * usec / 1e6 */ -int audio_buffer_frames(AudiodevPerDirectionOptions *pdo, - audsettings *as, int def_usecs) -{ - uint64_t usecs =3D pdo->has_buffer_length ? pdo->buffer_length : def_u= secs; - return (as->freq * usecs + 500000) / 1000000; -} - -/* samples =3D channels * frames =3D channels * freq * usec / 1e6 */ -int audio_buffer_samples(AudiodevPerDirectionOptions *pdo, - audsettings *as, int def_usecs) -{ - return as->nchannels * audio_buffer_frames(pdo, as, def_usecs); -} - -/* - * bytes =3D bytes_per_sample * samples =3D - * bytes_per_sample * channels * freq * usec / 1e6 - */ -int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo, - audsettings *as, int def_usecs) -{ - return audio_buffer_samples(pdo, as, def_usecs) * - audioformat_bytes_per_sample(as->fmt); -} - AudioBackend *audio_be_by_name(const char *name, Error **errp) { Object *obj =3D object_resolve_path_component(get_audiodevs_root(), na= me); @@ -2262,51 +459,6 @@ const char *audio_application_name(void) return vm_name ? vm_name : "qemu"; } =20 -void audio_rate_start(RateCtl *rate) -{ - memset(rate, 0, sizeof(RateCtl)); - rate->start_ticks =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -} - -size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info) -{ - int64_t now; - int64_t ticks; - int64_t bytes; - int64_t frames; - - now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - ticks =3D now - rate->start_ticks; - bytes =3D muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECO= ND); - frames =3D (bytes - rate->bytes_sent) / info->bytes_per_frame; - rate->peeked_frames =3D frames; - - return frames < 0 ? 0 : frames * info->bytes_per_frame; -} - -void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used) -{ - if (rate->peeked_frames < 0 || rate->peeked_frames > 65536) { - AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n", - rate->peeked_frames); - audio_rate_start(rate); - } - - rate->bytes_sent +=3D bytes_used; -} - -size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info, - size_t bytes_avail) -{ - size_t bytes; - - bytes =3D audio_rate_peek_bytes(rate, info); - bytes =3D MIN(bytes, bytes_avail); - audio_rate_add_bytes(rate, bytes); - - return bytes; -} - AudiodevList *qmp_query_audiodevs(Error **errp) { AudiodevList *ret =3D NULL; @@ -2316,21 +468,3 @@ AudiodevList *qmp_query_audiodevs(Error **errp) } return ret; } - -static const TypeInfo audio_driver_info =3D { - .name =3D TYPE_AUDIO_DRIVER, - .parent =3D TYPE_AUDIO_BACKEND, - .instance_size =3D sizeof(AudioDriver), - .instance_init =3D audio_driver_init, - .instance_finalize =3D audio_driver_finalize, - .abstract =3D false, - .class_size =3D sizeof(AudioDriverClass), - .class_init =3D audio_driver_class_init, -}; - -static void register_types(void) -{ - type_register_static(&audio_driver_info); -} - -type_init(register_types); diff --git a/audio/meson.build b/audio/meson.build index 2450098eb8..5586641d82 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -1,6 +1,7 @@ system_ss.add(files( 'audio.c', 'audio-be.c', + 'audio-driver.c', 'mixeng.c', 'noaudio.c', 'wavaudio.c', --=20 2.51.1 From nobody Mon Feb 9 17:12:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1764588376; cv=none; d=zohomail.com; s=zohoarc; b=eeIyL4o//OOxnbv4qeXhRBpiVfdVzwrPtuqBg7srl7gvXl6XDbrPZQrx4iJKeLjAeP5+KEc7rvPeBYtThVYqeOFuhMVqVUBmDRLgPUBUpgjbMdALfjJikcj/4JFxhzu/x8X2Oocey4SKkuVAxcHrhEsBefNeKvjV1cUgnD3QA4E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1764588376; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/t94+ihrSNyoZccvd70585Z+HE8PEbdes0oy6oQQBlQ=; b=LPHAO1doZ3O3iim6MBrsFHNayQ+/6Z7DO2s2gWfKz8zYoyoCKM0ZsHV1ajMRNPGdY9Ld09vzJMFolHK8GVUMz/OHyo9BcsiUh/gASDNk23WVL0EuTPl3GuJDK5P60Tc3BMHawSvm+2ubW+L5/c3P3qB1UlF/A24GUiYwa8FjqyE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1764588376881267.84108389569997; Mon, 1 Dec 2025 03:26:16 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vQ22m-0007ON-QY; Mon, 01 Dec 2025 06:26:14 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22h-00072P-3c for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:26:07 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vQ22c-00076g-0L for qemu-devel@nongnu.org; Mon, 01 Dec 2025 06:26:06 -0500 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-611-xLao2i6sOkq6G3hS9rF4xw-1; Mon, 01 Dec 2025 06:25:59 -0500 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CF2B718002CD; Mon, 1 Dec 2025 11:25:57 +0000 (UTC) Received: from localhost (unknown [10.45.242.40]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 00409195608E; Mon, 1 Dec 2025 11:25:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764588361; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/t94+ihrSNyoZccvd70585Z+HE8PEbdes0oy6oQQBlQ=; b=WGNoLikT0QPSZE1GoJnkJmUGfAsidqGTTlrlOCUeuvqTj24dLkP+DcfxjMNAzgmmlnXkkm JGec4PWP1kMqub2n5oCDglwGlH9d2d7rUVRxev+JCypFLCL7w1AGONk/3ThOV1tKNGF72X hm8yfj/mDIbOm0w2kRTS2/Wnkk7mYfM= X-MC-Unique: xLao2i6sOkq6G3hS9rF4xw-1 X-Mimecast-MFC-AGG-ID: xLao2i6sOkq6G3hS9rF4xw_1764588357 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , Thomas Huth , Akihiko Odaki , Alexandre Ratchov , dirty.ice.hu@gmail.com, Christian Schoenebeck , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Volker=20R=C3=BCmelin?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Eric Blake , Markus Armbruster , Manos Pitsidianakis , qemu-rust@nongnu.org (open list:Rust-related patc...) Subject: [RFC 24/24] WIP: rust/audio: add GStreamer backend Date: Mon, 1 Dec 2025 15:23:05 +0400 Message-ID: <20251201112309.4163921-25-marcandre.lureau@redhat.com> In-Reply-To: <20251201112309.4163921-1-marcandre.lureau@redhat.com> References: <20251201112309.4163921-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1764588379881019200 From: Marc-Andr=C3=A9 Lureau This patch introduce a rust/audio crate that replaces QEMU audio/ mixing/resampling code with GStreamer and Rust. It could potentially remove the need for all the system-specific audio API implementation, since GStreamer has audio elements for ALSA/Pipewire/PulseAudio/jack/OSX/WASAPI etc (removing ~10k loc). TODO: - test on various system, with various configuration to see if this backend can replace the other QEMU audio backends - add a spicesink/spicesrc to handle spice, or rewrite spice to use the capture approach used by VNC code. Or drop capture support, and use custom qemusrc/qemusink for both Spice and VNC, lowering the feature and behaviour disparity. - build-sys: make gstreamer optional - build-sys: loadable module support - investigate dropping get_buffer_size_out() - investigate improving emulated devices to not require regular timers (appsrc need-data is called once) - add generic audio backend tests - more tests for the mixing/liveadder behaviour (synchronization) - other: replace audio/dbus with a rust implementation (not using gstreamer) Signed-off-by: Marc-Andr=C3=A9 Lureau --- qapi/audio.json | 29 + audio/audio-driver_template.h | 2 + rust/audio/wrapper.h | 27 + audio/audio.c | 5 + Cargo.lock | 572 ++++++++++++++++-- Cargo.toml | 6 + audio/trace-events | 5 + rust/audio/Cargo.toml | 29 + rust/audio/build.rs | 49 ++ rust/audio/meson.build | 75 +++ rust/audio/src/audio.rs | 516 ++++++++++++++++ rust/audio/src/bindings.rs | 32 + rust/audio/src/gstreamer.rs | 1070 +++++++++++++++++++++++++++++++++ rust/audio/src/lib.rs | 99 +++ rust/meson.build | 6 + 15 files changed, 2467 insertions(+), 55 deletions(-) create mode 100644 rust/audio/wrapper.h create mode 100644 rust/audio/Cargo.toml create mode 100644 rust/audio/build.rs create mode 100644 rust/audio/meson.build create mode 100644 rust/audio/src/audio.rs create mode 100644 rust/audio/src/bindings.rs create mode 100644 rust/audio/src/gstreamer.rs create mode 100644 rust/audio/src/lib.rs diff --git a/qapi/audio.json b/qapi/audio.json index 2df87b9710..76dc7cbfa6 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -128,6 +128,33 @@ '*out': 'AudiodevAlsaPerDirectionOptions', '*threshold': 'uint32' } } =20 + ## + # @AudiodevGStreamerOptions: + # + # Options of the GStreamer audio backend. + # + # @in: options of the capture stream + # + # @out: options of the playback stream + # + # @sink: the name of the GStreamer sink element to use + # (default 'autoaudiosink') + # + # @source: the name of the GStreamer source element to use + # (default 'autoaudiosrc') + # + # Since: 11.0 + ## + { 'struct': 'AudiodevGStreamerOptions', + 'data': { + '*in': 'AudiodevPerDirectionOptions', + '*out': 'AudiodevPerDirectionOptions', + '*sink': 'str', + '*source': 'str' + } + } + + ## # @AudiodevSndioOptions: # @@ -484,6 +511,7 @@ { 'name': 'sdl', 'if': 'CONFIG_AUDIO_SDL' }, { 'name': 'sndio', 'if': 'CONFIG_AUDIO_SNDIO' }, { 'name': 'spice', 'if': 'CONFIG_SPICE' }, + { 'name': 'gstreamer' }, 'wav' ] } =20 ## @@ -530,6 +558,7 @@ 'if': 'CONFIG_AUDIO_SNDIO' }, 'spice': { 'type': 'AudiodevGenericOptions', 'if': 'CONFIG_SPICE' }, + 'gstreamer': { 'type': 'AudiodevGStreamerOptions' }, 'wav': 'AudiodevWavOptions' } } =20 ## diff --git a/audio/audio-driver_template.h b/audio/audio-driver_template.h index 40d1ad9dea..aa2451ac7f 100644 --- a/audio/audio-driver_template.h +++ b/audio/audio-driver_template.h @@ -391,6 +391,8 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)= (Audiodev *dev) case AUDIODEV_DRIVER_SPICE: return dev->u.spice.TYPE; #endif + case AUDIODEV_DRIVER_GSTREAMER: + abort(); case AUDIODEV_DRIVER_WAV: return dev->u.wav.TYPE; =20 diff --git a/rust/audio/wrapper.h b/rust/audio/wrapper.h new file mode 100644 index 0000000000..a7960d0acc --- /dev/null +++ b/rust/audio/wrapper.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This header file is meant to be used as input to the `bindgen` applicat= ion + * in order to generate C FFI compatible Rust bindings. + */ + +#ifndef __CLANG_STDATOMIC_H +#define __CLANG_STDATOMIC_H +/* + * Fix potential missing stdatomic.h error in case bindgen does not insert= the + * correct libclang header paths on its own. We do not use stdatomic.h sym= bols + * in QEMU code, so it's fine to declare dummy types instead. + */ +typedef enum memory_order { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst, +} memory_order; +#endif /* __CLANG_STDATOMIC_H */ + +#include "qemu/osdep.h" + +#include "qemu/audio.h" diff --git a/audio/audio.c b/audio/audio.c index ccb16ae3b2..5a11fe60db 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -219,6 +219,7 @@ static void audio_create_pdos(Audiodev *dev) #ifdef CONFIG_SPICE CASE(SPICE, spice, ); #endif + CASE(GSTREAMER, gstreamer, ); CASE(WAV, wav, ); =20 case AUDIODEV_DRIVER__MAX: @@ -316,6 +317,8 @@ static AudiodevPerDirectionOptions *audio_get_pdo_out(A= udiodev *dev) case AUDIODEV_DRIVER_SPICE: return dev->u.spice.out; #endif + case AUDIODEV_DRIVER_GSTREAMER: + return dev->u.gstreamer.out; case AUDIODEV_DRIVER_WAV: return dev->u.wav.out; =20 @@ -375,6 +378,8 @@ static AudiodevPerDirectionOptions *audio_get_pdo_in(Au= diodev *dev) case AUDIODEV_DRIVER_SPICE: return dev->u.spice.in; #endif + case AUDIODEV_DRIVER_GSTREAMER: + return dev->u.gstreamer.in; case AUDIODEV_DRIVER_WAV: return dev->u.wav.in; =20 diff --git a/Cargo.lock b/Cargo.lock index e6102b258b..274dd1be4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,15 +4,21 @@ version =3D 4 =20 [[package]] name =3D "anyhow" -version =3D "1.0.98" +version =3D "1.0.100" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdc= d487" +checksum =3D "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af= 6e61" =20 [[package]] name =3D "arbitrary-int" -version =3D "1.2.7" +version =3D "1.3.0" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "c84fc003e338a6f69fbd4f7fe9f92b535ff13e9af8997f3b14b6ddff8b1d= f46d" +checksum =3D "825297538d77367557b912770ca3083f778a196054b3ee63b22673c4a3ca= e0a5" + +[[package]] +name =3D "atomic_refcell" +version =3D "0.1.13" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3= 047c" =20 [[package]] name =3D "attrs" @@ -24,6 +30,29 @@ dependencies =3D [ "syn", ] =20 +[[package]] +name =3D "audio" +version =3D "0.1.0" +dependencies =3D [ + "bql", + "common", + "futures", + "gio-sys", + "glib-sys", + "gstreamer-app", + "gstreamer-audio", + "qom", + "system", + "trace", + "util", +] + +[[package]] +name =3D "autocfg" +version =3D "1.5.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172= e7e8" + [[package]] name =3D "bilge" version =3D "0.2.0" @@ -40,13 +69,19 @@ version =3D "0.2.0" source =3D "registry+https://github.com/rust-lang/crates.io-index" checksum =3D "feb11e002038ad243af39c2068c8a72bcf147acf05025dcdb916fcc000ad= b2d8" dependencies =3D [ - "itertools", + "itertools 0.11.0", "proc-macro-error", "proc-macro2", "quote", "syn", ] =20 +[[package]] +name =3D "bitflags" +version =3D "2.10.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e3= 1dd3" + [[package]] name =3D "bits" version =3D "0.1.0" @@ -63,14 +98,20 @@ dependencies =3D [ =20 [[package]] name =3D "cfg-expr" -version =3D "0.20.3" +version =3D "0.20.4" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "1a2c5f3bf25ec225351aa1c8e230d04d880d3bd89dea133537dafad4ae29= 1e5c" +checksum =3D "9acd0bdbbf4b2612d09f52ba61da432140cb10930354079d0d53fafc1296= 8726" dependencies =3D [ "smallvec", "target-lexicon", ] =20 +[[package]] +name =3D "cfg-if" +version =3D "1.0.4" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef98614261512= 1801" + [[package]] name =3D "chardev" version =3D "0.1.0" @@ -93,9 +134,9 @@ dependencies =3D [ =20 [[package]] name =3D "either" -version =3D "1.12.0" +version =3D "1.15.0" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385= b58b" +checksum =3D "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b= 3719" =20 [[package]] name =3D "equivalent" @@ -105,13 +146,149 @@ checksum =3D "877a4ace8713b0bcf2a4e7eec82529c029f1d0= 619886d18145fea96c3ffe5c0f" =20 [[package]] name =3D "foreign" -version =3D "0.3.1" +version =3D "0.3.2" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "17ca1b5be8c9d320daf386f1809c7acc0cb09accbae795c2001953fa5058= 5846" +checksum =3D "bec05eb9c07a3f66653535e5e50eb5eb935eb00d3bb7e06ea26a9d3a1d01= 6182" dependencies =3D [ "libc", ] =20 +[[package]] +name =3D "futures" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b= 0876" +dependencies =3D [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name =3D "futures-channel" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe= 1b10" +dependencies =3D [ + "futures-core", + "futures-sink", +] + +[[package]] +name =3D "futures-core" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6= 663e" + +[[package]] +name =3D "futures-executor" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d64= 6c9f" +dependencies =3D [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name =3D "futures-io" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce0= 75c6" + +[[package]] +name =3D "futures-macro" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c= 3650" +dependencies =3D [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name =3D "futures-sink" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1= d4f7" + +[[package]] +name =3D "futures-task" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd9= 9988" + +[[package]] +name =3D "futures-util" +version =3D "0.3.31" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a= 4a81" +dependencies =3D [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name =3D "gio-sys" +version =3D "0.21.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "171ed2f6dd927abbe108cfd9eebff2052c335013f5879d55bab0dc1dee19= b706" +dependencies =3D [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "windows-sys", +] + +[[package]] +name =3D "glib" +version =3D "0.21.4" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "5b9dbecb1c33e483a98be4acfea2ab369e1c28f517c6eadb674537409c25= c4b2" +dependencies =3D [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "smallvec", +] + +[[package]] +name =3D "glib-macros" +version =3D "0.21.4" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "880e524e0085f3546cfb38532b2c202c0d64741d9977a6e4aa24704bfc9f= 19fb" +dependencies =3D [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name =3D "glib-sys" version =3D "0.21.2" @@ -122,11 +299,144 @@ dependencies =3D [ "system-deps", ] =20 +[[package]] +name =3D "gobject-sys" +version =3D "0.21.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "538e41d8776173ec107e7b0f2aceced60abc368d7e1d81c1f0e2ecd35f59= 080d" +dependencies =3D [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name =3D "gstreamer" +version =3D "0.24.3" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "69ac2f12970a2f85a681d2ceaa40c32fe86cc202ead315e0dfa2223a1217= cd24" +dependencies =3D [ + "cfg-if", + "futures-channel", + "futures-core", + "futures-util", + "glib", + "gstreamer-sys", + "itertools 0.14.0", + "kstring", + "libc", + "muldiv", + "num-integer", + "num-rational", + "option-operations", + "pastey", + "pin-project-lite", + "smallvec", + "thiserror", +] + +[[package]] +name =3D "gstreamer-app" +version =3D "0.24.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "0af5d403738faf03494dfd502d223444b4b44feb997ba28ab3f118ee6d40= a0b2" +dependencies =3D [ + "futures-core", + "futures-sink", + "glib", + "gstreamer", + "gstreamer-app-sys", + "gstreamer-base", + "libc", +] + +[[package]] +name =3D "gstreamer-app-sys" +version =3D "0.24.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "aaf1a3af017f9493c34ccc8439cbce5c48f6ddff6ec0514c23996b374ff2= 5f9a" +dependencies =3D [ + "glib-sys", + "gstreamer-base-sys", + "gstreamer-sys", + "libc", + "system-deps", +] + +[[package]] +name =3D "gstreamer-audio" +version =3D "0.24.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "68e540174d060cd0d7ee2c2356f152f05d8262bf102b40a5869ff7993772= 69d8" +dependencies =3D [ + "cfg-if", + "glib", + "gstreamer", + "gstreamer-audio-sys", + "gstreamer-base", + "libc", + "smallvec", +] + +[[package]] +name =3D "gstreamer-audio-sys" +version =3D "0.24.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "626cd3130bc155a8b6d4ac48cfddc15774b5a6cc76fcb191aab09a2655ba= d8f5" +dependencies =3D [ + "glib-sys", + "gobject-sys", + "gstreamer-base-sys", + "gstreamer-sys", + "libc", + "system-deps", +] + +[[package]] +name =3D "gstreamer-base" +version =3D "0.24.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "71ff9b0bbc8041f0c6c8a53b206a6542f86c7d9fa8a7dff3f27d9c374d9f= 39b4" +dependencies =3D [ + "atomic_refcell", + "cfg-if", + "glib", + "gstreamer", + "gstreamer-base-sys", + "libc", +] + +[[package]] +name =3D "gstreamer-base-sys" +version =3D "0.24.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "fed78852b92db1459b8f4288f86e6530274073c20be2f94ba642cddaca08= b00e" +dependencies =3D [ + "glib-sys", + "gobject-sys", + "gstreamer-sys", + "libc", + "system-deps", +] + +[[package]] +name =3D "gstreamer-sys" +version =3D "0.24.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "a24ae2930e683665832a19ef02466094b09d1f2da5673f001515ed5486aa= 9377" +dependencies =3D [ + "cfg-if", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name =3D "hashbrown" -version =3D "0.16.0" +version =3D "0.16.1" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482= 748d" +checksum =3D "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d= 9100" =20 [[package]] name =3D "heck" @@ -165,9 +475,9 @@ dependencies =3D [ =20 [[package]] name =3D "indexmap" -version =3D "2.11.4" +version =3D "2.12.1" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b= 88e5" +checksum =3D "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74= acf2" dependencies =3D [ "equivalent", "hashbrown", @@ -182,11 +492,29 @@ dependencies =3D [ "either", ] =20 +[[package]] +name =3D "itertools" +version =3D "0.14.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd0335= 1285" +dependencies =3D [ + "either", +] + +[[package]] +name =3D "kstring" +version =3D "2.0.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5= dbd1" +dependencies =3D [ + "static_assertions", +] + [[package]] name =3D "libc" -version =3D "0.2.162" +version =3D "0.2.177" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef0150= 6398" +checksum =3D "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b1= 5976" =20 [[package]] name =3D "memchr" @@ -205,6 +533,67 @@ dependencies =3D [ "util", ] =20 +[[package]] +name =3D "muldiv" +version =3D "1.0.1" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96= d4b0" + +[[package]] +name =3D "num-integer" +version =3D "0.1.46" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879= 858f" +dependencies =3D [ + "num-traits", +] + +[[package]] +name =3D "num-rational" +version =3D "0.4.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb3= 7824" +dependencies =3D [ + "num-integer", + "num-traits", +] + +[[package]] +name =3D "num-traits" +version =3D "0.2.19" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd96026= 2841" +dependencies =3D [ + "autocfg", +] + +[[package]] +name =3D "option-operations" +version =3D "0.6.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "b31ce827892359f23d3cd1cc4c75a6c241772bbd2db17a92dcf27cbefdf5= 2689" +dependencies =3D [ + "pastey", +] + +[[package]] +name =3D "pastey" +version =3D "0.1.1" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c= 68ec" + +[[package]] +name =3D "pin-project-lite" +version =3D "0.2.16" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe61= 9f9b" + +[[package]] +name =3D "pin-utils" +version =3D "0.1.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9= f184" + [[package]] name =3D "pkg-config" version =3D "0.3.32" @@ -236,6 +625,15 @@ version =3D "0.5.2" source =3D "registry+https://github.com/rust-lang/crates.io-index" checksum =3D "136558b6e1ebaecc92755d0ffaf9421f519531bed30cc2ad23b22cb00965= cc5e" =20 +[[package]] +name =3D "proc-macro-crate" +version =3D "3.4.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac4= 6983" +dependencies =3D [ + "toml_edit", +] + [[package]] name =3D "proc-macro-error" version =3D "1.0.4" @@ -261,9 +659,9 @@ dependencies =3D [ =20 [[package]] name =3D "proc-macro2" -version =3D "1.0.95" +version =3D "1.0.103" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7= f778" +checksum =3D "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f= 49e8" dependencies =3D [ "unicode-ident", ] @@ -292,18 +690,18 @@ dependencies =3D [ =20 [[package]] name =3D "quote" -version =3D "1.0.36" +version =3D "1.0.42" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208ac= aca7" +checksum =3D "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3= 067f" dependencies =3D [ "proc-macro2", ] =20 [[package]] name =3D "serde" -version =3D "1.0.226" +version =3D "1.0.228" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b512= 95fd" +checksum =3D "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124= ae9e" dependencies =3D [ "serde_core", "serde_derive", @@ -311,18 +709,18 @@ dependencies =3D [ =20 [[package]] name =3D "serde_core" -version =3D "1.0.226" +version =3D "1.0.228" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e9= 66a4" +checksum =3D "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b= 67ad" dependencies =3D [ "serde_derive", ] =20 [[package]] name =3D "serde_derive" -version =3D "1.0.226" +version =3D "1.0.228" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699c= db33" +checksum =3D "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda9= 1d79" dependencies =3D [ "proc-macro2", "quote", @@ -331,24 +729,36 @@ dependencies =3D [ =20 [[package]] name =3D "serde_spanned" -version =3D "0.6.9" +version =3D "1.0.3" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee= 75a3" +checksum =3D "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd3013= 4392" dependencies =3D [ - "serde", + "serde_core", ] =20 +[[package]] +name =3D "slab" +version =3D "0.4.11" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c9026= 7589" + [[package]] name =3D "smallvec" version =3D "1.15.1" source =3D "registry+https://github.com/rust-lang/crates.io-index" checksum =3D "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6f= bd03" =20 +[[package]] +name =3D "static_assertions" +version =3D "1.1.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37= 543f" + [[package]] name =3D "syn" -version =3D "2.0.104" +version =3D "2.0.111" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b43= 5a40" +checksum =3D "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d= 2e87" dependencies =3D [ "proc-macro2", "quote", @@ -367,9 +777,9 @@ dependencies =3D [ =20 [[package]] name =3D "system-deps" -version =3D "7.0.5" +version =3D "7.0.7" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "e4be53aa0cba896d2dc615bd42bbc130acdcffa239e0a2d965ea5b3b2a86= ffdb" +checksum =3D "48c8f33736f986f16d69b6cb8b03f55ddcad5c41acc4ccc39dd88e84aa80= 5e7f" dependencies =3D [ "cfg-expr", "heck", @@ -380,9 +790,9 @@ dependencies =3D [ =20 [[package]] name =3D "target-lexicon" -version =3D "0.13.2" +version =3D "0.13.3" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5= a69a" +checksum =3D "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcba= a50c" =20 [[package]] name =3D "tests" @@ -398,40 +808,77 @@ dependencies =3D [ "util", ] =20 +[[package]] +name =3D "thiserror" +version =3D "2.0.17" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f= 4fc8" +dependencies =3D [ + "thiserror-impl", +] + +[[package]] +name =3D "thiserror-impl" +version =3D "2.0.17" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517= c913" +dependencies =3D [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name =3D "toml" -version =3D "0.8.23" +version =3D "0.9.8" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ce= d362" +checksum =3D "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804e= a6d8" dependencies =3D [ - "serde", + "indexmap", + "serde_core", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_parser", + "toml_writer", + "winnow", ] =20 [[package]] name =3D "toml_datetime" -version =3D "0.6.11" +version =3D "0.7.3" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8= f11c" +checksum =3D "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c72= 4533" dependencies =3D [ - "serde", + "serde_core", ] =20 [[package]] name =3D "toml_edit" -version =3D "0.22.27" +version =3D "0.23.7" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f= 819a" +checksum =3D "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb9= 8f8d" dependencies =3D [ "indexmap", - "serde", - "serde_spanned", "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name =3D "toml_parser" +version =3D "1.0.4" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039= 800e" +dependencies =3D [ "winnow", ] =20 +[[package]] +name =3D "toml_writer" +version =3D "1.0.4" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c63= 7bf2" + [[package]] name =3D "trace" version =3D "0.1.0" @@ -442,9 +889,9 @@ dependencies =3D [ =20 [[package]] name =3D "unicode-ident" -version =3D "1.0.12" +version =3D "1.0.22" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0f= ee4b" +checksum =3D "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf= 1df5" =20 [[package]] name =3D "util" @@ -461,21 +908,36 @@ dependencies =3D [ =20 [[package]] name =3D "version-compare" -version =3D "0.2.0" +version =3D "0.2.1" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411= c98b" +checksum =3D "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8e= df0e" =20 [[package]] name =3D "version_check" -version =3D "0.9.4" +version =3D "0.9.5" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e= 483f" +checksum =3D "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289= 105a" + +[[package]] +name =3D "windows-link" +version =3D "0.2.1" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a= 4fe5" + +[[package]] +name =3D "windows-sys" +version =3D "0.61.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921f= f3fc" +dependencies =3D [ + "windows-link", +] =20 [[package]] name =3D "winnow" -version =3D "0.7.13" +version =3D "0.7.14" source =3D "registry+https://github.com/rust-lang/crates.io-index" -checksum =3D "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc90393= 39cf" +checksum =3D "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a882554= 0829" dependencies =3D [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 8e0fbab290..0ced3297e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] resolver =3D "2" members =3D [ + "rust/audio", "rust/hw/char/pl011", "rust/hw/timer/hpet", "rust/tests", @@ -18,8 +19,13 @@ authors =3D ["The QEMU Project Developers "] [workspace.dependencies] anyhow =3D "~1.0" foreign =3D "~0.3.1" +futures =3D "0.3" libc =3D "0.2.162" glib-sys =3D { version =3D "0.21.2", features =3D ["v2_66"] } +gio-sys =3D { version =3D "0.21.2", features =3D ["v2_66"] } +gobect-sys =3D { version =3D "0.21.2", features =3D ["v2_66"] } +gst_app =3D { package =3D "gstreamer-app", version =3D "0.24.2", features = =3D ["v1_24"] } +gst_audio =3D { package =3D "gstreamer-audio", version =3D "0.24.2" } serde =3D { version =3D "1.0.226", features =3D ["derive"] } serde_derive =3D "1.0.226" =20 diff --git a/audio/trace-events b/audio/trace-events index f7f639d960..d71d85fe01 100644 --- a/audio/trace-events +++ b/audio/trace-events @@ -34,3 +34,8 @@ audio_be_set_active_out(void *sw, bool on) "sw=3D%p, on= =3D%d" audio_timer_start(int interval) "interval %d ms" audio_timer_stop(void) "" audio_timer_delayed(int interval) "interval %d ms" + +# gstreamer.rs +gst_write(size_t bytes_written, uint64_t elapsed_ms, size_t bytes_per_seco= nd) "bytes_written=3D%zu, elapsed_ms=3D%" PRIu64 ", bytes_per_second=3D%zu" +gst_need_data(const char *name, size_t len) "name=3D%s, len=3D%zu" +gst_new_sample(const char *name, size_t len) "name=3D%s, len=3D%zu" diff --git a/rust/audio/Cargo.toml b/rust/audio/Cargo.toml new file mode 100644 index 0000000000..ceeb1a5b14 --- /dev/null +++ b/rust/audio/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name =3D "audio" +version =3D "0.1.0" +description =3D "Rust bindings for QEMU/audio" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[dependencies] +bql =3D { path =3D "../bql" } +futures =3D { workspace =3D true } +glib-sys =3D { workspace =3D true } +gio-sys =3D { workspace =3D true } +gst_app =3D { workspace =3D true } +gst_audio =3D { workspace =3D true } +common =3D { path =3D "../common" } +qom =3D { path =3D "../qom" } +util =3D { path =3D "../util" } +system =3D { path =3D "../system" } +trace =3D { path =3D "../trace" } + +[lints] +workspace =3D true diff --git a/rust/audio/build.rs b/rust/audio/build.rs new file mode 100644 index 0000000000..5654d1d562 --- /dev/null +++ b/rust/audio/build.rs @@ -0,0 +1,49 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let manifest_dir =3D env!("CARGO_MANIFEST_DIR"); + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + let sub =3D get_rust_subdir(manifest_dir).unwrap(); + format!("{root}/{sub}/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{manifest_dir}/src/bindings.inc.rs") + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} + +fn get_rust_subdir(path: &str) -> Option<&str> { + path.find("/rust").map(|index| &path[index + 1..]) +} diff --git a/rust/audio/meson.build b/rust/audio/meson.build new file mode 100644 index 0000000000..27519a3e3f --- /dev/null +++ b/rust/audio/meson.build @@ -0,0 +1,75 @@ +c_enums =3D [ + 'audcnotification_e', + 'AudioFormat', +] +_audio_bindgen_args =3D [] +foreach enum : c_enums + _audio_bindgen_args +=3D ['--rustified-enum', enum] +endforeach + +blocked_type =3D [ + 'Error', + 'ObjectClass', +] +foreach type: blocked_type + _audio_bindgen_args +=3D ['--blocklist-type', type] +endforeach + + +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# detected `libclang` does not match the expected `clang` version/target. = In +# this case you must pass the path to `clang` and `libclang` to your build +# command invocation using the environment variables CLANG_PATH and +# LIBCLANG_PATH +_audio_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common + _audio_bindgen_args, + c_args: bindgen_c_args, +) + +_audio_rs =3D static_library( + 'audio', + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/audio.rs', + 'src/gstreamer.rs', + ], + {'.': _audio_bindings_inc_rs} + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + link_with: [ + _util_rs, + _bql_rs, + _qom_rs, + _trace_rs, + _system_rs, + ], + dependencies: [ + gio_sys_rs, + glib_sys_rs, + gst_app_rs, + gst_audio_rs, + common_rs, + futures_rs, + ], + rust_dependency_map: { + 'gstreamer_app': 'gst_app', + 'gstreamer_audio': 'gst_audio', + } +) + +audio_rs =3D declare_dependency(link_with: [_audio_rs]) + +rust_devices_ss.add(declare_dependency( + link_whole: [_audio_rs], + variables: {'crate': 'audio'}, +)) diff --git a/rust/audio/src/audio.rs b/rust/audio/src/audio.rs new file mode 100644 index 0000000000..436298ea17 --- /dev/null +++ b/rust/audio/src/audio.rs @@ -0,0 +1,516 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +use std::{ + ffi::{CStr, CString}, + ptr::NonNull, +}; + +use common::Opaque; +use qom::{prelude::*, ObjectImpl}; +use util::{Error, Result}; + +use crate::bindings; + +/// Called when audio data needs to be processed. The callback receives: +/// - `available`: Number of bytes/frames available for processing +pub type AudioCallback =3D Box; + +pub type CaptureNotification =3D bindings::audcnotification_e; + +pub trait AudioCaptureOps { + fn notify(&mut self, cmd: CaptureNotification); + + fn capture(&mut self, buf: &[u8]); + + fn destroy(&mut self); +} + +/// A safe wrapper around [`bindings::AudioBackend`]. +#[repr(transparent)] +#[derive(common::Wrapper)] +pub struct AudioBackend(Opaque); + +pub type AudioBackendClass =3D bindings::AudioBackendClass; + +pub trait AudioBackendImpl: ObjectImpl { + type VoiceOut; + type VoiceIn; + type Capture; + + fn realize(&self, dev: &bindings::Audiodev) -> Result<()>; + + fn id(&self) -> &CString; + + fn open_out( + &self, + sw: Option, + name: &CStr, + callback_fn: AudioCallback, + settings: &bindings::audsettings, + ) -> Option; + + fn open_in( + &self, + sw: Option, + name: &CStr, + callback_fn: AudioCallback, + settings: &bindings::audsettings, + ) -> Option; + + fn close_out(&self, sw: Self::VoiceOut); + + fn close_in(&self, sw: Self::VoiceIn); + + fn is_active_out(&self, sw: &Self::VoiceOut) -> bool; + + fn is_active_in(&self, sw: &Self::VoiceIn) -> bool; + + fn set_active_out(&self, sw: &mut Self::VoiceOut, on: bool); + + fn set_active_in(&self, sw: &mut Self::VoiceIn, on: bool); + + fn set_volume_out(&self, sw: &mut Self::VoiceOut, vol: &bindings::Volu= me); + + fn set_volume_in(&self, sw: &mut Self::VoiceIn, vol: &bindings::Volume= ); + + fn write(&self, sw: &mut Self::VoiceOut, buf: &[u8]) -> usize; + + fn read(&self, sw: &mut Self::VoiceIn, buf: &mut [u8]) -> usize; + + fn get_buffer_size_out(&self, sw: &mut Self::VoiceOut) -> i32; + + fn add_capture( + &self, + settings: &bindings::audsettings, + ops: Box, + ) -> Option; + + fn del_capture(&self, cap: Self::Capture); + + fn set_dbus_server( + &self, + manager: *mut gio_sys::GDBusObjectManagerServer, + p2p: bool, + ) -> Result<()>; + + /// Convert from opaque `SWVoiceOut` pointer to `VoiceOut` using Box + /// + /// # Safety + /// The pointer must be a valid pointer that was previously created by + /// `voice_out_to_ptr` + unsafe fn ptr_to_voice_out(&self, ptr: NonNull) = -> Box { + unsafe { Box::from_raw(ptr.as_ptr().cast::()) } + } + + /// Convert from `VoiceOut` to opaque `SWVoiceOut` pointer using Box + fn voice_out_to_ptr(&self, voice: Box) -> NonNull { + NonNull::new(Box::into_raw(voice).cast::()).= unwrap() + } + + /// Convert from opaque `SWVoiceIn` pointer to `VoiceIn` using Box + /// + /// # Safety + /// The pointer must be a valid pointer that was previously created by + /// `voice_in_to_ptr` + unsafe fn ptr_to_voice_in(&self, ptr: NonNull) ->= Box { + unsafe { Box::from_raw(ptr.as_ptr().cast::()) } + } + + /// Convert from `VoiceIn` to opaque `SWVoiceIn` pointer using Box + fn voice_in_to_ptr(&self, voice: Box) -> NonNull { + NonNull::new(Box::into_raw(voice).cast::()).u= nwrap() + } + + /// Convert from opaque `CaptureVoiceOut` pointer to Capture using Box + /// + /// # Safety + /// The pointer must be a valid pointer that was previously created by + /// `capture_to_ptr` + unsafe fn ptr_to_capture(&self, ptr: NonNull) -> Box { + unsafe { Box::from_raw(ptr.as_ptr().cast::()) } + } + + /// Convert from Capture to opaque `CaptureVoiceOut` pointer using Box + fn capture_to_ptr(&self, capture: Self::Capture) -> NonNull { + NonNull::new(Box::into_raw(Box::new(capture)).cast::()).unwrap() + } +} + +unsafe extern "C" fn rust_realize_fn( + be: *mut bindings::AudioBackend, + dev: *mut bindings::Audiodev, + errp: *mut *mut util::bindings::Error, +) -> bool { + let be =3D NonNull::new(be).unwrap().cast::(); + let dev =3D NonNull::new(dev).unwrap().cast(); + let result =3D unsafe { be.as_ref() }.realize(unsafe { dev.as_ref() }); + unsafe { Error::bool_or_propagate(result, errp) } +} + +unsafe extern "C" fn rust_get_id_fn( + be: *mut bindings::AudioBackend, +) -> *const std::os::raw::c_char { + let be =3D NonNull::new(be).unwrap().cast::(); + let id =3D unsafe { be.as_ref() }.id(); + id.as_ptr() +} + +unsafe extern "C" fn rust_open_out_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceOut, + name: *const std::os::raw::c_char, + callback_opaque: *mut std::os::raw::c_void, + callback_fn: Option, + settings: *mut bindings::audsettings, +) -> *mut bindings::SWVoiceOut { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let name =3D unsafe { CStr::from_ptr(name) }; + let settings =3D unsafe { settings.as_ref().unwrap() }; + + let sw_voice =3D NonNull::new(sw).map(|ptr| unsafe { be_ref.ptr_to_voi= ce_out(ptr) }); + + let rust_callback =3D c_callback_to_rust(callback_fn, callback_opaque); + + let result =3D be_ref.open_out( + sw_voice.map(|boxed| *boxed), + name, + rust_callback.unwrap(), + settings, + ); + + result.map_or(std::ptr::null_mut(), |voice| { + be_ref.voice_out_to_ptr(Box::new(voice)).as_ptr() + }) +} + +unsafe extern "C" fn rust_open_in_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceIn, + name: *const std::os::raw::c_char, + callback_opaque: *mut std::os::raw::c_void, + callback_fn: Option, + settings: *mut bindings::audsettings, +) -> *mut bindings::SWVoiceIn { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let name =3D unsafe { CStr::from_ptr(name) }; + let settings =3D unsafe { settings.as_ref().unwrap() }; + + let sw_voice =3D NonNull::new(sw).map(|ptr| unsafe { be_ref.ptr_to_voi= ce_in(ptr) }); + + let rust_callback =3D c_callback_to_rust(callback_fn, callback_opaque); + + let result =3D be_ref.open_in( + sw_voice.map(|boxed| *boxed), + name, + rust_callback.unwrap(), + settings, + ); + + result.map_or(std::ptr::null_mut(), |voice| { + be_ref.voice_in_to_ptr(Box::new(voice)).as_ptr() + }) +} + +unsafe extern "C" fn rust_close_out_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceOut, +) { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let voice =3D unsafe { be_ref.ptr_to_voice_out(sw) }; + be_ref.close_out(*voice); +} + +unsafe extern "C" fn rust_close_in_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceIn, +) { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let voice =3D unsafe { be_ref.ptr_to_voice_in(sw) }; + be_ref.close_in(*voice); +} + +unsafe extern "C" fn rust_is_active_out_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceOut, +) -> bool { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let voice =3D unsafe { be_ref.ptr_to_voice_out(sw) }; + let result =3D be_ref.is_active_out(&voice); + std::mem::forget(voice); + result +} + +unsafe extern "C" fn rust_is_active_in_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceIn, +) -> bool { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let voice =3D unsafe { be_ref.ptr_to_voice_in(sw) }; + let result =3D be_ref.is_active_in(&voice); + std::mem::forget(voice); + result +} + +unsafe extern "C" fn rust_set_active_out_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceOut, + on: bool, +) { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let mut voice =3D unsafe { be_ref.ptr_to_voice_out(sw) }; + be_ref.set_active_out(&mut voice, on); + std::mem::forget(voice); +} + +unsafe extern "C" fn rust_set_active_in_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceIn, + on: bool, +) { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let mut voice =3D unsafe { be_ref.ptr_to_voice_in(sw) }; + be_ref.set_active_in(&mut voice, on); + std::mem::forget(voice); +} + +unsafe extern "C" fn rust_set_volume_out_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceOut, + vol: *mut bindings::Volume, +) { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let vol =3D unsafe { vol.as_ref().unwrap() }; + let mut voice =3D unsafe { be_ref.ptr_to_voice_out(sw) }; + be_ref.set_volume_out(&mut voice, vol); + std::mem::forget(voice); +} + +unsafe extern "C" fn rust_set_volume_in_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceIn, + vol: *mut bindings::Volume, +) { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let vol =3D unsafe { vol.as_ref().unwrap() }; + let mut voice =3D unsafe { be_ref.ptr_to_voice_in(sw) }; + be_ref.set_volume_in(&mut voice, vol); + std::mem::forget(voice); +} + +unsafe extern "C" fn rust_write_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceOut, + buf: *mut std::os::raw::c_void, + size: usize, +) -> usize { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let mut voice =3D unsafe { be_ref.ptr_to_voice_out(sw) }; + let buf_slice =3D unsafe { std::slice::from_raw_parts(buf as *const u8= , size) }; + let result =3D be_ref.write(&mut voice, buf_slice); + // Put the voice back - we need to leak it since we only borrowed it + std::mem::forget(voice); + result +} + +unsafe extern "C" fn rust_read_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceIn, + buf: *mut std::os::raw::c_void, + size: usize, +) -> usize { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let mut voice =3D unsafe { be_ref.ptr_to_voice_in(sw) }; + let buf_slice =3D unsafe { std::slice::from_raw_parts_mut(buf.cast::(), size) }; + let result =3D be_ref.read(&mut voice, buf_slice); + std::mem::forget(voice); + result +} + +unsafe extern "C" fn rust_get_buffer_size_out_fn( + be: *mut bindings::AudioBackend, + sw: *mut bindings::SWVoiceOut, +) -> std::os::raw::c_int { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let sw =3D NonNull::new(sw).unwrap(); + let mut voice =3D unsafe { be_ref.ptr_to_voice_out(sw) }; + let result =3D be_ref.get_buffer_size_out(&mut voice); + std::mem::forget(voice); + result +} + +struct CToRustCaptureOpsBridge { + notify_fn: + Option, + capture_fn: Option< + unsafe extern "C" fn( + *mut std::os::raw::c_void, + *const std::os::raw::c_void, + std::os::raw::c_int, + ), + >, + destroy_fn: Option, + opaque: *mut std::os::raw::c_void, +} + +// SAFETY: The bridge is Send because it only contains function pointers a= nd raw +// pointers. The caller must ensure thread safety when using the opaque po= inter. +unsafe impl Send for CToRustCaptureOpsBridge {} + +impl CToRustCaptureOpsBridge { + fn new(c_ops: &bindings::audio_capture_ops, opaque: *mut std::os::raw:= :c_void) -> Self { + Self { + notify_fn: c_ops.notify, + capture_fn: c_ops.capture, + destroy_fn: c_ops.destroy, + opaque, + } + } +} + +impl AudioCaptureOps for CToRustCaptureOpsBridge { + fn notify(&mut self, cmd: CaptureNotification) { + if let Some(notify_fn) =3D self.notify_fn { + unsafe { + notify_fn(self.opaque, cmd); + } + } + } + + fn capture(&mut self, buf: &[u8]) { + if let Some(capture_fn) =3D self.capture_fn { + unsafe { + capture_fn( + self.opaque, + buf.as_ptr().cast::(), + buf.len() as std::os::raw::c_int, + ); + } + } + } + + fn destroy(&mut self) { + if let Some(destroy_fn) =3D self.destroy_fn { + unsafe { + destroy_fn(self.opaque); + } + } + } +} + +unsafe extern "C" fn rust_add_capture_fn( + be: *mut bindings::AudioBackend, + settings: *mut bindings::audsettings, + ops: *mut bindings::audio_capture_ops, + cb_opaque: *mut std::os::raw::c_void, +) -> *mut bindings::CaptureVoiceOut { + let be =3D NonNull::new(be).unwrap().cast::(); + let settings =3D unsafe { settings.as_ref().unwrap() }; + let ops =3D unsafe { ops.as_ref().unwrap() }; + + let bridge =3D CToRustCaptureOpsBridge::new(ops, cb_opaque); + let rust_ops =3D Box::new(bridge) as Box; + + let result =3D unsafe { be.as_ref() }.add_capture(settings, rust_ops); + result.map_or(std::ptr::null_mut(), |capture| { + unsafe { be.as_ref() }.capture_to_ptr(capture).as_ptr() + }) +} + +unsafe extern "C" fn rust_del_capture_fn( + be: *mut bindings::AudioBackend, + cap: *mut bindings::CaptureVoiceOut, + _cb_opaque: *mut std::os::raw::c_void, +) { + let be =3D NonNull::new(be).unwrap().cast::(); + let be_ref =3D unsafe { be.as_ref() }; + let cap_ptr =3D NonNull::new(cap).unwrap(); + let capture =3D *unsafe { be_ref.ptr_to_capture(cap_ptr) }; + be_ref.del_capture(capture); +} + +unsafe extern "C" fn rust_set_dbus_server_fn( + be: *mut bindings::AudioBackend, + manager: *mut gio_sys::GDBusObjectManagerServer, + p2p: bool, + errp: *mut *mut util::bindings::Error, +) -> bool { + let be =3D NonNull::new(be).unwrap().cast::(); + let result =3D unsafe { be.as_ref() }.set_dbus_server(manager, p2p); + unsafe { Error::bool_or_propagate(result, errp) } +} + +// SAFETY: The C audio callback is expected to handle its own thread safet= y. +struct SendCb( + unsafe extern "C" fn(*mut std::os::raw::c_void, std::os::raw::c_int), + *mut std::os::raw::c_void, +); +unsafe impl Send for SendCb {} + +impl SendCb { + fn call(&self, available: i32) { + unsafe { (self.0)(self.1, available) } + } +} + +fn c_callback_to_rust( + c_fn: Option, + opaque: *mut std::os::raw::c_void, +) -> Option { + c_fn.map(|f| -> AudioCallback { + let cb =3D SendCb(f, opaque); + Box::new(move |available| cb.call(available)) + }) +} + +impl AudioBackendClass { + pub(crate) fn class_init(&mut self) { + self.realize =3D Some(rust_realize_fn::); + self.get_id =3D Some(rust_get_id_fn::); + self.open_out =3D Some(rust_open_out_fn::); + self.open_in =3D Some(rust_open_in_fn::); + self.close_out =3D Some(rust_close_out_fn::); + self.close_in =3D Some(rust_close_in_fn::); + self.is_active_out =3D Some(rust_is_active_out_fn::); + self.is_active_in =3D Some(rust_is_active_in_fn::); + self.set_active_out =3D Some(rust_set_active_out_fn::); + self.set_active_in =3D Some(rust_set_active_in_fn::); + self.set_volume_out =3D Some(rust_set_volume_out_fn::); + self.set_volume_in =3D Some(rust_set_volume_in_fn::); + self.write =3D Some(rust_write_fn::); + self.read =3D Some(rust_read_fn::); + self.get_buffer_size_out =3D Some(rust_get_buffer_size_out_fn::= ); + self.add_capture =3D Some(rust_add_capture_fn::); + self.del_capture =3D Some(rust_del_capture_fn::); + self.set_dbus_server =3D Some(rust_set_dbus_server_fn::); + } +} + +unsafe impl ObjectType for AudioBackend { + type Class =3D AudioBackendClass; + const TYPE_NAME: &'static CStr =3D + unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_AUDIO_= BACKEND) }; +} +qom_isa!(AudioBackend: Object); diff --git a/rust/audio/src/bindings.rs b/rust/audio/src/bindings.rs new file mode 100644 index 0000000000..aee53473a8 --- /dev/null +++ b/rust/audio/src/bindings.rs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#![allow( + dead_code, + improper_ctypes_definitions, + improper_ctypes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unnecessary_transmutes, + unsafe_op_in_unsafe_fn, + clippy::pedantic, + clippy::restriction, + clippy::style, + clippy::missing_const_for_fn, + clippy::ptr_offset_with_cast, + clippy::useless_transmute, + clippy::missing_safety_doc, + clippy::too_many_arguments +)] + +use gio_sys::GDBusObjectManagerServer; +use glib_sys::{GHashTable, GHashTableIter, GPtrArray, GSList}; +use qom::bindings::ObjectClass; +use util::bindings::Error; + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); + +unsafe impl Send for audio_capture_ops {} diff --git a/rust/audio/src/gstreamer.rs b/rust/audio/src/gstreamer.rs new file mode 100644 index 0000000000..8b99944c9a --- /dev/null +++ b/rust/audio/src/gstreamer.rs @@ -0,0 +1,1070 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +use std::{ + ffi::{CStr, CString}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, + }, + time::Instant, +}; + +use bql::{BqlCell, BqlRefCell}; +use common::uninit_field_mut; +use futures::StreamExt; +use gst::prelude::*; +use gst_app::{glib, gst}; +use gst_audio::{self, prelude::StreamVolumeExt, StreamVolume}; +use qom::{prelude::*, ObjectImpl, ParentField, ParentInit}; +// Import qom traits explicitly to avoid ambiguity with gst traits +use qom::{IsA as QomIsA, ObjectType as QomObjectType}; +use util::{log::Log, log_mask_ln, Error, Result}; + +use crate::{ + bindings::{self}, + AudioBackend, AudioBackendImpl, AudioCallback, AudiodevGStreamerOption= s, + AudiodevPerDirectionOptions, CaptureNotification, +}; + +::trace::include_trace!("audio"); + +#[repr(C)] +#[derive(qom::Object)] +pub struct AudioGStreamer { + parent_obj: ParentField, + + id: BqlCell, + opt: BqlRefCell>, + mixer_pipeline: BqlRefCell>, +} + +qom_isa!(AudioGStreamer : AudioBackend, Object); + +#[repr(C)] +pub struct AudioGStreamerClass { + parent_class: ::Class, +} + +// Shared mixer pipeline for mixing multiple audio voices +struct MixerPipeline { + pipeline: gst::Pipeline, + mixer: gst::Element, + tee: gst::Element, + #[allow(dead_code)] // For RAII reasons + bus_watch: gst::bus::BusWatchGuard, +} + +trait AudioGStreamerImpl: AudioBackendImpl + QomIsA {} + +impl AudioGStreamerClass { + fn class_init(&mut self) { + self.parent_class.class_init::(); + } +} + +impl AudioGStreamerImpl for AudioGStreamer {} + +unsafe impl QomObjectType for AudioGStreamer { + type Class =3D AudioGStreamerClass; + + const TYPE_NAME: &'static CStr =3D crate::TYPE_AUDIO_GSTREAMER; +} + +impl ObjectImpl for AudioGStreamer { + type ParentType =3D AudioBackend; + + const INSTANCE_INIT: Option)> =3D Some(Self= ::init); + const CLASS_INIT: fn(&mut Self::Class) =3D Self::Class::class_init::; +} + +enum VoiceOutKind { + Mixed, + Standalone(gst::bus::BusWatchGuard), +} + +pub struct VoiceOut { + kind: VoiceOutKind, + pipeline: gst::Pipeline, + stream_volume: Option, + appsrc: gst_app::AppSrc, + active: Arc, + active_time: Option, + bytes_written: usize, + bytes_per_second: usize, + offset_time: Option, +} + +pub struct VoiceIn { + pipeline: gst::Pipeline, + appsink: gst_app::AppSink, + active: bool, + pending_data: Arc>>, +} + +pub struct Capture { + bin: gst::Bin, + tee_pad: gst::Pad, + ops: Arc>>, +} + +impl AudioBackendImpl for AudioGStreamer { + type VoiceOut =3D VoiceOut; + type VoiceIn =3D VoiceIn; + type Capture =3D Capture; + + fn realize(&self, dev: &bindings::Audiodev) -> Result<()> { + if dev.id.is_null() { + return Err(Error::msg("dev.id is null")); + } + + gst::init()?; + let id_cstr =3D unsafe { CStr::from_ptr(dev.id) }; + let id =3D CString::new(id_cstr.to_bytes())?; + self.id.set(id); + + // ideally using qapi-rs instead + let gst =3D unsafe { &dev.u.gstreamer }; + let opt: AudiodevGStreamerOptions =3D gst.into(); + + if opt + .out + .as_ref() + .and_then(|o| o.mixing_engine) + .unwrap_or(false) + { + let mixer_pipeline =3D create_mixer_pipeline(&opt)?; + *self.mixer_pipeline.borrow_mut() =3D Some(mixer_pipeline); + } else { + if opt + .out + .as_ref() + .and_then(|o| o.fixed_settings) + .unwrap_or(false) + { + log_mask_ln!( + Log::Unimp, + "Fixed settings aren't supported in non-mixer mode" + ); + } + if opt.out.as_ref().and_then(|o| o.buffer_length).is_some() { + log_mask_ln!( + Log::Unimp, + "Buffer length isn't supported in non-mixer mode" + ); + } + } + + if opt.in_ !=3D Default::default() { + log_mask_ln!(Log::Unimp, "Input configuration isn't supported = yet"); + } + + *self.opt.borrow_mut() =3D Some(opt); + + Ok(()) + } + + fn id(&self) -> &CString { + unsafe { &*self.id.as_ptr() } + } + + fn open_out( + &self, + sw: Option, + name: &CStr, + callback_fn: AudioCallback, + settings: &bindings::audsettings, + ) -> Option { + let mut active =3D false; + if let Some(voice) =3D sw { + active =3D voice.active.load(Ordering::Relaxed); + self.close_out(voice); + } + + let mixer_pipeline_ref =3D self.mixer_pipeline.borrow(); + let mut result =3D if let Some(mixer_pipeline) =3D mixer_pipeline_= ref.as_ref() { + create_mixed_voice(mixer_pipeline, settings, name) + } else { + create_standalone_voice(settings, name, self.opt.borrow().as_r= ef().unwrap()) + }; + + if let Ok(voice) =3D &mut result { + let (mut tx, mut rx) =3D futures::channel::mpsc::channel(1); + + let appsrc_clone =3D voice.appsrc.clone(); + let active_clone =3D voice.active.clone(); + glib::MainContext::default().spawn(async move { + loop { + // TODO: some emulated devices don't call write() afte= r callback (ex: hda) + // we need to call them regularly. Ideally, they shoul= d call write() when data is available. + let timeout =3D glib::timeout_future(std::time::Durati= on::from_millis(10)); + + match futures::future::select(rx.next(), timeout).awai= t { + futures::future::Either::Left((Some(size), _)) =3D= > { + let size =3D i32::try_from(size).unwrap_or(i32= ::MAX); + callback_fn(size); + } + futures::future::Either::Left((None, _)) =3D> brea= k, + futures::future::Either::Right(_) =3D> { + if active_clone.load(Ordering::Relaxed) + && appsrc_clone.current_level_bytes() =3D= =3D 0 + { + callback_fn(4096); + } + } + } + } + }); + + let name =3D CString::new(name.to_bytes()).unwrap(); + #[allow(clippy::shadow_unrelated)] + let active_clone =3D voice.active.clone(); + voice.appsrc.set_callbacks( + gst_app::AppSrcCallbacks::builder() + .need_data(move |_src, size| { + let size =3D size as usize; + trace::trace_gst_need_data(name.as_c_str(), size); + + if active_clone.load(Ordering::Relaxed) { + if let Err(err) =3D tx.try_send(size) { + eprintln!("Failed to send need-data to mai= n loop: {err}"); + } + } + }) + .build(), + ); + + self.set_active_out(voice, active); + }; + + result + .inspect_err(|e| eprintln!("Failed to create voice output: {e}= ")) + .ok() + } + + fn open_in( + &self, + sw: Option, + name: &CStr, + callback_fn: AudioCallback, + settings: &bindings::audsettings, + ) -> Option { + let mut active =3D false; + if let Some(voice) =3D sw { + active =3D voice.active; + self.close_in(voice); + } + + let mut result =3D create_input_voice(self.opt.borrow().as_ref().u= nwrap(), settings); + + if let Ok(voice) =3D &mut result { + let (mut tx, mut rx) =3D futures::channel::mpsc::channel::(1); + let pending_data =3D voice.pending_data.clone(); + + let name =3D CString::new(name.to_bytes()).unwrap(); + glib::MainContext::default().spawn(async move { + while let Some(sample) =3D rx.next().await { + let Some(buffer) =3D sample.buffer() else { + continue; + }; + let size =3D buffer.size(); + trace::trace_gst_new_sample(name.as_c_str(), size); + match buffer.map_readable() { + Ok(buffer) =3D> { + if let Ok(mut data) =3D pending_data.lock() { + data.extend_from_slice(buffer.as_slice()); + } + callback_fn(size.try_into().unwrap()); + } + Err(err) =3D> { + eprintln!("Failed to map buffer: {err}"); + continue; + } + }; + } + }); + + voice.appsink.set_callbacks( + gst_app::AppSinkCallbacks::builder() + .new_sample(move |sink| { + // FIXME: with 1.28, we could get "current-level-b= ytes" instead, and let read() pull + let sample =3D sink.pull_sample().map_err(|_| gst:= :FlowError::Eos)?; + tx.try_send(sample).map_err(|_| gst::FlowError::Eo= s)?; + Ok(gst::FlowSuccess::Ok) + }) + .build(), + ); + + self.set_active_in(voice, active); + } + + if let Err(e) =3D &result { + eprintln!("Failed to create voice input: {e}"); + } + result.ok() + } + + fn close_out(&self, mut sw: Self::VoiceOut) { + match sw.kind { + VoiceOutKind::Mixed =3D> { + self.set_active_out(&mut sw, false); + if let Some(bin) =3D sw + .appsrc + .parent() + .and_then(|p| p.downcast::().ok()) + { + let _ =3D bin.set_state(gst::State::Null); + let mp =3D self.mixer_pipeline.borrow(); + if let Some(pad) =3D bin.sink_pads().first() { + if let Some(peer) =3D pad.peer() { + let _ =3D pad.unlink(&peer); + mp.as_ref().unwrap().mixer.release_request_pad= (&peer); + } + } + if let Err(err) =3D mp.as_ref().unwrap().pipeline.remo= ve(&bin) { + eprintln!("Failed to remove voice from pipeline: {= err}"); + } + } + } + VoiceOutKind::Standalone(_bus_watch_guard) =3D> { + if let Err(e) =3D sw.pipeline.set_state(gst::State::Null) { + eprintln!("Warning: Failed to set to null state: {e}"); + } + } + } + } + + fn close_in(&self, mut sw: Self::VoiceIn) { + self.set_active_in(&mut sw, false); + if let Err(e) =3D sw.pipeline.set_state(gst::State::Null) { + eprintln!("Warning: Failed to set to null state: {e}"); + } + } + + fn is_active_out(&self, sw: &Self::VoiceOut) -> bool { + sw.active.load(Ordering::Relaxed) + } + + fn is_active_in(&self, sw: &Self::VoiceIn) -> bool { + sw.active + } + + fn set_active_out(&self, sw: &mut Self::VoiceOut, on: bool) { + if sw.active.load(Ordering::Relaxed) =3D=3D on { + return; + } + + sw.active.store(on, Ordering::Relaxed); + sw.bytes_written =3D 0; + sw.active_time =3D if on { Some(Instant::now()) } else { None }; + sw.offset_time =3D None; + + match &sw.kind { + VoiceOutKind::Mixed =3D> { + let Some(bin) =3D sw + .appsrc + .parent() + .and_then(|p| p.downcast::().ok()) + else { + eprintln!("Failed to get parent bin for voice"); + return; + }; + + set_playing(bin.upcast_ref(), on); + } + VoiceOutKind::Standalone(_bus_watch_guard) =3D> { + set_playing(sw.pipeline.upcast_ref(), on); + } + } + } + + fn set_active_in(&self, sw: &mut Self::VoiceIn, on: bool) { + sw.active =3D on; + set_playing(sw.pipeline.upcast_ref(), on); + } + + fn set_volume_out(&self, sw: &mut Self::VoiceOut, vol: &bindings::Volu= me) { + let volume =3D qemu_volume_to_gst(vol); + + if let Some(ref stream_volume) =3D sw.stream_volume { + stream_volume.set_volume(gst_audio::StreamVolumeFormat::Linear= , volume); + stream_volume.set_mute(vol.mute); + } else if let Some(sink) =3D find_sink_element(&sw.pipeline) { + set_element_volume(sink, volume, vol.mute); + } else { + eprintln!("Failed to find volume control in pipeline"); + } + } + + fn set_volume_in(&self, sw: &mut Self::VoiceIn, vol: &bindings::Volume= ) { + let volume =3D qemu_volume_to_gst(vol); + + if let Some(stream_volume) =3D sw + .pipeline + .upcast_ref::() + .by_interface(gst_audio::StreamVolume::static_type()) + .and_then(|elem| elem.dynamic_cast::(= ).ok()) + { + stream_volume.set_volume(gst_audio::StreamVolumeFormat::Linear= , volume); + stream_volume.set_mute(vol.mute); + } else if let Some(source) =3D find_source_element(&sw.pipeline) { + set_element_volume(source, volume, vol.mute) + } else { + eprintln!("Failed to find volume control in input pipeline"); + } + } + + fn write(&self, sw: &mut Self::VoiceOut, buf: &[u8]) -> usize { + if buf.is_empty() || !sw.active.load(Ordering::Relaxed) { + return 0; + } + + if let Some(timer) =3D sw.active_time { + trace::trace_gst_write( + sw.bytes_written, + timer.elapsed().as_millis() as u64, + sw.bytes_per_second, + ) + } + + let offset_time =3D sw + .offset_time + .get_or_insert_with(|| sw.pipeline.current_running_time().unwr= ap_or_default()); + + assert!(sw.bytes_per_second > 0); + let pts =3D gst::ClockTime::from_nseconds( + sw.bytes_written as u64 * gst::ClockTime::SECOND.nseconds() + / sw.bytes_per_second as u64 + + offset_time.nseconds(), + ); + + let mut gst_buffer =3D match gst::Buffer::with_size(buf.len()) { + Ok(buffer) =3D> buffer, + Err(e) =3D> { + eprintln!("Failed to create GStreamer buffer: {e}"); + return 0; + } + }; + + { + let Some(buffer_ref) =3D gst_buffer.get_mut() else { + eprintln!("Failed to get mutable reference to GStreamer bu= ffer"); + return 0; + }; + + let duration =3D gst::ClockTime::from_nseconds( + buf.len() as u64 * gst::ClockTime::SECOND.nseconds() / sw.= bytes_per_second as u64, + ); + + buffer_ref.set_pts(pts); + buffer_ref.set_duration(duration); + + let mut mapped_buffer =3D match buffer_ref.map_writable() { + Ok(mapped) =3D> mapped, + Err(e) =3D> { + eprintln!("Failed to map GStreamer buffer for writing:= {e}"); + return 0; + } + }; + mapped_buffer.copy_from_slice(buf); + } + + sw.bytes_written +=3D buf.len(); + + match sw.appsrc.push_buffer(gst_buffer) { + Ok(_) =3D> buf.len(), + Err(e) =3D> { + eprintln!("Failed to push buffer to appsrc: {e}"); + 0 + } + } + } + + fn read(&self, sw: &mut Self::VoiceIn, buf: &mut [u8]) -> usize { + if buf.is_empty() || !sw.active { + return 0; + } + + let mut total_read =3D 0; + + while total_read < buf.len() { + // First, try to consume pending data from previous read + if let Ok(mut pending) =3D sw.pending_data.lock() { + if !pending.is_empty() { + let bytes_to_copy =3D pending.len().min(buf.len() - to= tal_read); + buf[total_read..total_read + bytes_to_copy] + .copy_from_slice(&pending[..bytes_to_copy]); + pending.drain(..bytes_to_copy); + total_read +=3D bytes_to_copy; + if total_read >=3D buf.len() { + break; + } + } + } + + // Try to pull a new sample from the appsink + let sample =3D match sw.appsink.try_pull_sample(gst::ClockTime= ::ZERO) { + Some(sample) =3D> sample, + None =3D> break, + }; + + let buffer =3D match sample.buffer() { + Some(buffer) =3D> buffer, + None =3D> break, + }; + + let map =3D match buffer.map_readable() { + Ok(map) =3D> map, + Err(e) =3D> { + eprintln!("Failed to map input buffer for reading: {e}= "); + break; + } + }; + + let data =3D map.as_slice(); + let needed =3D buf.len() - total_read; + let bytes_to_copy =3D data.len().min(needed); + + buf[total_read..total_read + bytes_to_copy].copy_from_slice(&d= ata[..bytes_to_copy]); + total_read +=3D bytes_to_copy; + + // If there's remaining data, save it for next read + if bytes_to_copy < data.len() { + if let Ok(mut pending) =3D sw.pending_data.lock() { + pending.extend_from_slice(&data[bytes_to_copy..]); + } + break; + } + } + + total_read + } + + fn get_buffer_size_out(&self, sw: &mut Self::VoiceOut) -> i32 { + // Maybe it should query the pipeline for latency instead + // Tbh, it looks like this API is not very useful in QEMU + sw.appsrc.current_level_bytes() as i32 + } + + fn add_capture( + &self, + settings: &bindings::audsettings, + ops: Box, + ) -> Option { + match self.try_add_capture(settings, ops) { + Ok(capture) =3D> Some(capture), + Err(e) =3D> { + eprintln!("Failed to add capture: {e}"); + None + } + } + } + + fn del_capture(&self, cap: Self::Capture) { + if let Ok(mut ops_guard) =3D cap.ops.lock() { + ops_guard.destroy(); + } + + if let Some(ghost_pad) =3D cap.bin.static_pad("sink") { + let _ =3D cap.tee_pad.unlink(&ghost_pad); + } + + if let Some(tee) =3D cap.tee_pad.parent_element() { + tee.release_request_pad(&cap.tee_pad); + } + + if let Err(e) =3D cap.bin.set_state(gst::State::Null) { + eprintln!("Warning: Failed to set capture bin to null state: {= e}"); + } + + if let Some(pipeline) =3D cap + .bin + .parent() + .and_then(|p| p.downcast::().ok()) + { + if let Err(e) =3D pipeline.remove(&cap.bin) { + eprintln!("Warning: Failed to remove capture bin from pipe= line: {e}"); + } + } + } + + fn set_dbus_server( + &self, + _manager: *mut gio_sys::GDBusObjectManagerServer, + _p2p: bool, + ) -> Result<()> { + Err(Error::msg("DBus not supported by this backend")) + } +} + +impl AudioGStreamer { + fn try_add_capture( + &self, + settings: &bindings::audsettings, + ops: Box, + ) -> Result { + let mixer_pipeline_ref =3D self.mixer_pipeline.borrow(); + let mixer_pipeline =3D mixer_pipeline_ref + .as_ref() + .ok_or_else(|| Error::msg("Capture is only supported when mixi= ng-engine is enabled"))?; + + let caps =3D build_audio_caps(settings)?; + let appsink =3D gst_app::AppSink::builder().caps(&caps).sync(false= ).build(); + + let ops =3D Arc::new(Mutex::new(ops)); + let ops_clone =3D ops.clone(); + // Set up callback to pull samples from appsink + appsink.set_callbacks( + gst_app::AppSinkCallbacks::builder() + .new_sample(move |sink| { + let sample =3D sink.pull_sample().map_err(|_| gst::Flo= wError::Eos)?; + let buffer =3D sample.buffer().ok_or(gst::FlowError::E= rror)?; + + let map =3D buffer.map_readable().map_err(|_| gst::Flo= wError::Error)?; + let data =3D map.as_slice(); + + trace::trace_gst_new_sample(c"capture", data.len()); + // Forward captured audio to ops + if let Ok(mut ops_guard) =3D ops_clone.lock() { + ops_guard.notify(CaptureNotification::AUD_CNOTIFY_= ENABLE); + ops_guard.capture(data); + } + + Ok(gst::FlowSuccess::Ok) + }) + .build(), + ); + + let bin =3D gst::Bin::new(); + + let queue =3D create_element("queue")?; + let audioconvert =3D create_element("audioconvert")?; + let audioresample =3D create_element("audioresample")?; + + bin.add_many([&queue, &audioconvert, &audioresample, appsink.upcas= t_ref()])?; + + gst::Element::link_many([&queue, &audioconvert, &audioresample, ap= psink.upcast_ref()])?; + + let queue_sink_pad =3D queue + .static_pad("sink") + .ok_or_else(|| Error::msg("Failed to get queue sink pad"))?; + let ghost_pad =3D gst::GhostPad::with_target(&queue_sink_pad)?; + ghost_pad.set_active(true)?; + bin.add_pad(&ghost_pad)?; + + mixer_pipeline.pipeline.add(&bin)?; + + let tee_pad =3D mixer_pipeline + .tee + .request_pad_simple("src_%u") + .ok_or_else(|| Error::msg("Failed to request pad from tee"))?; + + // Link tee =E2=86=92 bin (ghost pad) + tee_pad.link(&ghost_pad)?; + + bin.sync_state_with_parent()?; + + Ok(Capture { bin, tee_pad, ops }) + } + + unsafe fn init(mut this: ParentInit) { + uninit_field_mut!(*this, id).write(BqlCell::new(CString::new("inva= lid-id").unwrap())); + uninit_field_mut!(*this, opt).write(BqlRefCell::new(None)); + uninit_field_mut!(*this, mixer_pipeline).write(BqlRefCell::new(Non= e)); + } +} + +fn set_playing(elem: &gst::Element, on: bool) { + let target_state =3D if on { + gst::State::Playing + } else { + gst::State::Null + }; + + if let Err(e) =3D elem.set_state(target_state) { + eprintln!("Failed to set element state to {target_state:?}: {e}"); + } +} + +/// Build `GStreamer` caps for the given audio settings +fn build_audio_caps(settings: &bindings::audsettings) -> Result= { + let format =3D audio_format_to_gst_format(settings.fmt)?; + + Ok(gst_audio::AudioCapsBuilder::new_interleaved() + .format(format) + .rate(settings.freq) + .channels(settings.nchannels) + .build()) +} + +/// Find the sink element in the pipeline +fn find_sink_element(pipeline: &gst::Pipeline) -> Option { + pipeline.iterate_sinks().into_iter().flatten().next() +} + +/// Find the source element in the pipeline +fn find_source_element(pipeline: &gst::Pipeline) -> Option { + pipeline.iterate_sources().into_iter().flatten().next() +} + +fn set_element_volume(elem: gst::Element, volume: f64, mute: bool) { + if elem.find_property("volume").is_some() { + elem.set_property("volume", volume); + } + if elem.find_property("mute").is_some() { + elem.set_property("mute", mute); + } +} + +/// Convert QEMU volume (0-255 per channel) to `GStreamer` volume (0.0-1.0) +/// Returns the average volume across all channels +fn qemu_volume_to_gst(vol: &bindings::Volume) -> f64 { + let channels =3D vol.channels.min(bindings::AUDIO_MAX_CHANNELS as i32)= as usize; + + if channels =3D=3D 0 { + return 0.0; + } + + let total: u32 =3D vol.vol[..channels].iter().map(|&v| u32::from(v)).s= um(); + + f64::from(total) / (channels as f64 * 255.0) +} + +/// Build caps from `AudiodevPerDirectionOptions` for fixed settings +fn build_caps_from_options(opt: &AudiodevPerDirectionOptions) -> Result { + let format =3D opt.format.map(audio_format_to_gst_format).transpose()?; + let rate =3D opt.frequency.map(|f| f as i32); + let channels =3D opt.channels.map(|c| c as i32); + + Ok(gst_audio::AudioCapsBuilder::new_interleaved() + .format_if_some(format) + .rate_if_some(rate) + .channels_if_some(channels) + .build()) +} + +/// Create a shared mixer pipeline for mixing multiple audio voices +fn create_mixer_pipeline(opt: &AudiodevGStreamerOptions) -> Result { + let pipeline =3D gst::Pipeline::new(); + + let mixer =3D gst::ElementFactory::make("liveadder") + .property("ignore-inactive-pads", true) + .property("force-live", true) + .build()?; + + let audioconvert =3D create_element("audioconvert")?; + let audioresample =3D create_element("audioresample")?; + let tee =3D create_element("tee")?; + let queue =3D create_element("queue")?; + let buffer_time_us =3D opt.out.as_ref().and_then(|o| o.buffer_length); + let audiosink =3D create_audiosink(&opt.sink, buffer_time_us)?; + + let capsfilter =3D if opt + .out + .as_ref() + .and_then(|o| o.fixed_settings) + .unwrap_or(false) + { + let cf =3D create_element("capsfilter")?; + let caps =3D build_caps_from_options(opt.out.as_ref().unwrap())?; + cf.set_property("caps", &caps); + Some(cf) + } else { + None + }; + + let mut elements: Vec<&gst::Element> =3D + vec![&mixer, &audioconvert, &audioresample, &tee, &queue]; + if let Some(ref cf) =3D capsfilter { + elements.push(cf); + } + elements.push(&audiosink); + + pipeline.add_many(&elements)?; + + gst::Element::link_many([&mixer, &audioconvert, &audioresample, &tee])= ?; + + if let Some(ref cf) =3D capsfilter { + gst::Element::link_many([&tee, &queue, cf, &audiosink])?; + } else { + gst::Element::link_many([&tee, &queue, &audiosink])?; + } + + let bus_watch =3D add_bus_watch(&pipeline)?; + set_playing(pipeline.upcast_ref(), true); + + Ok(MixerPipeline { + pipeline, + mixer, + tee, + bus_watch, + }) +} + +/// Create a voice output connected to the shared mixer +fn create_mixed_voice( + mixer_pipeline: &MixerPipeline, + settings: &bindings::audsettings, + name: &CStr, +) -> Result { + // Create a separate bin for this voice + let bin =3D gst::Bin::new(); + + let appsrc =3D create_appsrc(settings, name)?; + let volume =3D create_element("volume")?; + let stream_volume =3D volume + .clone() + .dynamic_cast::() + .ok(); + let identity =3D create_element("identity")?; + identity.set_property("sync", true); + let audioconvert =3D create_element("audioconvert")?; + let audioresample =3D create_element("audioresample")?; + + bin.add_many([ + appsrc.upcast_ref(), + &identity, + &volume, + &audioconvert, + &audioresample, + ])?; + gst::Element::link_many([ + appsrc.upcast_ref(), + &identity, + &volume, + &audioconvert, + &audioresample, + ])?; + + let src_pad =3D audioresample + .static_pad("src") + .ok_or_else(|| Error::msg("Failed to get source pad"))?; + + let ghost_pad =3D gst::GhostPad::with_target(&src_pad)?; + + ghost_pad.set_active(true)?; + bin.add_pad(&ghost_pad)?; + + mixer_pipeline + .pipeline + .add(bin.upcast_ref::())?; + + bin.link(&mixer_pipeline.mixer)?; + + Ok(VoiceOut { + kind: VoiceOutKind::Mixed, + pipeline: mixer_pipeline.pipeline.clone(), + stream_volume, + appsrc, + active: Arc::new(AtomicBool::new(false)), + active_time: None, + bytes_per_second: get_bytes_per_second(settings)?, + bytes_written: 0, + offset_time: None, + }) +} + +/// Create a standalone voice output without mixer or capture +fn create_standalone_voice( + settings: &bindings::audsettings, + name: &CStr, + opt: &AudiodevGStreamerOptions, +) -> Result { + let pipeline =3D gst::Pipeline::new(); + + let appsrc =3D create_appsrc(settings, name)?; + let identity =3D create_element("identity")?; + identity.set_property("sync", true); + let audioconvert =3D create_element("audioconvert")?; + let audioresample =3D create_element("audioresample")?; + let queue =3D create_element("queue")?; + + let buffer_time_us =3D opt.out.as_ref().and_then(|o| o.buffer_length); + let audiosink =3D create_audiosink(&opt.sink, buffer_time_us)?; + let stream_volume =3D audiosink + .clone() + .dynamic_cast::() + .ok(); + + pipeline.add_many([ + appsrc.upcast_ref(), + &identity, + &audioconvert, + &audioresample, + &queue, + &audiosink, + ])?; + + gst::Element::link_many([ + appsrc.upcast_ref(), + &identity, + &audioconvert, + &audioresample, + &queue, + &audiosink, + ])?; + + let bus_watch =3D add_bus_watch(&pipeline)?; + + Ok(VoiceOut { + kind: VoiceOutKind::Standalone(bus_watch), + pipeline, + stream_volume, + appsrc, + active: Arc::new(AtomicBool::new(false)), + active_time: None, + bytes_per_second: get_bytes_per_second(settings)?, + bytes_written: 0, + offset_time: None, + }) +} + +fn add_bus_watch(pipeline: &gst::Pipeline) -> Result { + // Add bus message handler to prevent queue overflow + let bus =3D pipeline + .bus() + .ok_or_else(|| Error::msg("Failed to get pipeline bus"))?; + let bus_watch =3D bus.add_watch(|_bus, msg| { + use gst::MessageView; + match msg.view() { + MessageView::Error(err) =3D> { + eprintln!( + "GStreamer error from {:?}: {} ({:?})", + err.src().map(gst::prelude::GstObjectExt::path_string), + err.error(), + err.debug() + ); + } + MessageView::Warning(warning) =3D> { + eprintln!( + "GStreamer warning from {:?}: {} ({:?})", + warning.src().map(gst::prelude::GstObjectExt::path_str= ing), + warning.error(), + warning.debug() + ); + } + _ =3D> {} + } + glib::ControlFlow::Continue + })?; + + Ok(bus_watch) +} + +/// Create an input voice for audio recording +fn create_input_voice( + opt: &AudiodevGStreamerOptions, + settings: &bindings::audsettings, +) -> Result { + let source_name =3D opt.source.as_deref().unwrap_or("autoaudiosrc"); + let pipeline =3D gst::Pipeline::new(); + + let audiosrc =3D create_element(source_name)?; + let audioconvert =3D create_element("audioconvert")?; + let audioresample =3D create_element("audioresample")?; + let caps =3D build_audio_caps(settings)?; + let appsink =3D gst_app::AppSink::builder() + .caps(&caps) + .sync(false) + .max_time(Some(gst::ClockTime::from_mseconds(10))) + .build(); + + pipeline.add_many([ + &audiosrc, + &audioconvert, + &audioresample, + appsink.upcast_ref(), + ])?; + + gst::Element::link_many([ + &audiosrc, + &audioconvert, + &audioresample, + appsink.upcast_ref(), + ])?; + + Ok(VoiceIn { + pipeline, + appsink, + active: false, + pending_data: Arc::new(Mutex::new(Vec::new())), + }) +} + +fn create_audiosink( + elem_name: &Option, + buffer_time_us: Option, +) -> Result { + const DEFAULT_BUFFER_TIME_US: u32 =3D 40_000; + + let elem_name =3D elem_name.as_deref().unwrap_or("autoaudiosink"); + let audiosink =3D create_element(elem_name)?; + let buffer_time_us: i64 =3D buffer_time_us.unwrap_or(DEFAULT_BUFFER_TI= ME_US).into(); + + if let Some(child_proxy) =3D audiosink.dynamic_cast_ref::() { + child_proxy.connect_child_added(move |_proxy, child, _child_name| { + if let Some(elem) =3D child.downcast_ref::() { + if elem.has_property("buffer-time") { + elem.set_property("buffer-time", buffer_time_us); + } else { + eprintln!("no buffer-time property on the sink"); + } + } + }); + } + + Ok(audiosink) +} + +fn create_appsrc(settings: &bindings::audsettings, name: &CStr) -> Result<= gst_app::AppSrc> { + let caps =3D build_audio_caps(settings)?; + + let appsrc =3D gst_app::AppSrc::builder() + .caps(&caps) + .is_live(true) + .format(gst::Format::Time) + // we don't want to block QEMU + .block(false) + .build(); + // create a stream-id + appsrc.set_uri(&format!("appsrc://{}", name.to_string_lossy()))?; + Ok(appsrc) +} + +/// Create a `GStreamer` element with error reporting +fn create_element(factory_name: &str) -> Result { + gst::ElementFactory::make(factory_name) + .build() + .map_err(|e| Error::msg(format!("Failed to create element '{factor= y_name}': {e}"))) +} + +fn get_bytes_per_second(settings: &bindings::audsettings) -> Result= { + let bytes_per_sample =3D get_bytes_per_sample(settings.fmt)?; + + Ok(settings.freq as usize * settings.nchannels as usize * bytes_per_sa= mple as usize) +} + +fn get_bytes_per_sample(fmt: bindings::AudioFormat) -> Result { + use bindings::AudioFormat::*; + match fmt { + AUDIO_FORMAT_U8 | AUDIO_FORMAT_S8 =3D> Ok(1), + AUDIO_FORMAT_U16 | AUDIO_FORMAT_S16 =3D> Ok(2), + AUDIO_FORMAT_U32 | AUDIO_FORMAT_S32 | AUDIO_FORMAT_F32 =3D> Ok(4), + _ =3D> Err(Error::msg(format!("Unsupported audio format: {fmt:?}")= )), + } +} + +fn audio_format_to_gst_format(fmt: bindings::AudioFormat) -> Result { + use bindings::AudioFormat::*; + use gst_audio::AudioFormat as GAF; + + match fmt { + AUDIO_FORMAT_U8 =3D> Ok(GAF::U8), + AUDIO_FORMAT_S8 =3D> Ok(GAF::S8), + AUDIO_FORMAT_U16 =3D> Ok(GAF::U16le), + AUDIO_FORMAT_S16 =3D> Ok(GAF::S16le), + AUDIO_FORMAT_U32 =3D> Ok(GAF::U32le), + AUDIO_FORMAT_S32 =3D> Ok(GAF::S32le), + AUDIO_FORMAT_F32 =3D> Ok(GAF::F32le), + _ =3D> Err(Error::msg(format!("Unsupported audio format: {fmt:?}")= )), + } +} diff --git a/rust/audio/src/lib.rs b/rust/audio/src/lib.rs new file mode 100644 index 0000000000..3e899e2439 --- /dev/null +++ b/rust/audio/src/lib.rs @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pub mod bindings; + +mod audio; +use std::ffi::CStr; + +pub use audio::*; + +mod gstreamer; + +pub const TYPE_AUDIO_GSTREAMER: &std::ffi::CStr =3D c"audio-gstreamer"; + +#[derive(Default, Debug, PartialEq, Eq)] +pub struct AudiodevGStreamerOptions { + pub in_: Option, + pub out: Option, + pub sink: Option, + pub source: Option, +} + +#[derive(Default, Debug, PartialEq, Eq)] +pub struct AudiodevPerDirectionOptions { + pub mixing_engine: Option, + pub fixed_settings: Option, + pub frequency: Option, + pub channels: Option, + pub voices: Option, + pub format: Option, + pub buffer_length: Option, +} + +impl From<&bindings::AudiodevGStreamerOptions> for AudiodevGStreamerOption= s { + fn from(value: &bindings::AudiodevGStreamerOptions) -> Self { + let in_ =3D (!value.in_.is_null()) + .then(|| AudiodevPerDirectionOptions::from(unsafe { &*value.in= _ })); + let out =3D (!value.out.is_null()) + .then(|| AudiodevPerDirectionOptions::from(unsafe { &*value.ou= t })); + let sink =3D (!value.sink.is_null()).then(|| { + unsafe { CStr::from_ptr(value.sink) } + .to_string_lossy() + .into_owned() + }); + let source =3D (!value.source.is_null()).then(|| { + unsafe { CStr::from_ptr(value.source) } + .to_string_lossy() + .into_owned() + }); + + Self { + in_, + out, + sink, + source, + } + } +} + +impl From<&bindings::AudiodevPerDirectionOptions> for AudiodevPerDirection= Options { + fn from(value: &bindings::AudiodevPerDirectionOptions) -> Self { + Self { + mixing_engine: if value.has_mixing_engine { + Some(value.mixing_engine) + } else { + None + }, + fixed_settings: if value.has_fixed_settings { + Some(value.fixed_settings) + } else { + None + }, + frequency: if value.has_frequency { + Some(value.frequency) + } else { + None + }, + channels: if value.has_channels { + Some(value.channels) + } else { + None + }, + voices: if value.has_voices { + Some(value.voices) + } else { + None + }, + format: if value.has_format { + Some(value.format) + } else { + None + }, + buffer_length: if value.has_buffer_length { + Some(value.buffer_length) + } else { + None + }, + } + } +} diff --git a/rust/meson.build b/rust/meson.build index 9f0ed48481..8c2905a7f0 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -13,6 +13,11 @@ syn_rs_native =3D cargo_ws.subproject('syn').dependency() proc_macro2_rs_native =3D cargo_ws.subproject('proc-macro2').dependency() attrs_rs_native =3D cargo_ws.subproject('attrs').dependency() =20 +futures_rs =3D cargo_ws.subproject('futures').dependency() +gio_sys_rs =3D cargo_ws.subproject('gio-sys').dependency() +gst_app_rs =3D cargo_ws.subproject('gstreamer-app').dependency() +gst_audio_rs =3D cargo_ws.subproject('gstreamer-audio').dependency() + genrs =3D [] =20 subdir('qemu-macros') @@ -29,6 +34,7 @@ subdir('hw/core') subdir('tests') subdir('trace') subdir('hw') +subdir('audio') =20 cargo =3D find_program('cargo', required: false) =20 --=20 2.51.1