mixer_plugin: use GError for error handling

This commit is contained in:
Max Kellermann
2009-10-20 22:10:56 +02:00
parent 9cd2129eeb
commit 4e2fb3fb89
11 changed files with 203 additions and 85 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;