From 0b9f650fe27bcb5ff78928b059c2e5032cfbcb97 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 29 Dec 2014 23:45:14 +0100 Subject: output/Wrapper: new helper class --- src/output/Wrapper.hxx | 93 ++++++++++++++++++++++++ src/output/plugins/JackOutputPlugin.cxx | 101 +++++++-------------------- src/output/plugins/PipeOutputPlugin.cxx | 58 ++++----------- src/output/plugins/RecorderOutputPlugin.cxx | 25 ++----- src/output/plugins/RoarOutputPlugin.cxx | 54 +++----------- src/output/plugins/sles/SlesOutputPlugin.cxx | 84 ++++------------------ 6 files changed, 159 insertions(+), 256 deletions(-) create mode 100644 src/output/Wrapper.hxx (limited to 'src') diff --git a/src/output/Wrapper.hxx b/src/output/Wrapper.hxx new file mode 100644 index 000000000..186544cce --- /dev/null +++ b/src/output/Wrapper.hxx @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2003-2014 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. + */ + +#ifndef MPD_OUTPUT_WRAPPER_HXX +#define MPD_OUTPUT_WRAPPER_HXX + +#include "util/Cast.hxx" + +template +struct AudioOutputWrapper { + static T &Cast(AudioOutput &ao) { + return ContainerCast(ao, &T::base); + } + + static AudioOutput *Init(const config_param ¶m, Error &error) { + T *t = T::Create(param, error); + return t != nullptr + ? &t->base + : nullptr; + } + + static void Finish(AudioOutput *ao) { + T *t = &Cast(*ao); + delete t; + } + + static bool Enable(AudioOutput *ao, Error &error) { + T &t = Cast(*ao); + return t.Enable(error); + } + + static void Disable(AudioOutput *ao) { + T &t = Cast(*ao); + t.Disable(); + } + + static bool Open(AudioOutput *ao, AudioFormat &audio_format, + Error &error) { + T &t = Cast(*ao); + return t.Open(audio_format, error); + } + + static void Close(AudioOutput *ao) { + T &t = Cast(*ao); + t.Close(); + } + + gcc_pure + static unsigned Delay(AudioOutput *ao) { + T &t = Cast(*ao); + return t.Delay(); + } + + static size_t Play(AudioOutput *ao, const void *chunk, size_t size, + Error &error) { + T &t = Cast(*ao); + return t.Play(chunk, size, error); + } + + static void Drain(AudioOutput *ao) { + T &t = Cast(*ao); + t.Drain(); + } + + static void Cancel(AudioOutput *ao) { + T &t = Cast(*ao); + t.Cancel(); + } + + gcc_pure + static bool Pause(AudioOutput *ao) { + T &t = Cast(*ao); + return t.Pause(); + } +}; + +#endif diff --git a/src/output/plugins/JackOutputPlugin.cxx b/src/output/plugins/JackOutputPlugin.cxx index f3a30b644..7a4b911c7 100644 --- a/src/output/plugins/JackOutputPlugin.cxx +++ b/src/output/plugins/JackOutputPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "JackOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "config/ConfigError.hxx" #include "util/ConstBuffer.hxx" #include "util/SplitString.hxx" @@ -100,6 +101,10 @@ struct JackOutput { bool Open(AudioFormat &new_audio_format, Error &error); + void Close() { + Stop(); + } + bool Start(Error &error); void Stop(); @@ -117,7 +122,15 @@ struct JackOutput { */ size_t WriteSamples(const float *src, size_t n_frames); + unsigned Delay() const { + return base.pause && pause && !shutdown + ? 1000 + : 0; + } + size_t Play(const void *chunk, size_t size, Error &error); + + bool Pause(); }; static constexpr Domain jack_output_domain("jack_output"); @@ -468,30 +481,6 @@ mpd_jack_init(const config_param ¶m, Error &error) return &jd->base; } -static void -mpd_jack_finish(AudioOutput *ao) -{ - JackOutput *jd = (JackOutput *)ao; - - delete jd; -} - -static bool -mpd_jack_enable(AudioOutput *ao, Error &error) -{ - JackOutput &jo = *(JackOutput *)ao; - - return jo.Enable(error); -} - -static void -mpd_jack_disable(AudioOutput *ao) -{ - JackOutput &jo = *(JackOutput *)ao; - - jo.Disable(); -} - /** * Stops the playback on the JACK connection. */ @@ -648,33 +637,6 @@ JackOutput::Open(AudioFormat &new_audio_format, Error &error) return Start(error); } -static bool -mpd_jack_open(AudioOutput *ao, AudioFormat &audio_format, - Error &error) -{ - JackOutput &jo = *(JackOutput *)ao; - - return jo.Open(audio_format, error); -} - -static void -mpd_jack_close(AudioOutput *ao) -{ - JackOutput &jo = *(JackOutput *)ao; - - jo.Stop(); -} - -static unsigned -mpd_jack_delay(AudioOutput *ao) -{ - JackOutput *jd = (JackOutput *)ao; - - return jd->base.pause && jd->pause && !jd->shutdown - ? 1000 - : 0; -} - inline size_t JackOutput::WriteSamples(const float *src, size_t n_frames) { @@ -744,42 +706,33 @@ JackOutput::Play(const void *chunk, size_t size, Error &error) } } -static size_t -mpd_jack_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) -{ - JackOutput &jo = *(JackOutput *)ao; - - return jo.Play(chunk, size, error); -} - -static bool -mpd_jack_pause(AudioOutput *ao) +inline bool +JackOutput::Pause() { - JackOutput *jd = (JackOutput *)ao; - - if (jd->shutdown) + if (shutdown) return false; - jd->pause = true; + pause = true; return true; } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin jack_output_plugin = { "jack", mpd_jack_test_default_device, mpd_jack_init, - mpd_jack_finish, - mpd_jack_enable, - mpd_jack_disable, - mpd_jack_open, - mpd_jack_close, - mpd_jack_delay, + &Wrapper::Finish, + &Wrapper::Enable, + &Wrapper::Disable, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, nullptr, - mpd_jack_play, + &Wrapper::Play, nullptr, nullptr, - mpd_jack_pause, + &Wrapper::Pause, nullptr, }; diff --git a/src/output/plugins/PipeOutputPlugin.cxx b/src/output/plugins/PipeOutputPlugin.cxx index 8fc9c92d6..7c0ea17de 100644 --- a/src/output/plugins/PipeOutputPlugin.cxx +++ b/src/output/plugins/PipeOutputPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "PipeOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "config/ConfigError.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -29,6 +30,8 @@ #include class PipeOutput { + friend AudioOutputWrapper; + AudioOutput base; std::string cmd; @@ -40,7 +43,7 @@ class PipeOutput { bool Configure(const config_param ¶m, Error &error); public: - static AudioOutput *Create(const config_param ¶m, Error &error); + static PipeOutput *Create(const config_param ¶m, Error &error); bool Open(AudioFormat &audio_format, Error &error); @@ -70,7 +73,7 @@ PipeOutput::Configure(const config_param ¶m, Error &error) return true; } -inline AudioOutput * +inline PipeOutput * PipeOutput::Create(const config_param ¶m, Error &error) { PipeOutput *po = new PipeOutput(); @@ -80,21 +83,7 @@ PipeOutput::Create(const config_param ¶m, Error &error) return nullptr; } - return &po->base; -} - -static AudioOutput * -pipe_output_init(const config_param ¶m, Error &error) -{ - return PipeOutput::Create(param, error); -} - -static void -pipe_output_finish(AudioOutput *ao) -{ - PipeOutput *pd = (PipeOutput *)ao; - - delete pd; + return po; } inline bool @@ -110,22 +99,6 @@ PipeOutput::Open(gcc_unused AudioFormat &audio_format, Error &error) return true; } -static bool -pipe_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) -{ - PipeOutput &po = *(PipeOutput *)ao; - - return po.Open(audio_format, error); -} - -static void -pipe_output_close(AudioOutput *ao) -{ - PipeOutput &po = *(PipeOutput *)ao; - - po.Close(); -} - inline size_t PipeOutput::Play(const void *chunk, size_t size, Error &error) { @@ -136,27 +109,20 @@ PipeOutput::Play(const void *chunk, size_t size, Error &error) return nbytes; } -static size_t -pipe_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) -{ - PipeOutput &po = *(PipeOutput *)ao; - - return po.Play(chunk, size, error); -} +typedef AudioOutputWrapper Wrapper; const struct AudioOutputPlugin pipe_output_plugin = { "pipe", nullptr, - pipe_output_init, - pipe_output_finish, + &Wrapper::Init, + &Wrapper::Finish, nullptr, nullptr, - pipe_output_open, - pipe_output_close, + &Wrapper::Open, + &Wrapper::Close, nullptr, nullptr, - pipe_output_play, + &Wrapper::Play, nullptr, nullptr, nullptr, diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx index 5a082538c..3a25ada2d 100644 --- a/src/output/plugins/RecorderOutputPlugin.cxx +++ b/src/output/plugins/RecorderOutputPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "RecorderOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "encoder/EncoderPlugin.hxx" #include "encoder/EncoderList.hxx" #include "config/ConfigError.hxx" @@ -213,16 +214,6 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &error) return true; } -static bool -recorder_output_open(AudioOutput *ao, - AudioFormat &audio_format, - Error &error) -{ - RecorderOutput &recorder = *(RecorderOutput *)ao; - - return recorder.Open(audio_format, error); -} - inline void RecorderOutput::Close() { @@ -238,14 +229,6 @@ RecorderOutput::Close() close(fd); } -static void -recorder_output_close(AudioOutput *ao) -{ - RecorderOutput &recorder = *(RecorderOutput *)ao; - - recorder.Close(); -} - inline void RecorderOutput::SendTag(const Tag &tag) { @@ -275,6 +258,8 @@ recorder_output_play(AudioOutput *ao, const void *chunk, size_t size, ? size : 0; } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin recorder_output_plugin = { "recorder", nullptr, @@ -282,8 +267,8 @@ const struct AudioOutputPlugin recorder_output_plugin = { recorder_output_finish, nullptr, nullptr, - recorder_output_open, - recorder_output_close, + &Wrapper::Open, + &Wrapper::Close, nullptr, recorder_output_send_tag, recorder_output_play, diff --git a/src/output/plugins/RoarOutputPlugin.cxx b/src/output/plugins/RoarOutputPlugin.cxx index 87a3f4e8f..d478d08e0 100644 --- a/src/output/plugins/RoarOutputPlugin.cxx +++ b/src/output/plugins/RoarOutputPlugin.cxx @@ -21,6 +21,7 @@ #include "config.h" #include "RoarOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "mixer/MixerList.hxx" #include "thread/Mutex.hxx" #include "util/Error.hxx" @@ -36,6 +37,8 @@ #undef new class RoarOutput { + friend struct AudioOutputWrapper; + AudioOutput base; std::string host, name; @@ -146,14 +149,6 @@ roar_init(const config_param ¶m, Error &error) return *self; } -static void -roar_finish(AudioOutput *ao) -{ - RoarOutput *self = (RoarOutput *)ao; - - delete self; -} - static void roar_use_audio_format(struct roar_audio_info *info, AudioFormat &audio_format) @@ -221,14 +216,6 @@ RoarOutput::Open(AudioFormat &audio_format, Error &error) return true; } -static bool -roar_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) -{ - RoarOutput *self = (RoarOutput *)ao; - - return self->Open(audio_format, error); -} - inline void RoarOutput::Close() { @@ -242,13 +229,6 @@ RoarOutput::Close() roar_disconnect(&con); } -static void -roar_close(AudioOutput *ao) -{ - RoarOutput *self = (RoarOutput *)ao; - self->Close(); -} - inline void RoarOutput::Cancel() { @@ -277,14 +257,6 @@ RoarOutput::Cancel() alive = true; } -static void -roar_cancel(AudioOutput *ao) -{ - RoarOutput *self = (RoarOutput *)ao; - - self->Cancel(); -} - inline size_t RoarOutput::Play(const void *chunk, size_t size, Error &error) { @@ -302,14 +274,6 @@ RoarOutput::Play(const void *chunk, size_t size, Error &error) return nbytes; } -static size_t -roar_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) -{ - RoarOutput *self = (RoarOutput *)ao; - return self->Play(chunk, size, error); -} - static const char* roar_tag_convert(TagType type, bool *is_uuid) { @@ -413,20 +377,22 @@ roar_send_tag(AudioOutput *ao, const Tag &meta) self->SendTag(meta); } +typedef AudioOutputWrapper Wrapper; + const struct AudioOutputPlugin roar_output_plugin = { "roar", nullptr, roar_init, - roar_finish, + &Wrapper::Finish, nullptr, nullptr, - roar_open, - roar_close, + &Wrapper::Open, + &Wrapper::Close, nullptr, roar_send_tag, - roar_play, + &Wrapper::Play, nullptr, - roar_cancel, + &Wrapper::Cancel, nullptr, &roar_mixer_plugin, }; diff --git a/src/output/plugins/sles/SlesOutputPlugin.cxx b/src/output/plugins/sles/SlesOutputPlugin.cxx index 85fd9f2f2..1d5b63b90 100644 --- a/src/output/plugins/sles/SlesOutputPlugin.cxx +++ b/src/output/plugins/sles/SlesOutputPlugin.cxx @@ -24,6 +24,7 @@ #include "Play.hxx" #include "AndroidSimpleBufferQueue.hxx" #include "../../OutputAPI.hxx" +#include "../../Wrapper.hxx" #include "util/Macros.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -34,6 +35,8 @@ #include class SlesOutput { + friend AudioOutputWrapper; + static constexpr unsigned N_BUFFERS = 3; static constexpr size_t BUFFER_SIZE = 65536; @@ -455,85 +458,22 @@ sles_output_init(const config_param ¶m, Error &error) return *sles; } -static void -sles_output_finish(AudioOutput *ao) -{ - SlesOutput *sles = (SlesOutput *)ao; - - delete sles; -} - -static bool -sles_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - return sles.Open(audio_format, error); -} - -static void -sles_output_close(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - sles.Close(); -} - -static unsigned -sles_output_delay(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - return sles.Delay(); -} - -static size_t -sles_output_play(AudioOutput *ao, const void *chunk, size_t size, - Error &error) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - return sles.Play(chunk, size, error); -} - -static void -sles_output_drain(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - sles.Drain(); -} - -static void -sles_output_cancel(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - sles.Cancel(); -} - -static bool -sles_output_pause(AudioOutput *ao) -{ - SlesOutput &sles = *(SlesOutput *)ao; - - return sles.Pause(); -} +typedef AudioOutputWrapper Wrapper; const struct AudioOutputPlugin sles_output_plugin = { "sles", sles_test_default_device, sles_output_init, - sles_output_finish, + &Wrapper::Finish, nullptr, nullptr, - sles_output_open, - sles_output_close, - sles_output_delay, + &Wrapper::Open, + &Wrapper::Close, + &Wrapper::Delay, nullptr, - sles_output_play, - sles_output_drain, - sles_output_cancel, - sles_output_pause, + &Wrapper::Play, + &Wrapper::Drain, + &Wrapper::Cancel, + &Wrapper::Pause, nullptr, }; -- cgit v1.2.3