Hi, I use mpd on OpenBSD. Here is a patch I use to build the OpenBSD port of mpd.
* adds sndio mixer support * increments the glibc++ version quirk in CommandError.cxx to a date that includes the OpenBSD glibc++ (gcc 4.9.4). It would be nice to have this included upstream. I'm not subscribed to the list, so please CC me. Thanks, Christopher -- http://gmerlin.de OpenPGP: http://gmerlin.de/christopher.pub 2779 7F73 44FD 0736 B67A C410 69EC 7922 34B4 2566
From 4ba990da805cb01c4cae5fbf6615a2b7d8416241 Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann <madro...@gmerlin.de> Date: Tue, 31 Jan 2017 14:24:00 +0100 Subject: [PATCH 1/2] Add sndio mixer plugin --- Makefile.am | 1 + doc/mpdconf.example | 2 +- src/mixer/MixerList.hxx | 1 + src/mixer/plugins/SndioMixerPlugin.cxx | 68 ++++++++++++++++++++++++++++++++ src/output/plugins/SndioOutputPlugin.cxx | 55 ++++++++++++++++---------- src/output/plugins/SndioOutputPlugin.hxx | 30 ++++++++++++++ 6 files changed, 136 insertions(+), 21 deletions(-) create mode 100644 src/mixer/plugins/SndioMixerPlugin.cxx diff --git Makefile.am Makefile.am index 898abba82..3dc078657 100644 --- Makefile.am +++ Makefile.am @@ -1449,6 +1449,7 @@ if ENABLE_SNDIO liboutput_plugins_a_SOURCES += \ src/output/plugins/SndioOutputPlugin.cxx \ src/output/plugins/SndioOutputPlugin.hxx +libmixer_plugins_a_SOURCES += src/mixer/plugins/SndioMixerPlugin.cxx endif if ENABLE_HAIKU diff --git doc/mpdconf.example doc/mpdconf.example index 2609c38c1..504ecd825 100644 --- doc/mpdconf.example +++ doc/mpdconf.example @@ -310,7 +310,7 @@ input { #audio_output { # type "sndio" # name "sndio output" -# mixer_type "software" +# mixer_type "hardware" #} # # An example of an OS X output: diff --git src/mixer/MixerList.hxx src/mixer/MixerList.hxx index b1a8cf11a..21edb9d17 100644 --- src/mixer/MixerList.hxx +++ src/mixer/MixerList.hxx @@ -35,5 +35,6 @@ extern const MixerPlugin oss_mixer_plugin; extern const MixerPlugin roar_mixer_plugin; extern const MixerPlugin pulse_mixer_plugin; extern const MixerPlugin winmm_mixer_plugin; +extern const MixerPlugin sndio_mixer_plugin; #endif diff --git src/mixer/plugins/SndioMixerPlugin.cxx src/mixer/plugins/SndioMixerPlugin.cxx new file mode 100644 index 000000000..9ba3ab42e --- /dev/null +++ src/mixer/plugins/SndioMixerPlugin.cxx @@ -0,0 +1,68 @@ +/* + * Copyright 2017 Christopher Zimmermann <christop...@gmerlin.de> + * + * 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 <sndio.h> + +#include "config.h" +#include "mixer/Listener.hxx" +#include "mixer/MixerInternal.hxx" +#include "output/plugins/SndioOutputPlugin.hxx" + +class SndioMixer; + +class SndioMixer final : public Mixer { + /** + * The current volume in percent (0..100). + */ + SndioOutput &output; + +public: + SndioMixer(SndioOutput &output, MixerListener &listener) + :Mixer(sndio_mixer_plugin, listener), output(output) + { + output.RegisterMixerListener(this, &listener); + } + + /* virtual methods from class Mixer */ + void Open() override {} + + void Close() override {} + + int GetVolume() override { + return output.GetVolume(); + } + + void SetVolume(unsigned volume) override { + output.SetVolume(volume); + } + +}; + +static Mixer * +sndio_mixer_init(gcc_unused EventLoop &event_loop, + AudioOutput &ao, + MixerListener &listener, + gcc_unused const ConfigBlock &block) +{ + return new SndioMixer((SndioOutput &)ao, listener); +} + +const MixerPlugin sndio_mixer_plugin = { + sndio_mixer_init, + false, +}; diff --git src/output/plugins/SndioOutputPlugin.cxx src/output/plugins/SndioOutputPlugin.cxx index 8c4a7327e..73a68f9b4 100644 --- src/output/plugins/SndioOutputPlugin.cxx +++ src/output/plugins/SndioOutputPlugin.cxx @@ -21,6 +21,7 @@ #include "SndioOutputPlugin.hxx" #include "../OutputAPI.hxx" #include "../Wrapper.hxx" +#include "mixer/MixerList.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -37,30 +38,16 @@ static constexpr unsigned MPD_SNDIO_BUFFER_TIME_MS = 250; static constexpr Domain sndio_output_domain("sndio_output"); -class SndioOutput { - friend struct AudioOutputWrapper<SndioOutput>; - AudioOutput base; - const char *const device; - const unsigned buffer_time; /* in ms */ - struct sio_hdl *sio_hdl; - -public: - SndioOutput(const ConfigBlock &block); - - static SndioOutput *Create(EventLoop &event_loop, - const ConfigBlock &block); - - void Open(AudioFormat &audio_format); - void Close(); - size_t Play(const void *chunk, size_t size); - void Cancel(); -}; +void SndioMixerCallback(void *arg, unsigned int volume) { + ((SndioOutput *)arg)->VolumeChanged(volume); +} SndioOutput::SndioOutput(const ConfigBlock &block) :base(sndio_output_plugin, block), device(block.GetBlockValue("device", SIO_DEVANY)), buffer_time(block.GetBlockValue("buffer_time", - MPD_SNDIO_BUFFER_TIME_MS)) + MPD_SNDIO_BUFFER_TIME_MS)), + raw_volume(SIO_MAXVOL) { } @@ -139,6 +126,9 @@ SndioOutput::Open(AudioFormat &audio_format) throw std::runtime_error("Requested audio params cannot be satisfied"); } + sio_setvol(sio_hdl, raw_volume); + sio_onvol(sio_hdl, SndioMixerCallback, this); + if (!sio_start(sio_hdl)) { sio_close(sio_hdl); throw std::runtime_error("Failed to start audio device"); @@ -162,6 +152,31 @@ SndioOutput::Play(const void *chunk, size_t size) return n; } +void +SndioOutput::SetVolume(unsigned int volume) { + sio_setvol(sio_hdl, volume * SIO_MAXVOL / 100); +} + +void +SndioOutput::VolumeChanged(unsigned int _raw_volume) { + raw_volume = _raw_volume; + if (listener != NULL && mixer != NULL) { + listener->OnMixerVolumeChanged(*mixer, + _raw_volume * 100 / SIO_MAXVOL); + } +} + +unsigned int +SndioOutput::GetVolume() { + return (raw_volume * 100 / SIO_MAXVOL); +} + +void +SndioOutput::RegisterMixerListener(Mixer *_mixer, MixerListener *_listener) { + mixer = _mixer; + listener = _listener; +} + typedef AudioOutputWrapper<SndioOutput> Wrapper; const struct AudioOutputPlugin sndio_output_plugin = { @@ -179,5 +194,5 @@ const struct AudioOutputPlugin sndio_output_plugin = { nullptr, nullptr, nullptr, - nullptr, + &sndio_mixer_plugin, }; diff --git src/output/plugins/SndioOutputPlugin.hxx src/output/plugins/SndioOutputPlugin.hxx index 5ad43f0f6..47416b058 100644 --- src/output/plugins/SndioOutputPlugin.hxx +++ src/output/plugins/SndioOutputPlugin.hxx @@ -20,6 +20,36 @@ #ifndef MPD_SNDIO_OUTPUT_PLUGIN_HXX #define MPD_SNDIO_OUTPUT_PLUGIN_HXX +#include "../OutputAPI.hxx" +#include "../Wrapper.hxx" +#include "mixer/Listener.hxx" + extern const struct AudioOutputPlugin sndio_output_plugin; +class SndioOutput { + friend struct AudioOutputWrapper<SndioOutput>; + AudioOutput base; + Mixer *mixer = NULL; + MixerListener *listener = NULL; + const char *const device; + const unsigned buffer_time; /* in ms */ + struct sio_hdl *sio_hdl; + unsigned int raw_volume; + +public: + SndioOutput(const ConfigBlock &block); + + static SndioOutput *Create(EventLoop &event_loop, + const ConfigBlock &block); + + void Open(AudioFormat &audio_format); + void Close(); + size_t Play(const void *chunk, size_t size); + void Cancel(); + void SetVolume(unsigned int _volume); + unsigned int GetVolume(); + void RegisterMixerListener(Mixer *_mixer, MixerListener *_listener); + void VolumeChanged(unsigned int _volume); +}; + #endif -- 2.11.0
From 4d0a8f8ce03eaa0199eb39a34a96a942eb80af3d Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann <madro...@gmerlin.de> Date: Tue, 31 Jan 2017 14:24:53 +0100 Subject: [PATCH 2/2] Fix building for gcc 4.9, too. --- src/command/CommandError.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git src/command/CommandError.cxx src/command/CommandError.cxx index 7d8878c61..a720e6745 100644 --- src/command/CommandError.cxx +++ src/command/CommandError.cxx @@ -100,13 +100,13 @@ ToAck(std::exception_ptr ep) return ACK_ERROR_SYSTEM; } catch (const std::invalid_argument &e) { return ACK_ERROR_ARG; -#if defined(__GLIBCXX__) && __GLIBCXX__ < 20151204 +#if defined(__GLIBCXX__) && __GLIBCXX__ < 20160727 } catch (const std::exception &e) { #else } catch (...) { #endif try { -#if defined(__GLIBCXX__) && __GLIBCXX__ < 20151204 +#if defined(__GLIBCXX__) && __GLIBCXX__ < 20160727 /* workaround for g++ 4.x: no overload for rethrow_exception(exception_ptr) */ std::rethrow_if_nested(e); -- 2.11.0
pgp83nkXE9r_3.pgp
Description: OpenPGP digital signature
_______________________________________________ mpd-devel mailing list mpd-devel@musicpd.org http://mailman.blarg.de/listinfo/mpd-devel