mixer/pulse: Add a new 'scale' parameter to allow volumes above 100

Closes GH-479.
This commit is contained in:
Clément Pit-Claudel 2019-02-17 16:14:52 -05:00
parent c0f57b8a8b
commit 110e6d026b
2 changed files with 34 additions and 6 deletions

View File

@ -935,6 +935,8 @@ The pulse plugin connects to a `PulseAudio <http://www.freedesktop.org/wiki/Soft
- Sets the host name of the PulseAudio server. By default, :program:`MPD` connects to the local PulseAudio server.
* - **sink NAME**
- Specifies the name of the PulseAudio sink :program:`MPD` should play on.
* - **scale FACTOR**
- Specifies a linear scaling coefficient (ranging from 0.5 to 5.0) to apply when adjusting volume through :program:`MPD`. For example, chosing a factor equal to ``"0.7"`` means that setting the volume to 100 in :program:`MPD` will set the PulseAudio volume to 70%, and a factor equal to ``"3.5"`` means that volume 100 in :program:`MPD` corresponds to a 350% PulseAudio volume.
recorder
~~~~~~~~

View File

@ -24,6 +24,9 @@
#include "mixer/MixerInternal.hxx"
#include "mixer/Listener.hxx"
#include "output/plugins/PulseOutputPlugin.hxx"
#include "util/NumberParser.hxx"
#include "util/RuntimeError.hxx"
#include "config/Block.hxx"
#include <pulse/context.h>
#include <pulse/introspect.h>
@ -39,11 +42,14 @@ class PulseMixer final : public Mixer {
bool online;
struct pa_cvolume volume;
float volume_scale_factor;
public:
PulseMixer(PulseOutput &_output, MixerListener &_listener)
PulseMixer(PulseOutput &_output, MixerListener &_listener,
double _volume_scale_factor)
:Mixer(pulse_mixer_plugin, _listener),
output(_output), online(false)
output(_output), online(false),
volume_scale_factor(_volume_scale_factor)
{
}
@ -159,13 +165,30 @@ pulse_mixer_on_change(PulseMixer &pm,
pm.Update(context, stream);
}
static float
parse_volume_scale_factor(const char *value) {
if (value == nullptr)
return 1.0;
char *endptr;
float factor = ParseFloat(value, &endptr);
if (*endptr != '\0' || factor < 0.5 || factor > 5.0)
throw FormatRuntimeError("scale \"%s\" is not a number in the "
"range 0.5 to 5.0",
value);
return factor;
}
static Mixer *
pulse_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
MixerListener &listener,
gcc_unused const ConfigBlock &block)
const ConfigBlock &block)
{
PulseOutput &po = (PulseOutput &)ao;
PulseMixer *pm = new PulseMixer(po, listener);
float scale = parse_volume_scale_factor(block.GetBlockValue("scale"));
PulseMixer *pm = new PulseMixer(po, listener, scale);
pulse_output_set_mixer(po, *pm);
@ -191,8 +214,9 @@ PulseMixer::GetVolume()
int
PulseMixer::GetVolumeInternal()
{
pa_volume_t max_pa_volume = volume_scale_factor * PA_VOLUME_NORM;
return online ?
(int)((100 * (pa_cvolume_avg(&volume) + 1)) / PA_VOLUME_NORM)
(int)((100 * (pa_cvolume_avg(&volume) + 1)) / max_pa_volume)
: -1;
}
@ -204,9 +228,11 @@ PulseMixer::SetVolume(unsigned new_volume)
if (!online)
throw std::runtime_error("disconnected");
pa_volume_t max_pa_volume = volume_scale_factor * PA_VOLUME_NORM;
struct pa_cvolume cvolume;
pa_cvolume_set(&cvolume, volume.channels,
(new_volume * PA_VOLUME_NORM + 50) / 100);
(new_volume * max_pa_volume + 50) / 100);
pulse_output_set_volume(output, &cvolume);
volume = cvolume;
}