From 4e2fb3fb89b8b80d5366466f391f21386120019e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 20 Oct 2009 22:10:56 +0200 Subject: mixer_plugin: use GError for error handling --- src/mixer/alsa_mixer_plugin.c | 55 +++++++++++++++++++++++++-------------- src/mixer/oss_mixer_plugin.c | 42 +++++++++++++++++++++--------- src/mixer/pulse_mixer_plugin.c | 47 ++++++++++++++++++++++++--------- src/mixer/software_mixer_plugin.c | 10 ++++--- src/mixer_all.c | 26 +++++++++++++++--- src/mixer_control.c | 25 +++++++++--------- src/mixer_control.h | 11 +++++--- src/mixer_plugin.h | 26 ++++++++++++++---- src/output_control.c | 11 ++++++-- src/output_init.c | 15 ++++++++--- test/read_mixer.c | 20 +++++++++----- 11 files changed, 203 insertions(+), 85 deletions(-) diff --git a/src/mixer/alsa_mixer_plugin.c b/src/mixer/alsa_mixer_plugin.c index 1a32ea9e1..0f23bc03f 100644 --- a/src/mixer/alsa_mixer_plugin.c +++ b/src/mixer/alsa_mixer_plugin.c @@ -42,8 +42,18 @@ struct alsa_mixer { int volume_set; }; +/** + * The quark used for GError.domain. + */ +static inline GQuark +alsa_mixer_quark(void) +{ + return g_quark_from_static_string("alsa_mixer"); +} + static struct mixer * -alsa_mixer_init(const struct config_param *param) +alsa_mixer_init(const struct config_param *param, + G_GNUC_UNUSED GError **error_r) { struct alsa_mixer *am = g_new(struct alsa_mixer, 1); @@ -81,7 +91,7 @@ alsa_mixer_close(struct mixer *data) } static bool -alsa_mixer_open(struct mixer *data) +alsa_mixer_open(struct mixer *data, GError **error_r) { struct alsa_mixer *am = (struct alsa_mixer *)data; int err; @@ -91,29 +101,33 @@ alsa_mixer_open(struct mixer *data) err = snd_mixer_open(&am->handle, 0); if (err < 0) { - g_warning("problems opening alsa mixer: %s\n", snd_strerror(err)); + g_set_error(error_r, alsa_mixer_quark(), err, + "snd_mixer_open() failed: %s", snd_strerror(err)); return false; } if ((err = snd_mixer_attach(am->handle, am->device)) < 0) { - g_warning("problems attaching alsa mixer: %s\n", - snd_strerror(err)); alsa_mixer_close(data); + g_set_error(error_r, alsa_mixer_quark(), err, + "failed to attach to %s: %s", + am->device, snd_strerror(err)); return false; } if ((err = snd_mixer_selem_register(am->handle, NULL, NULL)) < 0) { - g_warning("problems snd_mixer_selem_register'ing: %s\n", - snd_strerror(err)); alsa_mixer_close(data); + g_set_error(error_r, alsa_mixer_quark(), err, + "snd_mixer_selem_register() failed: %s", + snd_strerror(err)); return false; } if ((err = snd_mixer_load(am->handle)) < 0) { - g_warning("problems snd_mixer_selem_register'ing: %s\n", - snd_strerror(err)); alsa_mixer_close(data); + g_set_error(error_r, alsa_mixer_quark(), err, + "snd_mixer_load() failed: %s\n", + snd_strerror(err)); return false; } @@ -138,14 +152,14 @@ alsa_mixer_open(struct mixer *data) return true; } - g_warning("can't find alsa mixer control \"%s\"\n", am->control); - alsa_mixer_close(data); + g_set_error(error_r, alsa_mixer_quark(), 0, + "no such mixer control: %s", am->control); return false; } static int -alsa_mixer_get_volume(struct mixer *mixer) +alsa_mixer_get_volume(struct mixer *mixer, GError **error_r) { struct alsa_mixer *am = (struct alsa_mixer *)mixer; int err; @@ -156,8 +170,9 @@ alsa_mixer_get_volume(struct mixer *mixer) err = snd_mixer_handle_events(am->handle); if (err < 0) { - g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n", - snd_strerror(err), "handle_events"); + g_set_error(error_r, alsa_mixer_quark(), err, + "snd_mixer_handle_events() failed: %s", + snd_strerror(err)); return false; } @@ -165,8 +180,9 @@ alsa_mixer_get_volume(struct mixer *mixer) SND_MIXER_SCHN_FRONT_LEFT, &level); if (err < 0) { - g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n", - snd_strerror(err), "selem_get_playback_volume"); + g_set_error(error_r, alsa_mixer_quark(), err, + "failed to read ALSA volume: %s", + snd_strerror(err)); return false; } @@ -183,7 +199,7 @@ alsa_mixer_get_volume(struct mixer *mixer) } static bool -alsa_mixer_set_volume(struct mixer *mixer, unsigned volume) +alsa_mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r) { struct alsa_mixer *am = (struct alsa_mixer *)mixer; float vol; @@ -203,8 +219,9 @@ alsa_mixer_set_volume(struct mixer *mixer, unsigned volume) err = snd_mixer_selem_set_playback_volume_all(am->elem, level); if (err < 0) { - g_warning("problems setting alsa volume: %s\n", - snd_strerror(err)); + g_set_error(error_r, alsa_mixer_quark(), err, + "failed to set ALSA volume: %s", + snd_strerror(err)); return false; } diff --git a/src/mixer/oss_mixer_plugin.c b/src/mixer/oss_mixer_plugin.c index fb0fd787e..3b97e38f5 100644 --- a/src/mixer/oss_mixer_plugin.c +++ b/src/mixer/oss_mixer_plugin.c @@ -49,6 +49,15 @@ struct oss_mixer { int volume_control; }; +/** + * The quark used for GError.domain. + */ +static inline GQuark +oss_mixer_quark(void) +{ + return g_quark_from_static_string("oss_mixer"); +} + static int oss_find_mixer(const char *name) { @@ -65,7 +74,7 @@ oss_find_mixer(const char *name) } static struct mixer * -oss_mixer_init(const struct config_param *param) +oss_mixer_init(const struct config_param *param, GError **error_r) { struct oss_mixer *om = g_new(struct oss_mixer, 1); @@ -78,9 +87,9 @@ oss_mixer_init(const struct config_param *param) if (om->control != NULL) { om->volume_control = oss_find_mixer(om->control); if (om->volume_control < 0) { - g_warning("mixer control \"%s\" not found", - om->control); g_free(om); + g_set_error(error_r, oss_mixer_quark(), 0, + "no such mixer control: %s", om->control); return NULL; } } else @@ -108,13 +117,15 @@ oss_mixer_close(struct mixer *data) } static bool -oss_mixer_open(struct mixer *data) +oss_mixer_open(struct mixer *data, GError **error_r) { struct oss_mixer *om = (struct oss_mixer *) data; om->device_fd = open(om->device, O_RDONLY); if (om->device_fd < 0) { - g_warning("Unable to open oss mixer \"%s\"\n", om->device); + g_set_error(error_r, oss_mixer_quark(), errno, + "failed to open %s: %s", + om->device, g_strerror(errno)); return false; } @@ -122,14 +133,17 @@ oss_mixer_open(struct mixer *data) int devmask = 0; if (ioctl(om->device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { - g_warning("errors getting read_devmask for oss mixer\n"); + g_set_error(error_r, oss_mixer_quark(), errno, + "READ_DEVMASK failed: %s", + g_strerror(errno)); oss_mixer_close(data); return false; } if (((1 << om->volume_control) & devmask) == 0) { - g_warning("mixer control \"%s\" not usable\n", - om->control); + g_set_error(error_r, oss_mixer_quark(), 0, + "mixer control \"%s\" not usable", + om->control); oss_mixer_close(data); return false; } @@ -138,7 +152,7 @@ oss_mixer_open(struct mixer *data) } static int -oss_mixer_get_volume(struct mixer *mixer) +oss_mixer_get_volume(struct mixer *mixer, GError **error_r) { struct oss_mixer *om = (struct oss_mixer *)mixer; int left, right, level; @@ -148,7 +162,9 @@ oss_mixer_get_volume(struct mixer *mixer) ret = ioctl(om->device_fd, MIXER_READ(om->volume_control), &level); if (ret < 0) { - g_warning("unable to read oss volume\n"); + g_set_error(error_r, oss_mixer_quark(), errno, + "failed to read OSS volume: %s", + g_strerror(errno)); return false; } @@ -164,7 +180,7 @@ oss_mixer_get_volume(struct mixer *mixer) } static bool -oss_mixer_set_volume(struct mixer *mixer, unsigned volume) +oss_mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r) { struct oss_mixer *om = (struct oss_mixer *)mixer; int level; @@ -177,7 +193,9 @@ oss_mixer_set_volume(struct mixer *mixer, unsigned volume) ret = ioctl(om->device_fd, MIXER_WRITE(om->volume_control), &level); if (ret < 0) { - g_warning("unable to set oss volume\n"); + g_set_error(error_r, oss_mixer_quark(), errno, + "failed to set OSS volume: %s", + g_strerror(errno)); return false; } diff --git a/src/mixer/pulse_mixer_plugin.c b/src/mixer/pulse_mixer_plugin.c index 54b082819..3399d5baa 100644 --- a/src/mixer/pulse_mixer_plugin.c +++ b/src/mixer/pulse_mixer_plugin.c @@ -45,6 +45,15 @@ struct pulse_mixer { }; +/** + * The quark used for GError.domain. + */ +static inline GQuark +pulse_mixer_quark(void) +{ + return g_quark_from_static_string("pulse_mixer"); +} + /** * \brief waits for a pulseaudio operation to finish, frees it and * unlocks the mainloop @@ -203,7 +212,8 @@ context_state_cb(pa_context *context, void *userdata) static struct mixer * -pulse_mixer_init(const struct config_param *param) +pulse_mixer_init(const struct config_param *param, + G_GNUC_UNUSED GError **error_r) { struct pulse_mixer *pm = g_new(struct pulse_mixer,1); mixer_init(&pm->base, &pulse_mixer_plugin); @@ -226,13 +236,14 @@ pulse_mixer_finish(struct mixer *data) } static bool -pulse_mixer_setup(struct pulse_mixer *pm) +pulse_mixer_setup(struct pulse_mixer *pm, GError **error_r) { pa_context_set_state_callback(pm->context, context_state_cb, pm); if (pa_context_connect(pm->context, pm->server, (pa_context_flags_t)0, NULL) < 0) { - g_debug("context server fail"); + g_set_error(error_r, pulse_mixer_quark(), 0, + "pa_context_connect() has failed"); return false; } @@ -240,15 +251,18 @@ pulse_mixer_setup(struct pulse_mixer *pm) if (pa_threaded_mainloop_start(pm->mainloop) < 0) { pa_threaded_mainloop_unlock(pm->mainloop); - g_debug("error start mainloop"); + g_set_error(error_r, pulse_mixer_quark(), 0, + "pa_threaded_mainloop_start() has failed"); return false; } pa_threaded_mainloop_wait(pm->mainloop); if (pa_context_get_state(pm->context) != PA_CONTEXT_READY) { + g_set_error(error_r, pulse_mixer_quark(), 0, + "failed to connect: %s", + pa_strerror(pa_context_errno(pm->context))); pa_threaded_mainloop_unlock(pm->mainloop); - g_debug("error context not ready"); return false; } @@ -258,7 +272,7 @@ pulse_mixer_setup(struct pulse_mixer *pm) } static bool -pulse_mixer_open(struct mixer *data) +pulse_mixer_open(struct mixer *data, GError **error_r) { struct pulse_mixer *pm = (struct pulse_mixer *) data; @@ -269,7 +283,8 @@ pulse_mixer_open(struct mixer *data) pm->mainloop = pa_threaded_mainloop_new(); if (pm->mainloop == NULL) { - g_debug("failed mainloop"); + g_set_error(error_r, pulse_mixer_quark(), 0, + "pa_threaded_mainloop_new() has failed"); return false; } @@ -278,11 +293,12 @@ pulse_mixer_open(struct mixer *data) if (pm->context == NULL) { pa_threaded_mainloop_stop(pm->mainloop); pa_threaded_mainloop_free(pm->mainloop); - g_debug("failed context"); + g_set_error(error_r, pulse_mixer_quark(), 0, + "pa_context_new() has failed"); return false; } - if (!pulse_mixer_setup(pm)) { + if (!pulse_mixer_setup(pm, error_r)) { pa_threaded_mainloop_stop(pm->mainloop); pa_context_disconnect(pm->context); pa_context_unref(pm->context); @@ -307,7 +323,7 @@ pulse_mixer_close(struct mixer *data) } static int -pulse_mixer_get_volume(struct mixer *mixer) +pulse_mixer_get_volume(struct mixer *mixer, GError **error_r) { struct pulse_mixer *pm = (struct pulse_mixer *) mixer; int ret; @@ -324,12 +340,15 @@ pulse_mixer_get_volume(struct mixer *mixer) sink_input_vol, pm); if (o == NULL) { pa_threaded_mainloop_unlock(pm->mainloop); - g_debug("pa_context_get_sink_input_info() failed"); + g_set_error(error_r, pulse_mixer_quark(), 0, + "pa_context_get_sink_input_info() has failed"); return false; } if (!pulse_wait_for_operation(pm->mainloop, o)) { pa_threaded_mainloop_unlock(pm->mainloop); + g_set_error(error_r, pulse_mixer_quark(), 0, + "failed to read PulseAudio volume"); return false; } @@ -343,7 +362,7 @@ pulse_mixer_get_volume(struct mixer *mixer) } static bool -pulse_mixer_set_volume(struct mixer *mixer, unsigned volume) +pulse_mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r) { struct pulse_mixer *pm = (struct pulse_mixer *) mixer; struct pa_cvolume cvolume; @@ -353,6 +372,7 @@ pulse_mixer_set_volume(struct mixer *mixer, unsigned volume) if (!pm->online) { pa_threaded_mainloop_unlock(pm->mainloop); + g_set_error(error_r, pulse_mixer_quark(), 0, "disconnected"); return false; } @@ -363,7 +383,8 @@ pulse_mixer_set_volume(struct mixer *mixer, unsigned volume) &cvolume, NULL, NULL); pa_threaded_mainloop_unlock(pm->mainloop); if (o == NULL) { - g_debug("pa_context_set_sink_input_volume() failed"); + g_set_error(error_r, pulse_mixer_quark(), 0, + "failed to set PulseAudio volume"); return false; } diff --git a/src/mixer/software_mixer_plugin.c b/src/mixer/software_mixer_plugin.c index 661334e1b..e81d265cb 100644 --- a/src/mixer/software_mixer_plugin.c +++ b/src/mixer/software_mixer_plugin.c @@ -37,7 +37,8 @@ struct software_mixer { }; static struct mixer * -software_mixer_init(G_GNUC_UNUSED const struct config_param *param) +software_mixer_init(G_GNUC_UNUSED const struct config_param *param, + G_GNUC_UNUSED GError **error_r) { struct software_mixer *sm = g_new(struct software_mixer, 1); @@ -60,7 +61,7 @@ software_mixer_finish(struct mixer *data) } static bool -software_mixer_open(struct mixer *data) +software_mixer_open(struct mixer *data, G_GNUC_UNUSED GError **error_r) { struct software_mixer *sm = (struct software_mixer *)data; @@ -77,7 +78,7 @@ software_mixer_close(struct mixer *data) } static int -software_mixer_get_volume(struct mixer *mixer) +software_mixer_get_volume(struct mixer *mixer, G_GNUC_UNUSED GError **error_r) { struct software_mixer *sm = (struct software_mixer *)mixer; @@ -85,7 +86,8 @@ software_mixer_get_volume(struct mixer *mixer) } static bool -software_mixer_set_volume(struct mixer *mixer, unsigned volume) +software_mixer_set_volume(struct mixer *mixer, unsigned volume, + G_GNUC_UNUSED GError **error_r) { struct software_mixer *sm = (struct software_mixer *)mixer; diff --git a/src/mixer_all.c b/src/mixer_all.c index cd05eec85..b9c1afdad 100644 --- a/src/mixer_all.c +++ b/src/mixer_all.c @@ -38,6 +38,8 @@ output_mixer_get_volume(unsigned i) { struct audio_output *output; struct mixer *mixer; + int volume; + GError *error = NULL; assert(i < audio_output_count()); @@ -49,7 +51,14 @@ output_mixer_get_volume(unsigned i) if (mixer == NULL) return -1; - return mixer_get_volume(mixer); + volume = mixer_get_volume(mixer, &error); + if (volume < 0 && error != NULL) { + g_warning("Failed to read mixer for '%s': %s", + output->name, error->message); + g_error_free(error); + } + + return volume; } int @@ -77,6 +86,8 @@ output_mixer_set_volume(unsigned i, unsigned volume) { struct audio_output *output; struct mixer *mixer; + bool success; + GError *error = NULL; assert(i < audio_output_count()); assert(volume <= 100); @@ -89,7 +100,14 @@ output_mixer_set_volume(unsigned i, unsigned volume) if (mixer == NULL) return false; - return mixer_set_volume(mixer, volume); + success = mixer_set_volume(mixer, volume, &error); + if (!success && error != NULL) { + g_warning("Failed to set mixer for '%s': %s", + output->name, error->message); + g_error_free(error); + } + + return success; } bool @@ -123,7 +141,7 @@ output_mixer_get_software_volume(unsigned i) if (mixer == NULL || mixer->plugin != &software_mixer_plugin) return -1; - return mixer_get_volume(mixer); + return mixer_get_volume(mixer, NULL); } int @@ -157,6 +175,6 @@ mixer_all_set_software_volume(unsigned volume) struct audio_output *output = audio_output_get(i); if (output->mixer != NULL && output->mixer->plugin == &software_mixer_plugin) - mixer_set_volume(output->mixer, volume); + mixer_set_volume(output->mixer, volume, NULL); } } diff --git a/src/mixer_control.c b/src/mixer_control.c index 927a1276c..7ee9fabf0 100644 --- a/src/mixer_control.c +++ b/src/mixer_control.c @@ -20,8 +20,6 @@ #include "mixer_control.h" #include "mixer_api.h" -#include - #include #include @@ -29,13 +27,14 @@ #define G_LOG_DOMAIN "mixer" struct mixer * -mixer_new(const struct mixer_plugin *plugin, const struct config_param *param) +mixer_new(const struct mixer_plugin *plugin, const struct config_param *param, + GError **error_r) { struct mixer *mixer; assert(plugin != NULL); - mixer = plugin->init(param); + mixer = plugin->init(param, error_r); assert(mixer == NULL || mixer->plugin == plugin); @@ -55,7 +54,7 @@ mixer_free(struct mixer *mixer) } bool -mixer_open(struct mixer *mixer) +mixer_open(struct mixer *mixer, GError **error_r) { bool success; @@ -67,7 +66,7 @@ mixer_open(struct mixer *mixer) if (mixer->open) success = true; else - success = mixer->open = mixer->plugin->open(mixer); + success = mixer->open = mixer->plugin->open(mixer, error_r); mixer->failed = !success; @@ -123,19 +122,20 @@ mixer_failed(struct mixer *mixer) } int -mixer_get_volume(struct mixer *mixer) +mixer_get_volume(struct mixer *mixer, GError **error_r) { int volume; assert(mixer != NULL); - if (mixer->plugin->global && !mixer->failed && !mixer_open(mixer)) + if (mixer->plugin->global && !mixer->failed && + !mixer_open(mixer, error_r)) return -1; g_mutex_lock(mixer->mutex); if (mixer->open) { - volume = mixer->plugin->get_volume(mixer); + volume = mixer->plugin->get_volume(mixer, error_r); if (volume < 0) mixer_failed(mixer); } else @@ -147,20 +147,21 @@ mixer_get_volume(struct mixer *mixer) } bool -mixer_set_volume(struct mixer *mixer, unsigned volume) +mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r) { bool success; assert(mixer != NULL); assert(volume <= 100); - if (mixer->plugin->global && !mixer->failed && !mixer_open(mixer)) + if (mixer->plugin->global && !mixer->failed && + !mixer_open(mixer, error_r)) return false; g_mutex_lock(mixer->mutex); if (mixer->open) { - success = mixer->plugin->set_volume(mixer, volume); + success = mixer->plugin->set_volume(mixer, volume, error_r); if (!success) mixer_failed(mixer); } else diff --git a/src/mixer_control.h b/src/mixer_control.h index b8997a795..f023317e3 100644 --- a/src/mixer_control.h +++ b/src/mixer_control.h @@ -25,6 +25,8 @@ #ifndef MPD_MIXER_CONTROL_H #define MPD_MIXER_CONTROL_H +#include + #include struct mixer; @@ -32,13 +34,14 @@ struct mixer_plugin; struct config_param; struct mixer * -mixer_new(const struct mixer_plugin *plugin, const struct config_param *param); +mixer_new(const struct mixer_plugin *plugin, const struct config_param *param, + GError **error_r); void mixer_free(struct mixer *mixer); bool -mixer_open(struct mixer *mixer); +mixer_open(struct mixer *mixer, GError **error_r); void mixer_close(struct mixer *mixer); @@ -51,9 +54,9 @@ void mixer_auto_close(struct mixer *mixer); int -mixer_get_volume(struct mixer *mixer); +mixer_get_volume(struct mixer *mixer, GError **error_r); bool -mixer_set_volume(struct mixer *mixer, unsigned volume); +mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r); #endif diff --git a/src/mixer_plugin.h b/src/mixer_plugin.h index 2b9b440e5..f3f70e2ef 100644 --- a/src/mixer_plugin.h +++ b/src/mixer_plugin.h @@ -27,6 +27,8 @@ #ifndef MPD_MIXER_PLUGIN_H #define MPD_MIXER_PLUGIN_H +#include + #include struct config_param; @@ -35,8 +37,13 @@ struct mixer; struct mixer_plugin { /** * Alocates and configures a mixer device. + * + * @param error_r location to store the error occuring, or + * NULL to ignore errors + * @return a mixer object, or NULL on error */ - struct mixer *(*init)(const struct config_param *param); + struct mixer *(*init)(const struct config_param *param, + GError **error_r); /** * Finish and free mixer data @@ -45,8 +52,12 @@ struct mixer_plugin { /** * Open mixer device + * + * @param error_r location to store the error occuring, or + * NULL to ignore errors + * @return true on success, false on error */ - bool (*open)(struct mixer *data); + bool (*open)(struct mixer *data, GError **error_r); /** * Close mixer device @@ -56,18 +67,23 @@ struct mixer_plugin { /** * Reads the current volume. * + * @param error_r location to store the error occuring, or + * NULL to ignore errors * @return the current volume (0..100 including) or -1 on * error */ - int (*get_volume)(struct mixer *mixer); + int (*get_volume)(struct mixer *mixer, GError **error_r); /** * Sets the volume. * + * @param error_r location to store the error occuring, or + * NULL to ignore errors * @param volume the new volume (0..100 including) - * @return true on success + * @return true on success, false on error */ - bool (*set_volume)(struct mixer *mixer, unsigned volume); + bool (*set_volume)(struct mixer *mixer, unsigned volume, + GError **error_r); /** * If true, then the mixer is automatically opened, even if diff --git a/src/output_control.c b/src/output_control.c index ef77bf4fa..b833fb08d 100644 --- a/src/output_control.c +++ b/src/output_control.c @@ -102,8 +102,15 @@ audio_output_open(struct audio_output *ao, ao_command(ao, ao->open ? AO_COMMAND_REOPEN : AO_COMMAND_OPEN); open = ao->open; - if (open && ao->mixer != NULL) - mixer_open(ao->mixer); + if (open && ao->mixer != NULL) { + GError *error = NULL; + + if (!mixer_open(ao->mixer, &error)) { + g_warning("Failed to open mixer for '%s': %s", + ao->name, error->message); + g_error_free(error); + } + } return open; } diff --git a/src/output_init.c b/src/output_init.c index b139ec0fd..a628a2499 100644 --- a/src/output_init.c +++ b/src/output_init.c @@ -91,7 +91,8 @@ audio_output_mixer_type(const struct config_param *param) static struct mixer * audio_output_load_mixer(const struct config_param *param, const struct mixer_plugin *plugin, - struct filter *filter_chain) + struct filter *filter_chain, + GError **error_r) { struct mixer *mixer; @@ -104,10 +105,10 @@ audio_output_load_mixer(const struct config_param *param, if (plugin == NULL) return NULL; - return mixer_new(plugin, param); + return mixer_new(plugin, param, error_r); case MIXER_TYPE_SOFTWARE: - mixer = mixer_new(&software_mixer_plugin, NULL); + mixer = mixer_new(&software_mixer_plugin, NULL, NULL); assert(mixer != NULL); filter_chain_append(filter_chain, @@ -124,6 +125,7 @@ audio_output_init(struct audio_output *ao, const struct config_param *param, GError **error_r) { const struct audio_output_plugin *plugin = NULL; + GError *error = NULL; if (param) { const char *p; @@ -199,7 +201,12 @@ audio_output_init(struct audio_output *ao, const struct config_param *param, return false; ao->mixer = audio_output_load_mixer(param, plugin->mixer_plugin, - ao->filter); + ao->filter, &error); + if (ao->mixer == NULL && error != NULL) { + g_warning("Failed to initialize hardware mixer for '%s': %s", + ao->name, error->message); + g_error_free(error); + } /* the "convert" filter must be the last one in the chain */ diff --git a/test/read_mixer.c b/test/read_mixer.c index 0e814f4ba..89ea55356 100644 --- a/test/read_mixer.c +++ b/test/read_mixer.c @@ -46,6 +46,7 @@ pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED int length, int main(int argc, G_GNUC_UNUSED char **argv) { + GError *error = NULL; struct mixer *mixer; bool success; int volume; @@ -57,27 +58,34 @@ int main(int argc, G_GNUC_UNUSED char **argv) g_thread_init(NULL); - mixer = mixer_new(&alsa_mixer_plugin, NULL); + mixer = mixer_new(&alsa_mixer_plugin, NULL, &error); if (mixer == NULL) { - g_printerr("mixer_new() failed\n"); + g_printerr("mixer_new() failed: %s\n", error->message); + g_error_free(error); return 2; } - success = mixer_open(mixer); + success = mixer_open(mixer, &error); if (!success) { mixer_free(mixer); - g_printerr("failed to open the mixer\n"); + g_printerr("failed to open the mixer: %s\n", error->message); + g_error_free(error); return 2; } - volume = mixer_get_volume(mixer); + volume = mixer_get_volume(mixer, &error); mixer_close(mixer); mixer_free(mixer); assert(volume >= -1 && volume <= 100); if (volume < 0) { - g_printerr("failed to read volume\n"); + if (error != NULL) { + g_printerr("failed to read volume: %s\n", + error->message); + g_error_free(error); + } else + g_printerr("failed to read volume\n"); return 2; } -- cgit v1.2.3