summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Pit-Claudel <clement.pitclaudel@live.com>2019-02-17 16:14:52 -0500
committerClément Pit-Claudel <clement.pitclaudel@live.com>2019-02-17 16:14:52 -0500
commit110e6d026b87326ecc739619c36cacb2b2caf303 (patch)
tree0ed4c295e2825186e6a5f8fe6a75b452823eda66
parentc0f57b8a8bd8ab9cdb7c69cafabe74b33aed7abc (diff)
mixer/pulse: Add a new 'scale' parameter to allow volumes above 100
Closes GH-479.
-rw-r--r--doc/plugins.rst2
-rw-r--r--src/mixer/plugins/PulseMixerPlugin.cxx38
2 files changed, 34 insertions, 6 deletions
diff --git a/doc/plugins.rst b/doc/plugins.rst
index 0e09b35ab..5b39069cb 100644
--- a/doc/plugins.rst
+++ b/doc/plugins.rst
@@ -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
~~~~~~~~
diff --git a/src/mixer/plugins/PulseMixerPlugin.cxx b/src/mixer/plugins/PulseMixerPlugin.cxx
index f04369fe2..d2bfb2444 100644
--- a/src/mixer/plugins/PulseMixerPlugin.cxx
+++ b/src/mixer/plugins/PulseMixerPlugin.cxx
@@ -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;
}