aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-12-29 23:45:14 +0100
committerMax Kellermann <max@duempel.org>2014-12-29 23:45:14 +0100
commit0b9f650fe27bcb5ff78928b059c2e5032cfbcb97 (patch)
treea64e6c31716cfff9a39eae58f970a3b4bb31f929
parent977834179a790e8573eb8cd12252e0c160b69bd7 (diff)
downloadmpd-0b9f650fe27bcb5ff78928b059c2e5032cfbcb97.tar.gz
mpd-0b9f650fe27bcb5ff78928b059c2e5032cfbcb97.tar.xz
mpd-0b9f650fe27bcb5ff78928b059c2e5032cfbcb97.zip
output/Wrapper: new helper class
-rw-r--r--Makefile.am1
-rw-r--r--src/output/Wrapper.hxx93
-rw-r--r--src/output/plugins/JackOutputPlugin.cxx101
-rw-r--r--src/output/plugins/PipeOutputPlugin.cxx58
-rw-r--r--src/output/plugins/RecorderOutputPlugin.cxx25
-rw-r--r--src/output/plugins/RoarOutputPlugin.cxx54
-rw-r--r--src/output/plugins/sles/SlesOutputPlugin.cxx84
7 files changed, 160 insertions, 256 deletions
diff --git a/Makefile.am b/Makefile.am
index ad0d65427..d204c9947 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1236,6 +1236,7 @@ OUTPUT_LIBS = \
OUTPUT_API_SRC = \
src/output/OutputAPI.hxx \
src/output/Internal.hxx \
+ src/output/Wrapper.hxx \
src/output/Registry.cxx src/output/Registry.hxx \
src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx \
src/output/OutputThread.cxx \
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<class T>
+struct AudioOutputWrapper {
+ static T &Cast(AudioOutput &ao) {
+ return ContainerCast(ao, &T::base);
+ }
+
+ static AudioOutput *Init(const config_param &param, 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 &param, 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<JackOutput> 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 <stdio.h>
class PipeOutput {
+ friend AudioOutputWrapper<PipeOutput>;
+
AudioOutput base;
std::string cmd;
@@ -40,7 +43,7 @@ class PipeOutput {
bool Configure(const config_param &param, Error &error);
public:
- static AudioOutput *Create(const config_param &param, Error &error);
+ static PipeOutput *Create(const config_param &param, Error &error);
bool Open(AudioFormat &audio_format, Error &error);
@@ -70,7 +73,7 @@ PipeOutput::Configure(const config_param &param, Error &error)
return true;
}
-inline AudioOutput *
+inline PipeOutput *
PipeOutput::Create(const config_param &param, Error &error)
{
PipeOutput *po = new PipeOutput();
@@ -80,21 +83,7 @@ PipeOutput::Create(const config_param &param, Error &error)
return nullptr;
}
- return &po->base;
-}
-
-static AudioOutput *
-pipe_output_init(const config_param &param, 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<PipeOutput> 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<RecorderOutput> 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<RoarOutput>;
+
AudioOutput base;
std::string host, name;
@@ -147,14 +150,6 @@ roar_init(const config_param &param, Error &error)
}
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<RoarOutput> 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 <SLES/OpenSLES_Android.h>
class SlesOutput {
+ friend AudioOutputWrapper<SlesOutput>;
+
static constexpr unsigned N_BUFFERS = 3;
static constexpr size_t BUFFER_SIZE = 65536;
@@ -455,85 +458,22 @@ sles_output_init(const config_param &param, 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<SlesOutput> 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,
};