@samitouri / QOSamiQemu / commits / 909f04f417

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