audio: make AudioBackend truly abstract
Add virtual methods to be implemented by concrete classes, like AudioMixengBackendClass. Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Marc-André Lureau committed
Jan 16, 2026 at 00:48 UTC
909f04f4174b8029aae8943be7a4ade4221e7b30
4 files changed
+227
-40
audio/audio.c
+174
-13
@@ -847,7 +847,8 @@ static void audio_timer (void *opaque)
847
/*
848
* Public API
849
*/
850
-size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size)
850
+static size_t audio_mixeng_backend_write(AudioBackend *be, SWVoiceOut *sw,
851
+ void *buf, size_t size)
852
{
853
HWVoiceOut *hw;
854
@@ -858,7 +859,7 @@ size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size)
859
hw = sw->hw;
860
861
if (!hw->enabled) {
861
- dolog ("Writing to disabled voice %s\n", SW_NAME (sw));
862
+ dolog("Writing to disabled voice %s\n", SW_NAME(sw));
863
return 0;
864
}
865
@@ -869,7 +870,15 @@ size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size)
870
}
871
}
872
872
-size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size)
873
+size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size)
874
+{
875
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
876
+
877
+ return klass->write(be, sw, buf, size);
878
+}
879
+
880
+static size_t audio_mixeng_backend_read(AudioBackend *be, SWVoiceIn *sw,
881
+ void *buf, size_t size)
882
{
883
HWVoiceIn *hw;
884
@@ -880,7 +889,7 @@ size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size)
889
hw = sw->hw;
890
891
if (!hw->enabled) {
883
- dolog ("Reading from disabled voice %s\n", SW_NAME (sw));
892
+ dolog("Reading from disabled voice %s\n", SW_NAME(sw));
893
return 0;
894
}
895
@@ -889,9 +898,17 @@ size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size)
898
} else {
899
return hw->pcm_ops->read(hw, buf, size);
900
}
901
+
902
}
903
894
-int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw)
904
+size_t AUD_read(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size)
905
+{
906
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
907
+
908
+ return klass->read(be, sw, buf, size);
909
+}
910
+
911
+static int audio_mixeng_backend_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw)
912
{
913
if (!sw) {
914
return 0;
@@ -904,7 +921,15 @@ int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw)
921
return sw->hw->samples * sw->hw->info.bytes_per_frame;
922
}
923
907
-void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on)
924
+int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw)
925
+{
926
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
927
+
928
+ return klass->get_buffer_size_out(be, sw);
929
+}
930
+
931
+static void audio_mixeng_backend_set_active_out(AudioBackend *be, SWVoiceOut *sw,
932
+ bool on)
933
{
934
HWVoiceOut *hw;
935
@@ -950,9 +975,17 @@ void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on)
975
}
976
sw->active = on;
977
}
978
+
979
}
980
955
-void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on)
981
+void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on)
982
+{
983
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
984
+
985
+ return klass->set_active_out(be, sw, on);
986
+}
987
+
988
+static void audio_mixeng_backend_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on)
989
{
990
HWVoiceIn *hw;
991
@@ -997,6 +1030,13 @@ void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on)
1030
}
1031
}
1032
1033
+void AUD_set_active_in(AudioBackend *be, SWVoiceIn *sw, bool on)
1034
+{
1035
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
1036
+
1037
+ return klass->set_active_in(be, sw, on);
1038
+}
1039
+
1040
static size_t audio_get_avail(SWVoiceIn *sw)
1041
{
1042
size_t live;
@@ -1658,12 +1698,97 @@ static const char *audio_mixeng_backend_get_id(AudioBackend *be)
1698
return AUDIO_MIXENG_BACKEND(be)->dev->id;
1699
}
1700
1701
+static CaptureVoiceOut *audio_mixeng_backend_add_capture(
1702
+ AudioBackend *be,
1703
+ struct audsettings *as,
1704
+ struct audio_capture_ops *ops,
1705
+ void *cb_opaque);
1706
+
1707
+static void audio_mixeng_backend_del_capture(
1708
+ AudioBackend *be,
1709
+ CaptureVoiceOut *cap,
1710
+ void *cb_opaque);
1711
+
1712
+static void audio_mixeng_backend_set_volume_out(AudioBackend *be, SWVoiceOut *sw,
1713
+ Volume *vol);
1714
+static void audio_mixeng_backend_set_volume_in(AudioBackend *be, SWVoiceIn *sw,
1715
+ Volume *vol);
1716
+
1717
+SWVoiceOut *AUD_open_out(
1718
+ AudioBackend *be,
1719
+ SWVoiceOut *sw,
1720
+ const char *name,
1721
+ void *callback_opaque,
1722
+ audio_callback_fn callback_fn,
1723
+ const struct audsettings *as)
1724
+{
1725
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
1726
+
1727
+ return klass->open_out(be, sw, name, callback_opaque, callback_fn, as);
1728
+}
1729
+
1730
+SWVoiceIn *AUD_open_in(
1731
+ AudioBackend *be,
1732
+ SWVoiceIn *sw,
1733
+ const char *name,
1734
+ void *callback_opaque,
1735
+ audio_callback_fn callback_fn,
1736
+ const struct audsettings *as)
1737
+{
1738
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
1739
+
1740
+ return klass->open_in(be, sw, name, callback_opaque, callback_fn, as);
1741
+}
1742
+
1743
+void AUD_close_out(AudioBackend *be, SWVoiceOut *sw)
1744
+{
1745
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
1746
+
1747
+ return klass->close_out(be, sw);
1748
+}
1749
+
1750
+void AUD_close_in(AudioBackend *be, SWVoiceIn *sw)
1751
+{
1752
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
1753
+
1754
+ return klass->close_in(be, sw);
1755
+}
1756
+
1757
+bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw)
1758
+{
1759
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
1760
+
1761
+ return klass->is_active_out(be, sw);
1762
+}
1763
+
1764
+bool AUD_is_active_in(AudioBackend *be, SWVoiceIn *sw)
1765
+{
1766
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
1767
+
1768
+ return klass->is_active_in(be, sw);
1769
+}
1770
+
1771
static void audio_mixeng_backend_class_init(ObjectClass *klass, const void *data)
1772
{
1773
AudioBackendClass *be = AUDIO_BACKEND_CLASS(klass);
1774
1775
be->realize = audio_mixeng_backend_realize;
1776
be->get_id = audio_mixeng_backend_get_id;
1777
+ be->open_in = audio_mixeng_backend_open_in;
1778
+ be->open_out = audio_mixeng_backend_open_out;
1779
+ be->close_in = audio_mixeng_backend_close_in;
1780
+ be->close_out = audio_mixeng_backend_close_out;
1781
+ be->is_active_out = audio_mixeng_backend_is_active_out;
1782
+ be->is_active_in = audio_mixeng_backend_is_active_in;
1783
+ be->set_active_out = audio_mixeng_backend_set_active_out;
1784
+ be->set_active_in = audio_mixeng_backend_set_active_in;
1785
+ be->set_volume_out = audio_mixeng_backend_set_volume_out;
1786
+ be->set_volume_in = audio_mixeng_backend_set_volume_in;
1787
+ be->read = audio_mixeng_backend_read;
1788
+ be->write = audio_mixeng_backend_write;
1789
+ be->get_buffer_size_out = audio_mixeng_backend_get_buffer_size_out;
1790
+ be->add_capture = audio_mixeng_backend_add_capture;
1791
+ be->del_capture = audio_mixeng_backend_del_capture;
1792
}
1793
1794
static void audio_mixeng_backend_init(Object *obj)
@@ -1863,12 +1988,11 @@ bool AUD_backend_check(AudioBackend **be, Error **errp)
1988
1989
static struct audio_pcm_ops capture_pcm_ops;
1990
1866
-CaptureVoiceOut *AUD_add_capture(
1991
+static CaptureVoiceOut *audio_mixeng_backend_add_capture(
1992
AudioBackend *be,
1993
struct audsettings *as,
1994
struct audio_capture_ops *ops,
1870
- void *cb_opaque
1871
- )
1995
+ void *cb_opaque)
1996
{
1997
AudioMixengBackend *s = AUDIO_MIXENG_BACKEND(be);
1998
CaptureVoiceOut *cap;
@@ -1938,7 +2062,21 @@ CaptureVoiceOut *AUD_add_capture(
2062
return cap;
2063
}
2064
1941
-void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaque)
2065
+CaptureVoiceOut *AUD_add_capture(
2066
+ AudioBackend *be,
2067
+ struct audsettings *as,
2068
+ struct audio_capture_ops *ops,
2069
+ void *cb_opaque)
2070
+{
2071
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
2072
+
2073
+ return klass->add_capture(be, as, ops, cb_opaque);
2074
+}
2075
+
2076
+static void audio_mixeng_backend_del_capture(
2077
+ AudioBackend *be,
2078
+ CaptureVoiceOut *cap,
2079
+ void *cb_opaque)
2080
{
2081
struct capture_callback *cb;
2082
@@ -1977,7 +2115,15 @@ void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaque)
2115
}
2116
}
2117
1980
-void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol)
2118
+void AUD_del_capture(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaque)
2119
+{
2120
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
2121
+
2122
+ klass->del_capture(be, cap, cb_opaque);
2123
+}
2124
+
2125
+static void audio_mixeng_backend_set_volume_out(AudioBackend *be, SWVoiceOut *sw,
2126
+ Volume *vol)
2127
{
2128
if (sw) {
2129
HWVoiceOut *hw = sw->hw;
@@ -1993,7 +2139,15 @@ void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol)
2139
}
2140
}
2141
1996
-void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol)
2142
+void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol)
2143
+{
2144
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
2145
+
2146
+ klass->set_volume_out(be, sw, vol);
2147
+}
2148
+
2149
+static void audio_mixeng_backend_set_volume_in(AudioBackend *be, SWVoiceIn *sw,
2150
+ Volume *vol)
2151
{
2152
if (sw) {
2153
HWVoiceIn *hw = sw->hw;
@@ -2009,6 +2163,13 @@ void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol)
2163
}
2164
}
2165
2166
+void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol)
2167
+{
2168
+ AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be);
2169
+
2170
+ klass->set_volume_in(be, sw, vol);
2171
+}
2172
+
2173
static void audio_create_pdos(Audiodev *dev)
2174
{
2175
switch (dev->driver) {
audio/audio_template.h
+4
-5
@@ -478,7 +478,7 @@ static void glue (audio_close_, TYPE) (SW *sw)
478
g_free (sw);
479
}
480
481
-void glue(AUD_close_, TYPE)(AudioBackend *be, SW *sw)
481
+static void glue(audio_mixeng_backend_close_, TYPE)(AudioBackend *be, SW *sw)
482
{
483
if (sw) {
484
if (audio_bug(__func__, !be)) {
@@ -490,14 +490,13 @@ void glue(AUD_close_, TYPE)(AudioBackend *be, SW *sw)
490
}
491
}
492
493
-SW *glue (AUD_open_, TYPE) (
493
+static SW *glue(audio_mixeng_backend_open_, TYPE) (
494
AudioBackend *be,
495
SW *sw,
496
const char *name,
497
void *callback_opaque ,
498
audio_callback_fn callback_fn,
499
- const struct audsettings *as
500
- )
499
+ const struct audsettings *as)
500
{
501
AudioMixengBackend *s = AUDIO_MIXENG_BACKEND(be);
502
AudiodevPerDirectionOptions *pdo;
@@ -569,7 +568,7 @@ SW *glue (AUD_open_, TYPE) (
568
return NULL;
569
}
570
572
-bool glue(AUD_is_active_, TYPE)(AudioBackend *be, SW *sw)
571
+static bool glue(audio_mixeng_backend_is_active_, TYPE)(AudioBackend *be, SW *sw)
572
{
573
return sw ? sw->active : 0;
574
}
include/qemu/audio-capture.h
-13
@@ -8,19 +8,6 @@
8
9
#include "audio.h"
10
11
-typedef struct CaptureVoiceOut CaptureVoiceOut;
12
-
13
-typedef enum {
14
- AUD_CNOTIFY_ENABLE,
15
- AUD_CNOTIFY_DISABLE
16
-} audcnotification_e;
17
-
18
-struct audio_capture_ops {
19
- void (*notify) (void *opaque, audcnotification_e cmd);
20
- void (*capture) (void *opaque, const void *buf, int size);
21
- void (*destroy) (void *opaque);
22
-};
23
-
11
struct capture_ops {
12
void (*info) (void *opaque);
13
void (*destroy) (void *opaque);
include/qemu/audio.h
+49
-9
@@ -43,6 +43,25 @@ typedef struct audsettings {
43
44
typedef struct SWVoiceOut SWVoiceOut;
45
typedef struct SWVoiceIn SWVoiceIn;
46
+typedef struct CaptureVoiceOut CaptureVoiceOut;
47
+
48
+typedef enum {
49
+ AUD_CNOTIFY_ENABLE,
50
+ AUD_CNOTIFY_DISABLE
51
+} audcnotification_e;
52
+
53
+struct audio_capture_ops {
54
+ void (*notify) (void *opaque, audcnotification_e cmd);
55
+ void (*capture) (void *opaque, const void *buf, int size);
56
+ void (*destroy) (void *opaque);
57
+};
58
+
59
+#define AUDIO_MAX_CHANNELS 16
60
+typedef struct Volume {
61
+ bool mute;
62
+ int channels;
63
+ uint8_t vol[AUDIO_MAX_CHANNELS];
64
+} Volume;
65
66
typedef struct AudioBackend {
67
Object parent_obj;
@@ -53,6 +72,35 @@ typedef struct AudioBackendClass {
72
73
bool (*realize)(AudioBackend *be, Audiodev *dev, Error **errp);
74
const char *(*get_id)(AudioBackend *be);
75
+ SWVoiceOut *(*open_out)(AudioBackend *be,
76
+ SWVoiceOut *sw,
77
+ const char *name,
78
+ void *callback_opaque,
79
+ audio_callback_fn callback_fn,
80
+ const struct audsettings *as);
81
+ SWVoiceIn *(*open_in)(AudioBackend *be,
82
+ SWVoiceIn *sw,
83
+ const char *name,
84
+ void *callback_opaque,
85
+ audio_callback_fn callback_fn,
86
+ const struct audsettings *as);
87
+ void (*close_out)(AudioBackend *be, SWVoiceOut *sw);
88
+ void (*close_in)(AudioBackend *be, SWVoiceIn *sw);
89
+ bool (*is_active_out)(AudioBackend *be, SWVoiceOut *sw);
90
+ bool (*is_active_in)(AudioBackend *be, SWVoiceIn *sw);
91
+ void (*set_active_out)(AudioBackend *be, SWVoiceOut *sw, bool on);
92
+ void (*set_active_in)(AudioBackend *be, SWVoiceIn *sw, bool on);
93
+ void (*set_volume_out)(AudioBackend *be, SWVoiceOut *sw, Volume *vol);
94
+ void (*set_volume_in)(AudioBackend *be, SWVoiceIn *sw, Volume *vol);
95
+ size_t (*write)(AudioBackend *be, SWVoiceOut *sw, void *buf, size_t size);
96
+ size_t (*read)(AudioBackend *be, SWVoiceIn *sw, void *buf, size_t size);
97
+ int (*get_buffer_size_out)(AudioBackend *be, SWVoiceOut *sw);
98
+ CaptureVoiceOut *(*add_capture)(AudioBackend *be,
99
+ struct audsettings *as,
100
+ struct audio_capture_ops *ops,
101
+ void *cb_opaque);
102
+ void (*del_capture)(AudioBackend *be, CaptureVoiceOut *cap, void *cb_opaque);
103
+
104
#ifdef CONFIG_GIO
105
bool (*set_dbus_server)(AudioBackend *be,
106
GDBusObjectManagerServer *manager,
@@ -69,8 +117,7 @@ SWVoiceOut *AUD_open_out(
117
const char *name,
118
void *callback_opaque,
119
audio_callback_fn callback_fn,
72
- const struct audsettings *settings
73
- );
120
+ const struct audsettings *settings);
121
122
void AUD_close_out(AudioBackend *be, SWVoiceOut *sw);
123
size_t AUD_write(AudioBackend *be, SWVoiceOut *sw, void *pcm_buf, size_t size);
@@ -78,13 +125,6 @@ int AUD_get_buffer_size_out(AudioBackend *be, SWVoiceOut *sw);
125
void AUD_set_active_out(AudioBackend *be, SWVoiceOut *sw, bool on);
126
bool AUD_is_active_out(AudioBackend *be, SWVoiceOut *sw);
127
81
-#define AUDIO_MAX_CHANNELS 16
82
-typedef struct Volume {
83
- bool mute;
84
- int channels;
85
- uint8_t vol[AUDIO_MAX_CHANNELS];
86
-} Volume;
87
-
128
void AUD_set_volume_out(AudioBackend *be, SWVoiceOut *sw, Volume *vol);
129
void AUD_set_volume_in(AudioBackend *be, SWVoiceIn *sw, Volume *vol);
130