audio: allow returning an error from the driver init
An error is already printed by audio_driver_init, but we can make it more precise if the driver can return an Error *. Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
aaa6a6f93d
commit
f6061733a9
@ -904,7 +904,7 @@ static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *alsa_audio_init(Audiodev *dev)
|
static void *alsa_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
AudiodevAlsaOptions *aopts;
|
AudiodevAlsaOptions *aopts;
|
||||||
assert(dev->driver == AUDIODEV_DRIVER_ALSA);
|
assert(dev->driver == AUDIODEV_DRIVER_ALSA);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "qapi/qapi-visit-audio.h"
|
#include "qapi/qapi-visit-audio.h"
|
||||||
#include "qapi/qapi-commands-audio.h"
|
#include "qapi/qapi-commands-audio.h"
|
||||||
#include "qemu/cutils.h"
|
#include "qemu/cutils.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/help_option.h"
|
#include "qemu/help_option.h"
|
||||||
@ -1555,7 +1556,9 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
|
|||||||
static int audio_driver_init(AudioState *s, struct audio_driver *drv,
|
static int audio_driver_init(AudioState *s, struct audio_driver *drv,
|
||||||
bool msg, Audiodev *dev)
|
bool msg, Audiodev *dev)
|
||||||
{
|
{
|
||||||
s->drv_opaque = drv->init(dev);
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
s->drv_opaque = drv->init(dev, &local_err);
|
||||||
|
|
||||||
if (s->drv_opaque) {
|
if (s->drv_opaque) {
|
||||||
if (!drv->pcm_ops->get_buffer_in) {
|
if (!drv->pcm_ops->get_buffer_in) {
|
||||||
@ -1572,8 +1575,12 @@ static int audio_driver_init(AudioState *s, struct audio_driver *drv,
|
|||||||
s->drv = drv;
|
s->drv = drv;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
if (msg) {
|
if (!msg) {
|
||||||
dolog("Could not init `%s' audio driver\n", drv->name);
|
error_free(local_err);
|
||||||
|
} else if (local_err) {
|
||||||
|
error_report_err(local_err);
|
||||||
|
} else {
|
||||||
|
error_report("Could not init `%s' audio driver", drv->name);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ typedef struct audio_driver audio_driver;
|
|||||||
struct audio_driver {
|
struct audio_driver {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *descr;
|
const char *descr;
|
||||||
void *(*init) (Audiodev *);
|
void *(*init) (Audiodev *, Error **);
|
||||||
void (*fini) (void *);
|
void (*fini) (void *);
|
||||||
#ifdef CONFIG_GIO
|
#ifdef CONFIG_GIO
|
||||||
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p);
|
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p);
|
||||||
|
@ -644,7 +644,7 @@ static void coreaudio_enable_out(HWVoiceOut *hw, bool enable)
|
|||||||
update_device_playback_state(core);
|
update_device_playback_state(core);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *coreaudio_audio_init(Audiodev *dev)
|
static void *coreaudio_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,7 @@ dbus_enable_in(HWVoiceIn *hw, bool enable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
dbus_audio_init(Audiodev *dev)
|
dbus_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
DBusAudio *da = g_new0(DBusAudio, 1);
|
DBusAudio *da = g_new0(DBusAudio, 1);
|
||||||
|
|
||||||
|
@ -619,7 +619,7 @@ static void dsound_audio_fini (void *opaque)
|
|||||||
g_free(s);
|
g_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *dsound_audio_init(Audiodev *dev)
|
static void *dsound_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -645,7 +645,7 @@ static int qjack_thread_creator(jack_native_thread_t *thread,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void *qjack_init(Audiodev *dev)
|
static void *qjack_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
assert(dev->driver == AUDIODEV_DRIVER_JACK);
|
assert(dev->driver == AUDIODEV_DRIVER_JACK);
|
||||||
return dev;
|
return dev;
|
||||||
|
@ -104,7 +104,7 @@ static void no_enable_in(HWVoiceIn *hw, bool enable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *no_audio_init(Audiodev *dev)
|
static void *no_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
return &no_audio_init;
|
return &no_audio_init;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
@ -736,7 +737,7 @@ static void oss_init_per_direction(AudiodevOssPerDirectionOptions *opdo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *oss_audio_init(Audiodev *dev)
|
static void *oss_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
AudiodevOssOptions *oopts;
|
AudiodevOssOptions *oopts;
|
||||||
assert(dev->driver == AUDIODEV_DRIVER_OSS);
|
assert(dev->driver == AUDIODEV_DRIVER_OSS);
|
||||||
@ -745,8 +746,12 @@ static void *oss_audio_init(Audiodev *dev)
|
|||||||
oss_init_per_direction(oopts->in);
|
oss_init_per_direction(oopts->in);
|
||||||
oss_init_per_direction(oopts->out);
|
oss_init_per_direction(oopts->out);
|
||||||
|
|
||||||
if (access(oopts->in->dev ?: "/dev/dsp", R_OK | W_OK) < 0 ||
|
if (access(oopts->in->dev ?: "/dev/dsp", R_OK | W_OK) < 0) {
|
||||||
access(oopts->out->dev ?: "/dev/dsp", R_OK | W_OK) < 0) {
|
error_setg_errno(errp, errno, "%s not accessible", oopts->in->dev ?: "/dev/dsp");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (access(oopts->out->dev ?: "/dev/dsp", R_OK | W_OK) < 0) {
|
||||||
|
error_setg_errno(errp, errno, "%s not accessible", oopts->out->dev ?: "/dev/dsp");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return dev;
|
return dev;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "qapi/opts-visitor.h"
|
#include "qapi/error.h"
|
||||||
|
|
||||||
#include <pulse/pulseaudio.h>
|
#include <pulse/pulseaudio.h>
|
||||||
|
|
||||||
@ -818,7 +818,7 @@ fail:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *qpa_audio_init(Audiodev *dev)
|
static void *qpa_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
paaudio *g;
|
paaudio *g;
|
||||||
AudiodevPaOptions *popts = &dev->u.pa;
|
AudiodevPaOptions *popts = &dev->u.pa;
|
||||||
@ -834,10 +834,12 @@ static void *qpa_audio_init(Audiodev *dev)
|
|||||||
|
|
||||||
runtime = getenv("XDG_RUNTIME_DIR");
|
runtime = getenv("XDG_RUNTIME_DIR");
|
||||||
if (!runtime) {
|
if (!runtime) {
|
||||||
|
error_setg(errp, "XDG_RUNTIME_DIR not set");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime);
|
snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime);
|
||||||
if (stat(pidfile, &st) != 0) {
|
if (stat(pidfile, &st) != 0) {
|
||||||
|
error_setg_errno(errp, errno, "could not stat pidfile %s", pidfile);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -867,6 +869,7 @@ static void *qpa_audio_init(Audiodev *dev)
|
|||||||
}
|
}
|
||||||
if (!g->conn) {
|
if (!g->conn) {
|
||||||
g_free(g);
|
g_free(g);
|
||||||
|
error_setg(errp, "could not connect to PulseAudio server");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
#include <spa/param/audio/format-utils.h>
|
#include <spa/param/audio/format-utils.h>
|
||||||
#include <spa/utils/ringbuffer.h>
|
#include <spa/utils/ringbuffer.h>
|
||||||
#include <spa/utils/result.h>
|
#include <spa/utils/result.h>
|
||||||
@ -736,7 +737,7 @@ static const struct pw_core_events core_events = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
qpw_audio_init(Audiodev *dev)
|
qpw_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
g_autofree pwaudio *pw = g_new0(pwaudio, 1);
|
g_autofree pwaudio *pw = g_new0(pwaudio, 1);
|
||||||
|
|
||||||
@ -748,19 +749,19 @@ qpw_audio_init(Audiodev *dev)
|
|||||||
pw->dev = dev;
|
pw->dev = dev;
|
||||||
pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL);
|
pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL);
|
||||||
if (pw->thread_loop == NULL) {
|
if (pw->thread_loop == NULL) {
|
||||||
error_report("Could not create PipeWire loop: %s", g_strerror(errno));
|
error_setg_errno(errp, errno, "Could not create PipeWire loop");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pw->context =
|
pw->context =
|
||||||
pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0);
|
pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0);
|
||||||
if (pw->context == NULL) {
|
if (pw->context == NULL) {
|
||||||
error_report("Could not create PipeWire context: %s", g_strerror(errno));
|
error_setg_errno(errp, errno, "Could not create PipeWire context");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pw_thread_loop_start(pw->thread_loop) < 0) {
|
if (pw_thread_loop_start(pw->thread_loop) < 0) {
|
||||||
error_report("Could not start PipeWire loop: %s", g_strerror(errno));
|
error_setg_errno(errp, errno, "Could not start PipeWire loop");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,13 +770,13 @@ qpw_audio_init(Audiodev *dev)
|
|||||||
pw->core = pw_context_connect(pw->context, NULL, 0);
|
pw->core = pw_context_connect(pw->context, NULL, 0);
|
||||||
if (pw->core == NULL) {
|
if (pw->core == NULL) {
|
||||||
pw_thread_loop_unlock(pw->thread_loop);
|
pw_thread_loop_unlock(pw->thread_loop);
|
||||||
goto fail;
|
goto fail_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pw_core_add_listener(pw->core, &pw->core_listener,
|
if (pw_core_add_listener(pw->core, &pw->core_listener,
|
||||||
&core_events, pw) < 0) {
|
&core_events, pw) < 0) {
|
||||||
pw_thread_loop_unlock(pw->thread_loop);
|
pw_thread_loop_unlock(pw->thread_loop);
|
||||||
goto fail;
|
goto fail_error;
|
||||||
}
|
}
|
||||||
if (wait_resync(pw) < 0) {
|
if (wait_resync(pw) < 0) {
|
||||||
pw_thread_loop_unlock(pw->thread_loop);
|
pw_thread_loop_unlock(pw->thread_loop);
|
||||||
@ -785,8 +786,9 @@ qpw_audio_init(Audiodev *dev)
|
|||||||
|
|
||||||
return g_steal_pointer(&pw);
|
return g_steal_pointer(&pw);
|
||||||
|
|
||||||
|
fail_error:
|
||||||
|
error_setg(errp, "Failed to initialize PW context");
|
||||||
fail:
|
fail:
|
||||||
AUD_log(AUDIO_CAP, "Failed to initialize PW context");
|
|
||||||
if (pw->thread_loop) {
|
if (pw->thread_loop) {
|
||||||
pw_thread_loop_stop(pw->thread_loop);
|
pw_thread_loop_stop(pw->thread_loop);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL_thread.h>
|
#include <SDL_thread.h>
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@ -449,10 +450,10 @@ static void sdl_enable_in(HWVoiceIn *hw, bool enable)
|
|||||||
SDL_PauseAudioDevice(sdl->devid, !enable);
|
SDL_PauseAudioDevice(sdl->devid, !enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *sdl_audio_init(Audiodev *dev)
|
static void *sdl_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
|
if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
|
||||||
sdl_logerr ("SDL failed to initialize audio subsystem\n");
|
error_setg(errp, "SDL failed to initialize audio subsystem");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ static void sndio_fini_in(HWVoiceIn *hw)
|
|||||||
sndio_fini(self);
|
sndio_fini(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *sndio_audio_init(Audiodev *dev)
|
static void *sndio_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
assert(dev->driver == AUDIODEV_DRIVER_SNDIO);
|
assert(dev->driver == AUDIODEV_DRIVER_SNDIO);
|
||||||
return dev;
|
return dev;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
#include "ui/qemu-spice.h"
|
#include "ui/qemu-spice.h"
|
||||||
|
|
||||||
#define AUDIO_CAP "spice"
|
#define AUDIO_CAP "spice"
|
||||||
@ -71,11 +72,13 @@ static const SpiceRecordInterface record_sif = {
|
|||||||
.base.minor_version = SPICE_INTERFACE_RECORD_MINOR,
|
.base.minor_version = SPICE_INTERFACE_RECORD_MINOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *spice_audio_init(Audiodev *dev)
|
static void *spice_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
if (!using_spice) {
|
if (!using_spice) {
|
||||||
|
error_setg(errp, "Cannot use spice audio without -spice");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &spice_audio_init;
|
return &spice_audio_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ static void wav_enable_out(HWVoiceOut *hw, bool enable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *wav_audio_init(Audiodev *dev)
|
static void *wav_audio_init(Audiodev *dev, Error **errp)
|
||||||
{
|
{
|
||||||
assert(dev->driver == AUDIODEV_DRIVER_WAV);
|
assert(dev->driver == AUDIODEV_DRIVER_WAV);
|
||||||
return dev;
|
return dev;
|
||||||
|
Loading…
Reference in New Issue
Block a user