qapi, audio: Make introspection reflect build configuration more closely

Currently the -audiodev accepts any audiodev type regardless of what is
built in to QEMU. An error only occurs later at runtime when a sound
device tries to use the audio backend.

With this change QEMU will immediately reject -audiodev args that are
not compiled into the binary. The QMP schema will also be introspectable
to identify what is compiled in.

This also helps to avoid compiling code that is not required in the
binary. Note: When building the audiodevs as modules, the patch only
compiles out code for modules that we don't build at all.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
[thuth: Rebase, take sndio and dbus devices into account]
Message-Id: <20230123083957.20349-3-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2023-01-23 09:39:57 +01:00 committed by Thomas Huth
parent 637d18090e
commit 7a92a8573c
4 changed files with 112 additions and 13 deletions

View File

@ -2048,16 +2048,36 @@ void audio_create_pdos(Audiodev *dev)
break break
CASE(NONE, none, ); CASE(NONE, none, );
#ifdef CONFIG_AUDIO_ALSA
CASE(ALSA, alsa, Alsa); CASE(ALSA, alsa, Alsa);
#endif
#ifdef CONFIG_AUDIO_COREAUDIO
CASE(COREAUDIO, coreaudio, Coreaudio); CASE(COREAUDIO, coreaudio, Coreaudio);
#endif
#ifdef CONFIG_DBUS_DISPLAY
CASE(DBUS, dbus, ); CASE(DBUS, dbus, );
#endif
#ifdef CONFIG_AUDIO_DSOUND
CASE(DSOUND, dsound, ); CASE(DSOUND, dsound, );
#endif
#ifdef CONFIG_AUDIO_JACK
CASE(JACK, jack, Jack); CASE(JACK, jack, Jack);
#endif
#ifdef CONFIG_AUDIO_OSS
CASE(OSS, oss, Oss); CASE(OSS, oss, Oss);
#endif
#ifdef CONFIG_AUDIO_PA
CASE(PA, pa, Pa); CASE(PA, pa, Pa);
#endif
#ifdef CONFIG_AUDIO_SDL
CASE(SDL, sdl, Sdl); CASE(SDL, sdl, Sdl);
#endif
#ifdef CONFIG_AUDIO_SNDIO
CASE(SNDIO, sndio, ); CASE(SNDIO, sndio, );
#endif
#ifdef CONFIG_SPICE
CASE(SPICE, spice, ); CASE(SPICE, spice, );
#endif
CASE(WAV, wav, ); CASE(WAV, wav, );
case AUDIODEV_DRIVER__MAX: case AUDIODEV_DRIVER__MAX:

View File

