diff --git a/NEWS b/NEWS index b146b50cc..b852673ac 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.20.1 (not yet released) +* mixer + - alsa: normalize displayed volume according to human perception * fix crash with volume_normalization enabled ver 0.20 (2017/01/04) diff --git a/src/mixer/plugins/AlsaMixerPlugin.cxx b/src/mixer/plugins/AlsaMixerPlugin.cxx index a5ce94118..255439932 100644 --- a/src/mixer/plugins/AlsaMixerPlugin.cxx +++ b/src/mixer/plugins/AlsaMixerPlugin.cxx @@ -25,15 +25,18 @@ #include "event/DeferredMonitor.hxx" #include "util/ASCII.hxx" #include "util/ReusableArray.hxx" -#include "util/Clamp.hxx" #include "util/Domain.hxx" #include "util/RuntimeError.hxx" #include "Log.hxx" -#include +extern "C" { +#include "volume_mapping.h" +} #include +#include + #define VOLUME_MIXER_ALSA_DEFAULT "default" #define VOLUME_MIXER_ALSA_CONTROL_DEFAULT "PCM" static constexpr unsigned VOLUME_MIXER_ALSA_INDEX_DEFAULT = 0; @@ -68,9 +71,6 @@ class AlsaMixer final : public Mixer { snd_mixer_t *handle; snd_mixer_elem_t *elem; - long volume_min; - long volume_max; - int volume_set; AlsaMixerMonitor *monitor; @@ -228,9 +228,6 @@ AlsaMixer::Setup() if (elem == nullptr) throw FormatRuntimeError("no such mixer control: %s", control); - snd_mixer_selem_get_playback_volume_range(elem, &volume_min, - &volume_max); - snd_mixer_elem_set_callback_private(elem, this); snd_mixer_elem_set_callback(elem, alsa_mixer_elem_callback); @@ -242,8 +239,6 @@ AlsaMixer::Open() { int err; - volume_set = -1; - err = snd_mixer_open(&handle, 0); if (err < 0) throw FormatRuntimeError("snd_mixer_open() failed: %s", @@ -272,8 +267,6 @@ int AlsaMixer::GetVolume() { int err; - int ret; - long level; assert(handle != nullptr); @@ -282,43 +275,15 @@ AlsaMixer::GetVolume() throw FormatRuntimeError("snd_mixer_handle_events() failed: %s", snd_strerror(err)); - err = snd_mixer_selem_get_playback_volume(elem, - SND_MIXER_SCHN_FRONT_LEFT, - &level); - if (err < 0) - throw FormatRuntimeError("failed to read ALSA volume: %s", - snd_strerror(err)); - - ret = ((volume_set / 100.0) * (volume_max - volume_min) - + volume_min) + 0.5; - if (volume_set > 0 && ret == level) { - ret = volume_set; - } else { - ret = (int)(100 * (((float)(level - volume_min)) / - (volume_max - volume_min)) + 0.5); - } - - return ret; + return lrint(100 * get_normalized_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT)); } void AlsaMixer::SetVolume(unsigned volume) { - float vol; - long level; - int err; - assert(handle != nullptr); - vol = volume; - - volume_set = vol + 0.5; - - level = (long)(((vol / 100.0) * (volume_max - volume_min) + - volume_min) + 0.5); - level = Clamp(level, volume_min, volume_max); - - err = snd_mixer_selem_set_playback_volume_all(elem, level); + int err = set_normalized_playback_volume(elem, 0.01*volume, 1); if (err < 0) throw FormatRuntimeError("failed to set ALSA volume: %s", snd_strerror(err));