summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Leon <ml@matthewleon.com>2017-08-22 10:36:37 +0100
committerMatthew Leon <ml@matthewleon.com>2017-08-22 10:36:37 +0100
commitaa9c6062b04dc83f8a6302bc7aeb2dfd7c8c51bd (patch)
treef35862e0c021dc641314a2a65ddd815feb02c39e
parent95637fd1533108b90979d92f4b6c851864602d07 (diff)
parent5fb39658f17d1eafeb745a316112440944c3a507 (diff)
Merge branch 'v0.20.x' into master
contains OSX mixer
-rw-r--r--AUTHORS1
-rw-r--r--Makefile.am2
-rw-r--r--NEWS2
-rw-r--r--src/mixer/MixerList.hxx1
-rw-r--r--src/mixer/plugins/OSXMixerPlugin.cxx69
-rw-r--r--src/output/plugins/OSXOutputPlugin.cxx54
-rw-r--r--src/output/plugins/OSXOutputPlugin.hxx8
7 files changed, 137 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
index e4582d0ec..14aa053fa 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -30,3 +30,4 @@ The following people have contributed code to MPD:
Jurgen Kramer <gtmkramer@xs4all.nl>
Jean-Francois Dockes <jf@dockes.org>
Yue Wang <yuleopen@gmail.com>
+ Matthew Leon Grinshpun <ml@matthewleon.com>
diff --git a/Makefile.am b/Makefile.am
index 42ba6eefc..61b442b75 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1507,6 +1507,8 @@ liboutput_plugins_a_SOURCES += \
src/output/plugins/OSXOutputPlugin.cxx \
src/output/plugins/OSXOutputPlugin.hxx
endif
+libmixer_plugins_a_SOURCES += \
+ src/mixer/plugins/OSXMixerPlugin.cxx
if ENABLE_PULSE
liboutput_plugins_a_SOURCES += \
diff --git a/NEWS b/NEWS
index cd8da113b..530f194a5 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,8 @@ ver 0.20.10 (not yet released)
- ffmpeg: support MusicBrainz ID3v2 tags
* tags
- aiff: fix FORM chunk size endianess (is big-endian)
+* mixer
+ - osx: add a mixer for OSX.
* fix crash on Windows
ver 0.20.9 (2017/06/04)
diff --git a/src/mixer/MixerList.hxx b/src/mixer/MixerList.hxx
index b1a8cf11a..7c5fe24b2 100644
--- a/src/mixer/MixerList.hxx
+++ b/src/mixer/MixerList.hxx
@@ -32,6 +32,7 @@ extern const MixerPlugin software_mixer_plugin;
extern const MixerPlugin alsa_mixer_plugin;
extern const MixerPlugin haiku_mixer_plugin;
extern const MixerPlugin oss_mixer_plugin;
+extern const MixerPlugin osx_mixer_plugin;
extern const MixerPlugin roar_mixer_plugin;
extern const MixerPlugin pulse_mixer_plugin;
extern const MixerPlugin winmm_mixer_plugin;
diff --git a/src/mixer/plugins/OSXMixerPlugin.cxx b/src/mixer/plugins/OSXMixerPlugin.cxx
new file mode 100644
index 000000000..0132cbad0
--- /dev/null
+++ b/src/mixer/plugins/OSXMixerPlugin.cxx
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2003-2017 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "mixer/MixerInternal.hxx"
+#include "output/plugins/OSXOutputPlugin.hxx"
+
+class OSXMixer final : public Mixer {
+ OSXOutput &output;
+
+public:
+ OSXMixer(OSXOutput &_output, MixerListener &_listener)
+ :Mixer(osx_mixer_plugin, _listener),
+ output(_output)
+ {
+ }
+
+ /* virtual methods from class Mixer */
+ void Open() noexcept override {
+ }
+
+ void Close() noexcept override {
+ }
+
+ int GetVolume() override;
+ void SetVolume(unsigned volume) override;
+};
+
+int
+OSXMixer::GetVolume()
+{
+ return osx_output_get_volume(output);
+}
+
+void
+OSXMixer::SetVolume(unsigned new_volume)
+{
+ osx_output_set_volume(output, new_volume);
+}
+
+static Mixer *
+osx_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao,
+ MixerListener &listener,
+ gcc_unused const ConfigBlock &block)
+{
+ OSXOutput &osxo = (OSXOutput &)ao;
+ return new OSXMixer(osxo, listener);
+}
+
+const MixerPlugin osx_mixer_plugin = {
+ osx_mixer_init,
+ true,
+};
diff --git a/src/output/plugins/OSXOutputPlugin.cxx b/src/output/plugins/OSXOutputPlugin.cxx
index eed0552da..e9f0f1b9a 100644
--- a/src/output/plugins/OSXOutputPlugin.cxx
+++ b/src/output/plugins/OSXOutputPlugin.cxx
@@ -20,6 +20,7 @@
#include "config.h"
#include "OSXOutputPlugin.hxx"
#include "../OutputAPI.hxx"
+#include "mixer/MixerList.hxx"
#include "util/ScopeExit.hxx"
#include "util/RuntimeError.hxx"
#include "util/Domain.hxx"
@@ -53,6 +54,8 @@ struct OSXOutput final : AudioOutput {
OSXOutput(const ConfigBlock &block);
static AudioOutput *Create(EventLoop &, const ConfigBlock &block);
+ int GetVolume();
+ void SetVolume(unsigned new_volume);
private:
void Enable() override;
@@ -137,6 +140,45 @@ OSXOutput::Create(EventLoop &, const ConfigBlock &block)
return oo;
}
+
+int
+OSXOutput::GetVolume()
+{
+ AudioUnitParameterValue dvolume;
+ char errormsg[1024];
+
+ OSStatus status = AudioUnitGetParameter(au, kHALOutputParam_Volume,
+ kAudioUnitScope_Global, 0, &dvolume);
+ if (status != noErr) {
+ osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
+ throw FormatRuntimeError("unable to get volume: %s", errormsg);
+ }
+
+ /* see the explanation in SetVolume, below */
+ return static_cast<int>(dvolume * dvolume * 100.0);
+}
+
+void
+OSXOutput::SetVolume(unsigned new_volume) {
+ char errormsg[1024];
+
+ /* The scaling below makes shifts in volume greater at the lower end
+ * of the scale. This mimics the "feel" of physical volume levers. This is
+ * generally what users of audio software expect.
+ */
+
+ AudioUnitParameterValue scaled_volume =
+ sqrt(static_cast<AudioUnitParameterValue>(new_volume) / 100.0);
+
+ OSStatus status = AudioUnitSetParameter(au, kHALOutputParam_Volume,
+ kAudioUnitScope_Global, 0, scaled_volume, 0);
+ if (status != noErr) {
+ osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
+ throw FormatRuntimeError( "unable to set new volume %u: %s",
+ new_volume, errormsg);
+ }
+}
+
static void
osx_output_parse_channel_map(
const char *device_name,
@@ -669,6 +711,18 @@ OSXOutput::Delay() const noexcept
: std::chrono::milliseconds(25);
}
+int
+osx_output_get_volume(OSXOutput &output)
+{
+ return output.GetVolume();
+}
+
+void
+osx_output_set_volume(OSXOutput &output, unsigned new_volume)
+{
+ return output.SetVolume(new_volume);
+}
+
const struct AudioOutputPlugin osx_output_plugin = {
"osx",
osx_output_test_default_device,
diff --git a/src/output/plugins/OSXOutputPlugin.hxx b/src/output/plugins/OSXOutputPlugin.hxx
index 440cb8de1..9c98424b2 100644
--- a/src/output/plugins/OSXOutputPlugin.hxx
+++ b/src/output/plugins/OSXOutputPlugin.hxx
@@ -20,6 +20,14 @@
#ifndef MPD_OSX_OUTPUT_PLUGIN_HXX
#define MPD_OSX_OUTPUT_PLUGIN_HXX
+struct OSXOutput;
+
extern const struct AudioOutputPlugin osx_output_plugin;
+int
+osx_output_get_volume(OSXOutput &output);
+
+void
+osx_output_set_volume(OSXOutput &output, unsigned new_volume);
+
#endif