@ -90,6 +90,7 @@ static void get_fmt(const char *env, AudioFormat *dst, bool *has_dst)
} }
#if defined(CONFIG_AUDIO_ALSA) || defined(CONFIG_AUDIO_DSOUND)
static void get_millis_to_usecs(const char *env, uint32_t *dst, bool *has_dst) static void get_millis_to_usecs(const char *env, uint32_t *dst, bool *has_dst)
{ {
const char *val = getenv(env); const char *val = getenv(env);
@ -98,15 +99,20 @@ static void get_millis_to_usecs(const char *env, uint32_t *dst, bool *has_dst)
*has_dst = true; *has_dst = true;
} }
} }
#endif
#if defined(CONFIG_AUDIO_ALSA) || defined(CONFIG_AUDIO_COREAUDIO) || \
defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL) || \
defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS)
static uint32_t frames_to_usecs(uint32_t frames, static uint32_t frames_to_usecs(uint32_t frames,
AudiodevPerDirectionOptions *pdo) AudiodevPerDirectionOptions *pdo)
{ {
uint32_t freq = pdo->has_frequency ? pdo->frequency : 44100; uint32_t freq = pdo->has_frequency ? pdo->frequency : 44100;
return (frames * 1000000 + freq / 2) / freq; return (frames * 1000000 + freq / 2) / freq;
} }
#endif
#ifdef CONFIG_AUDIO_COREAUDIO
static void get_frames_to_usecs(const char *env, uint32_t *dst, bool *has_dst, static void get_frames_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
AudiodevPerDirectionOptions *pdo) AudiodevPerDirectionOptions *pdo)
{ {
@ -116,14 +122,19 @@ static void get_frames_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
*has_dst = true; *has_dst = true;
} }
} }
#endif
#if defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL) || \
defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS)
static uint32_t samples_to_usecs(uint32_t samples, static uint32_t samples_to_usecs(uint32_t samples,
AudiodevPerDirectionOptions *pdo) AudiodevPerDirectionOptions *pdo)
{ {
uint32_t channels = pdo->has_channels ? pdo->channels : 2; uint32_t channels = pdo->has_channels ? pdo->channels : 2;
return frames_to_usecs(samples / channels, pdo); return frames_to_usecs(samples / channels, pdo);
} }
#endif
#if defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL)
static void get_samples_to_usecs(const char *env, uint32_t *dst, bool *has_dst, static void get_samples_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
AudiodevPerDirectionOptions *pdo) AudiodevPerDirectionOptions *pdo)
{ {
@ -133,7 +144,9 @@ static void get_samples_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
*has_dst = true; *has_dst = true;
} }
} }
#endif
#if defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS)
static uint32_t bytes_to_usecs(uint32_t bytes, AudiodevPerDirectionOptions *pdo) static uint32_t bytes_to_usecs(uint32_t bytes, AudiodevPerDirectionOptions *pdo)
{ {
AudioFormat fmt = pdo->has_format ? pdo->format : AUDIO_FORMAT_S16; AudioFormat fmt = pdo->has_format ? pdo->format : AUDIO_FORMAT_S16;
@ -150,8 +163,11 @@ static void get_bytes_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
*has_dst = true; *has_dst = true;
} }
} }
#endif
/* backend specific functions */ /* backend specific functions */
#ifdef CONFIG_AUDIO_ALSA
/* ALSA */ /* ALSA */
static void handle_alsa_per_direction( static void handle_alsa_per_direction(
AudiodevAlsaPerDirectionOptions *apdo, const char *prefix) AudiodevAlsaPerDirectionOptions *apdo, const char *prefix)
@ -197,7 +213,9 @@ static void handle_alsa(Audiodev *dev)
get_millis_to_usecs("QEMU_ALSA_THRESHOLD", get_millis_to_usecs("QEMU_ALSA_THRESHOLD",
&aopt->threshold, &aopt->has_threshold); &aopt->threshold, &aopt->has_threshold);
} }
#endif
#ifdef CONFIG_AUDIO_COREAUDIO
/* coreaudio */ /* coreaudio */
static void handle_coreaudio(Audiodev *dev) static void handle_coreaudio(Audiodev *dev)
{ {
@ -210,7 +228,9 @@ static void handle_coreaudio(Audiodev *dev)
&dev->u.coreaudio.out->buffer_count, &dev->u.coreaudio.out->buffer_count,
&dev->u.coreaudio.out->has_buffer_count); &dev->u.coreaudio.out->has_buffer_count);
} }
#endif
#ifdef CONFIG_AUDIO_DSOUND
/* dsound */ /* dsound */
static void handle_dsound(Audiodev *dev) static void handle_dsound(Audiodev *dev)
{ {
@ -225,7 +245,9 @@ static void handle_dsound(Audiodev *dev)
&dev->u.dsound.in->has_buffer_length, &dev->u.dsound.in->has_buffer_length,
dev->u.dsound.in); dev->u.dsound.in);
} }
#endif
#ifdef CONFIG_AUDIO_OSS
/* OSS */ /* OSS */
static void handle_oss_per_direction( static void handle_oss_per_direction(
AudiodevOssPerDirectionOptions *opdo, const char *try_poll_env, AudiodevOssPerDirectionOptions *opdo, const char *try_poll_env,
@ -253,7 +275,9 @@ static void handle_oss(Audiodev *dev)
get_bool("QEMU_OSS_EXCLUSIVE", &oopt->exclusive, &oopt->has_exclusive); get_bool("QEMU_OSS_EXCLUSIVE", &oopt->exclusive, &oopt->has_exclusive);
get_int("QEMU_OSS_POLICY", &oopt->dsp_policy, &oopt->has_dsp_policy); get_int("QEMU_OSS_POLICY", &oopt->dsp_policy, &oopt->has_dsp_policy);
} }
#endif
#ifdef CONFIG_AUDIO_PA
/* pulseaudio */ /* pulseaudio */
static void handle_pa_per_direction( static void handle_pa_per_direction(
AudiodevPaPerDirectionOptions *ppdo, const char *env) AudiodevPaPerDirectionOptions *ppdo, const char *env)
@ -277,7 +301,9 @@ static void handle_pa(Audiodev *dev)
get_str("QEMU_PA_SERVER", &dev->u.pa.server); get_str("QEMU_PA_SERVER", &dev->u.pa.server);
} }
#endif
#ifdef CONFIG_AUDIO_SDL
/* SDL */ /* SDL */
static void handle_sdl(Audiodev *dev) static void handle_sdl(Audiodev *dev)
{ {
@ -286,6 +312,7 @@ static void handle_sdl(Audiodev *dev)
&dev->u.sdl.out->has_buffer_length, &dev->u.sdl.out->has_buffer_length,
qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.out)); qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.out));
} }
#endif
/* wav */ /* wav */
static void handle_wav(Audiodev *dev) static void handle_wav(Audiodev *dev)
@ -345,29 +372,41 @@ static AudiodevListEntry *legacy_opt(const char *drvname)
} }
switch (e->dev->driver) { switch (e->dev->driver) {
#ifdef CONFIG_AUDIO_ALSA
case AUDIODEV_DRIVER_ALSA: case AUDIODEV_DRIVER_ALSA:
handle_alsa(e->dev); handle_alsa(e->dev);
break; break;
#endif
#ifdef CONFIG_AUDIO_COREAUDIO
case AUDIODEV_DRIVER_COREAUDIO: case AUDIODEV_DRIVER_COREAUDIO:
handle_coreaudio(e->dev); handle_coreaudio(e->dev);
break; break;
#endif
#ifdef CONFIG_AUDIO_DSOUND
case AUDIODEV_DRIVER_DSOUND: case AUDIODEV_DRIVER_DSOUND:
handle_dsound(e->dev); handle_dsound(e->dev);
break; break;
#endif
#ifdef CONFIG_AUDIO_OSS
case AUDIODEV_DRIVER_OSS: case AUDIODEV_DRIVER_OSS:
handle_oss(e->dev); handle_oss(e->dev);
break; break;
#endif
#ifdef CONFIG_AUDIO_PA
case AUDIODEV_DRIVER_PA: case AUDIODEV_DRIVER_PA:
handle_pa(e->dev); handle_pa(e->dev);
break; break;
#endif
#ifdef CONFIG_AUDIO_SDL
case AUDIODEV_DRIVER_SDL: case AUDIODEV_DRIVER_SDL:
handle_sdl(e->dev); handle_sdl(e->dev);
break; break;
#endif
case AUDIODEV_DRIVER_WAV: case AUDIODEV_DRIVER_WAV:
handle_wav(e->dev); handle_wav(e->dev);

View File

@ -326,27 +326,47 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
switch (dev->driver) { switch (dev->driver) {
case AUDIODEV_DRIVER_NONE: case AUDIODEV_DRIVER_NONE:
return dev->u.none.TYPE; return dev->u.none.TYPE;
#ifdef CONFIG_AUDIO_ALSA
case AUDIODEV_DRIVER_ALSA: case AUDIODEV_DRIVER_ALSA:
return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.TYPE); return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.TYPE);
#endif
#ifdef CONFIG_AUDIO_COREAUDIO
case AUDIODEV_DRIVER_COREAUDIO: case AUDIODEV_DRIVER_COREAUDIO:
return qapi_AudiodevCoreaudioPerDirectionOptions_base( return qapi_AudiodevCoreaudioPerDirectionOptions_base(
dev->u.coreaudio.TYPE); dev->u.coreaudio.TYPE);
#endif
#ifdef CONFIG_DBUS_DISPLAY
case AUDIODEV_DRIVER_DBUS: case AUDIODEV_DRIVER_DBUS:
return dev->u.dbus.TYPE; return dev->u.dbus.TYPE;
#endif
#ifdef CONFIG_AUDIO_DSOUND
case AUDIODEV_DRIVER_DSOUND: case AUDIODEV_DRIVER_DSOUND:
return dev->u.dsound.TYPE; return dev->u.dsound.TYPE;
#endif
#ifdef CONFIG_AUDIO_JACK
case AUDIODEV_DRIVER_JACK: case AUDIODEV_DRIVER_JACK:
return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE); return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE);
#endif
#ifdef CONFIG_AUDIO_OSS
case AUDIODEV_DRIVER_OSS: case AUDIODEV_DRIVER_OSS:
return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE); return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
#endif
#ifdef CONFIG_AUDIO_PA
case AUDIODEV_DRIVER_PA: case AUDIODEV_DRIVER_PA:
return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE); return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE);
#endif
#ifdef CONFIG_AUDIO_SDL
case AUDIODEV_DRIVER_SDL: case AUDIODEV_DRIVER_SDL:
return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.TYPE); return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.TYPE);
#endif
#ifdef CONFIG_AUDIO_SNDIO
case AUDIODEV_DRIVER_SNDIO: case AUDIODEV_DRIVER_SNDIO:
return dev->u.sndio.TYPE; return dev->u.sndio.TYPE;
#endif
#ifdef CONFIG_SPICE
case AUDIODEV_DRIVER_SPICE: case AUDIODEV_DRIVER_SPICE:
return dev->u.spice.TYPE; return dev->u.spice.TYPE;
#endif
case AUDIODEV_DRIVER_WAV: case AUDIODEV_DRIVER_WAV:
return dev->u.wav.TYPE; return dev->u.wav.TYPE;

