output/Wrapper: new helper class

This commit is contained in:
Max Kellermann 2014-12-29 23:45:14 +01:00
parent 977834179a
commit 0b9f650fe2
7 changed files with 160 additions and 256 deletions

View File

@ -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 \

93
src/output/Wrapper.hxx Normal file
View File

@ -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

View File

@ -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)
inline bool
JackOutput::Pause()
{
JackOutput &jo = *(JackOutput *)ao;
return jo.Play(chunk, size, error);
}
static bool
mpd_jack_pause(AudioOutput *ao)
{
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,
};

View File

@ -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,

View File

@ -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,

View File

@ -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;
@ -146,14 +149,6 @@ roar_init(const config_param &param, 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<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,
};

View File

@ -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,
};