diff options
Diffstat (limited to '')
-rw-r--r-- | src/mixer/alsa_mixer.c | 144 | ||||
-rw-r--r-- | src/mixer/oss_mixer.c | 96 | ||||
-rw-r--r-- | src/mixer_api.c | 6 | ||||
-rw-r--r-- | src/mixer_api.h | 34 |
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 |