View File

@ -408,8 +408,18 @@
# Since: 4.0 # Since: 4.0
## ##
{ 'enum': 'AudiodevDriver', { 'enum': 'AudiodevDriver',
'data': [ 'none', 'alsa', 'coreaudio', 'dbus', 'dsound', 'jack', 'oss', 'pa', 'data': [ 'none',
'sdl', 'sndio', 'spice', 'wav' ] } { 'name': 'alsa', 'if': 'CONFIG_AUDIO_ALSA' },
{ 'name': 'coreaudio', 'if': 'CONFIG_AUDIO_COREAUDIO' },
{ 'name': 'dbus', 'if': 'CONFIG_DBUS_DISPLAY' },
{ 'name': 'dsound', 'if': 'CONFIG_AUDIO_DSOUND' },
{ 'name': 'jack', 'if': 'CONFIG_AUDIO_JACK' },
{ 'name': 'oss', 'if': 'CONFIG_AUDIO_OSS' },
{ 'name': 'pa', 'if': 'CONFIG_AUDIO_PA' },
{ 'name': 'sdl', 'if': 'CONFIG_AUDIO_SDL' },
{ 'name': 'sndio', 'if': 'CONFIG_AUDIO_SNDIO' },
{ 'name': 'spice', 'if': 'CONFIG_SPICE' },
'wav' ] }
## ##
# @Audiodev: # @Audiodev:
@ -432,16 +442,26 @@
'discriminator': 'driver', 'discriminator': 'driver',
'data': { 'data': {
'none': 'AudiodevGenericOptions', 'none': 'AudiodevGenericOptions',
'alsa': 'AudiodevAlsaOptions', 'alsa': { 'type': 'AudiodevAlsaOptions',
'coreaudio': 'AudiodevCoreaudioOptions', 'if': 'CONFIG_AUDIO_ALSA' },
'dbus': 'AudiodevGenericOptions', 'coreaudio': { 'type': 'AudiodevCoreaudioOptions',
'dsound': 'AudiodevDsoundOptions', 'if': 'CONFIG_AUDIO_COREAUDIO' },
'jack': 'AudiodevJackOptions', 'dbus': { 'type': 'AudiodevGenericOptions',
'oss': 'AudiodevOssOptions', 'if': 'CONFIG_DBUS_DISPLAY' },
'pa': 'AudiodevPaOptions', 'dsound': { 'type': 'AudiodevDsoundOptions',
'sdl': 'AudiodevSdlOptions', 'if': 'CONFIG_AUDIO_DSOUND' },
'sndio': 'AudiodevSndioOptions', 'jack': { 'type': 'AudiodevJackOptions',
'spice': 'AudiodevGenericOptions', 'if': 'CONFIG_AUDIO_JACK' },
'oss': { 'type': 'AudiodevOssOptions',
'if': 'CONFIG_AUDIO_OSS' },
'pa': { 'type': 'AudiodevPaOptions',
'if': 'CONFIG_AUDIO_PA' },
'sdl': { 'type': 'AudiodevSdlOptions',
'if': 'CONFIG_AUDIO_SDL' },
'sndio': { 'type': 'AudiodevSndioOptions',
'if': 'CONFIG_AUDIO_SNDIO' },
'spice': { 'type': 'AudiodevGenericOptions',
'if': 'CONFIG_SPICE' },
'wav': 'AudiodevWavOptions' } } 'wav': 'AudiodevWavOptions' } }
## ##