aboutsummaryrefslogtreecommitdiffstats
path: root/src/mixer
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mixer/alsa_mixer.c144
-rw-r--r--src/mixer/oss_mixer.c96
-rw-r--r--src/mixer_api.c6
-rw-r--r--src/mixer_api.h34
4 files changed, 144 insertions, 136 deletions
diff --git a/src/mixer/alsa_mixer.c b/src/mixer/alsa_mixer.c
index d35040499..b22ee48e9 100644
--- a/src/mixer/alsa_mixer.c
+++ b/src/mixer/alsa_mixer.c
@@ -146,85 +146,87 @@ alsa_mixer_open(struct mixer *data)
return false;
}
-static bool
-alsa_mixer_control(struct mixer *data, int cmd, void *arg)
+static int
+alsa_mixer_get_volume(struct mixer *mixer)
{
- struct alsa_mixer *am = (struct alsa_mixer *)data;
- switch (cmd) {
- case AC_MIXER_GETVOL:
- {
- int err;
- int ret, *volume = arg;
- long level;
-
- if (!am->handle && !alsa_mixer_open(data)) {
- return false;
- }
- if ((err = snd_mixer_handle_events(am->handle)) < 0) {
- g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n",
- snd_strerror(err), "handle_events");
- alsa_mixer_close(data);
- return false;
- }
- if ((err = snd_mixer_selem_get_playback_volume(am->elem,
- SND_MIXER_SCHN_FRONT_LEFT, &level)) < 0) {
- g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n",
- snd_strerror(err), "selem_get_playback_volume");
- alsa_mixer_close(data);
- return false;
- }
- ret = ((am->volume_set / 100.0) * (am->volume_max - am->volume_min)
- + am->volume_min) + 0.5;
- if (am->volume_set > 0 && ret == level) {
- ret = am->volume_set;
- } else {
- ret = (int)(100 * (((float)(level - am->volume_min)) /
- (am->volume_max - am->volume_min)) + 0.5);
- }
- *volume = ret;
- return true;
+ struct alsa_mixer *am = (struct alsa_mixer *)mixer;
+ int err;
+ int ret;
+ long level;
+
+ if (am->handle == NULL && !alsa_mixer_open(mixer))
+ return -1;
+
+ 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");
+ alsa_mixer_close(mixer);
+ return false;
}
- case AC_MIXER_SETVOL:
- {
- float vol;
- long level;
- int *volume = arg;
- int err;
-
- if (!am->handle && !alsa_mixer_open(data)) {
- return false;
- }
- vol = *volume;
-
- am->volume_set = vol + 0.5;
- am->volume_set = am->volume_set > 100 ? 100 :
- (am->volume_set < 0 ? 0 : am->volume_set);
-
- level = (long)(((vol / 100.0) * (am->volume_max - am->volume_min) +
- am->volume_min) + 0.5);
- level = level > am->volume_max ? am->volume_max : level;
- level = level < am->volume_min ? am->volume_min : level;
-
- if ((err = snd_mixer_selem_set_playback_volume_all(am->elem,
- level)) < 0) {
- g_warning("problems setting alsa volume: %s\n",
- snd_strerror(err));
- alsa_mixer_close(data);
- return false;
- }
- return true;
+
+ err = snd_mixer_selem_get_playback_volume(am->elem,
+ 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");
+ alsa_mixer_close(mixer);
+ return false;
}
- default:
- g_warning("Unsuported alsa control\n");
- break;
+
+ ret = ((am->volume_set / 100.0) * (am->volume_max - am->volume_min)
+ + am->volume_min) + 0.5;
+ if (am->volume_set > 0 && ret == level) {
+ ret = am->volume_set;
+ } else {
+ ret = (int)(100 * (((float)(level - am->volume_min)) /
+ (am->volume_max - am->volume_min)) + 0.5);
}
- return false;
+
+ return ret;
+}
+
+static bool
+alsa_mixer_set_volume(struct mixer *mixer, unsigned volume)
+{
+ struct alsa_mixer *am = (struct alsa_mixer *)mixer;
+ float vol;
+ long level;
+ int err;
+
+ if (am->handle == NULL && !alsa_mixer_open(mixer))
+ return false;
+
+ vol = volume;
+
+ am->volume_set = vol + 0.5;
+ am->volume_set = am->volume_set > 100
+ ? 100 :
+ (am->volume_set < 0
+ ? 0 : am->volume_set);
+
+ level = (long)(((vol / 100.0) * (am->volume_max - am->volume_min) +
+ am->volume_min) + 0.5);
+ level = level > am->volume_max ? am->volume_max : level;
+ level = level < am->volume_min ? am->volume_min : level;
+
+ 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));
+ alsa_mixer_close(mixer);
+ return false;
+ }
+
+ return true;
}
const struct mixer_plugin alsa_mixer = {
.init = alsa_mixer_init,
.finish = alsa_mixer_finish,
.open = alsa_mixer_open,
- .control = alsa_mixer_control,
- .close = alsa_mixer_close
+ .close = alsa_mixer_close,
+ .get_volume = alsa_mixer_get_volume,
+ .set_volume = alsa_mixer_set_volume,
};
diff --git a/src/mixer/oss_mixer.c b/src/mixer/oss_mixer.c
index 4dbd40bbb..2c73236ee 100644
--- a/src/mixer/oss_mixer.c
+++ b/src/mixer/oss_mixer.c
@@ -137,74 +137,64 @@ oss_mixer_open(struct mixer *data)
return true;
}
-static bool
-oss_mixer_control(struct mixer *data, int cmd, void *arg)
+static int
+oss_mixer_get_volume(struct mixer *mixer)
{
- struct oss_mixer *om = (struct oss_mixer *) data;
- switch (cmd) {
- case AC_MIXER_GETVOL:
- {
- int left, right, level;
- int *ret;
+ struct oss_mixer *om = (struct oss_mixer *)mixer;
+ int left, right, level;
+ int ret;
- if (om->device_fd < 0 && !oss_mixer_open(data)) {
- return false;
- }
+ if (om->device_fd < 0 && !oss_mixer_open(mixer))
+ return false;
- if (ioctl(om->device_fd, MIXER_READ(om->volume_control), &level) < 0) {
- oss_mixer_close(data);
- g_warning("unable to read oss volume\n");
- return false;
- }
+ ret = ioctl(om->device_fd, MIXER_READ(om->volume_control), &level);
+ if (ret < 0) {
+ oss_mixer_close(mixer);
+ g_warning("unable to read oss volume\n");
+ return false;
+ }
- left = level & 0xff;
- right = (level & 0xff00) >> 8;
+ left = level & 0xff;
+ right = (level & 0xff00) >> 8;
- if (left != right) {
- g_warning("volume for left and right is not the same, \"%i\" and "
- "\"%i\"\n", left, right);
- }
- ret = (int *) arg;
- *ret = left;
- return true;
+ if (left != right) {
+ g_warning("volume for left and right is not the same, \"%i\" and "
+ "\"%i\"\n", left, right);
}
- case AC_MIXER_SETVOL:
- {
- int new;
- int level;
- int *value = arg;
- if (om->device_fd < 0 && !oss_mixer_open(data)) {
- return false;
- }
+ return left;
+}
- new = *value;
- if (new < 0) {
- new = 0;
- } else if (new > 100) {
- new = 100;
- }
+static bool
+oss_mixer_set_volume(struct mixer *mixer, unsigned volume)
+{
+ struct oss_mixer *om = (struct oss_mixer *)mixer;
+ int level;
+ int ret;
- level = (new << 8) + new;
+ if (om->device_fd < 0 && !oss_mixer_open(mixer))
+ return false;
- if (ioctl(om->device_fd, MIXER_WRITE(om->volume_control), &level) < 0) {
- g_warning("unable to set oss volume\n");
- oss_mixer_close(data);
- return false;
- }
- return true;
- }
- default:
- g_warning("Unsuported oss control\n");
- break;
+ if (volume > 100)
+ volume = 100;
+
+ level = (volume << 8) + volume;
+
+ ret = ioctl(om->device_fd, MIXER_WRITE(om->volume_control), &level);
+ if (ret < 0) {
+ g_warning("unable to set oss volume\n");
+ oss_mixer_close(mixer);
+ return false;
}
- return false;
+
+ return true;
}
const struct mixer_plugin oss_mixer = {
.init = oss_mixer_init,
.finish = oss_mixer_finish,
.open = oss_mixer_open,
- .control = oss_mixer_control,
- .close = oss_mixer_close
+ .close = oss_mixer_close,
+ .get_volume = oss_mixer_get_volume,
+ .set_volume = oss_mixer_set_volume,
};
diff --git a/src/mixer_api.c b/src/mixer_api.c
index b0905bc5e..ec621950c 100644
--- a/src/mixer_api.c
+++ b/src/mixer_api.c
@@ -50,12 +50,6 @@ bool mixer_open(struct mixer *mixer)
return mixer->plugin->open(mixer);
}
-bool mixer_control(struct mixer *mixer, int cmd, void *arg)
-{
- assert(mixer != NULL && mixer->plugin != NULL);
- return mixer->plugin->control(mixer, cmd, arg);
-}
-
void mixer_close(struct mixer *mixer)
{
assert(mixer != NULL && mixer->plugin != NULL);
diff --git a/src/mixer_api.h b/src/mixer_api.h
index b79d02a1c..8dbbbe820 100644
--- a/src/mixer_api.h
+++ b/src/mixer_api.h
@@ -45,14 +45,25 @@ struct mixer_plugin {
bool (*open)(struct mixer *data);
/**
- * Control mixer device.
- */
- bool (*control)(struct mixer *data, int cmd, void *arg);
-
- /**
* Close mixer device
*/
void (*close)(struct mixer *data);
+
+ /**
+ * Reads the current volume.
+ *
+ * @return the current volume (0..100 including) or -1 on
+ * error
+ */
+ int (*get_volume)(struct mixer *mixer);
+
+ /**
+ * Sets the volume.
+ *
+ * @param volume the new volume (0..100 including)
+ * @return true on success
+ */
+ bool (*set_volume)(struct mixer *mixer, unsigned volume);
};
struct mixer {
@@ -72,7 +83,18 @@ void
mixer_free(struct mixer *mixer);
bool mixer_open(struct mixer *mixer);
-bool mixer_control(struct mixer *mixer, int cmd, void *arg);
void mixer_close(struct mixer *mixer);
+static inline int
+mixer_get_volume(struct mixer *mixer)
+{
+ return mixer->plugin->get_volume(mixer);
+}
+
+static inline bool
+mixer_set_volume(struct mixer *mixer, unsigned volume)
+{
+ return mixer->plugin->set_volume(mixer, volume);
+}
+
#endif