output/fifo: use template AudioOutputWrapper

This commit is contained in:
Max Kellermann 2015-01-28 19:43:37 +01:00
parent 593bb5a8a7
commit 8bfb88840b

View File

@ -21,6 +21,7 @@
#include "FifoOutputPlugin.hxx" #include "FifoOutputPlugin.hxx"
#include "config/ConfigError.hxx" #include "config/ConfigError.hxx"
#include "../OutputAPI.hxx" #include "../OutputAPI.hxx"
#include "../Wrapper.hxx"
#include "../Timer.hxx" #include "../Timer.hxx"
#include "fs/AllocatedPath.hxx" #include "fs/AllocatedPath.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
@ -51,16 +52,26 @@ struct FifoOutput {
path(AllocatedPath::Null()), input(-1), output(-1), path(AllocatedPath::Null()), input(-1), output(-1),
created(false) {} created(false) {}
~FifoOutput() {
Close();
}
bool Initialize(const ConfigBlock &block, Error &error) { bool Initialize(const ConfigBlock &block, Error &error) {
return base.Configure(block, error); return base.Configure(block, error);
} }
static FifoOutput *Create(const ConfigBlock &block, Error &error);
bool Create(Error &error); bool Create(Error &error);
bool Check(Error &error); bool Check(Error &error);
void Delete(); void Delete();
bool Open(Error &error); bool Open(Error &error);
void Close(); void Close();
unsigned Delay() const;
size_t Play(const void *chunk, size_t size, Error &error);
void Cancel();
}; };
static constexpr Domain fifo_output_domain("fifo_output"); static constexpr Domain fifo_output_domain("fifo_output");
@ -162,14 +173,8 @@ FifoOutput::Open(Error &error)
return true; return true;
} }
static bool inline FifoOutput *
fifo_open(FifoOutput *fd, Error &error) FifoOutput::Create(const ConfigBlock &block, Error &error)
{
return fd->Open(error);
}
static AudioOutput *
fifo_output_init(const ConfigBlock &block, Error &error)
{ {
FifoOutput *fd = new FifoOutput(); FifoOutput *fd = new FifoOutput();
@ -190,21 +195,12 @@ fifo_output_init(const ConfigBlock &block, Error &error)
return nullptr; return nullptr;
} }
if (!fifo_open(fd, error)) { if (!fd->Open(error)) {
delete fd; delete fd;
return nullptr; return nullptr;
} }
return &fd->base; return fd;
}
static void
fifo_output_finish(AudioOutput *ao)
{
FifoOutput *fd = (FifoOutput *)ao;
fd->Close();
delete fd;
} }
static bool static bool
@ -226,47 +222,41 @@ fifo_output_close(AudioOutput *ao)
delete fd->timer; delete fd->timer;
} }
static void inline void
fifo_output_cancel(AudioOutput *ao) FifoOutput::Cancel()
{ {
FifoOutput *fd = (FifoOutput *)ao;
char buf[FIFO_BUFFER_SIZE]; char buf[FIFO_BUFFER_SIZE];
int bytes = 1; int bytes = 1;
fd->timer->Reset(); timer->Reset();
while (bytes > 0 && errno != EINTR) while (bytes > 0 && errno != EINTR)
bytes = read(fd->input, buf, FIFO_BUFFER_SIZE); bytes = read(input, buf, FIFO_BUFFER_SIZE);
if (bytes < 0 && errno != EAGAIN) { if (bytes < 0 && errno != EAGAIN) {
FormatErrno(fifo_output_domain, FormatErrno(fifo_output_domain,
"Flush of FIFO \"%s\" failed", "Flush of FIFO \"%s\" failed",
fd->path_utf8.c_str()); path_utf8.c_str());
} }
} }
static unsigned inline unsigned
fifo_output_delay(AudioOutput *ao) FifoOutput::Delay() const
{ {
FifoOutput *fd = (FifoOutput *)ao; return timer->IsStarted()
? timer->GetDelay()
return fd->timer->IsStarted()
? fd->timer->GetDelay()
: 0; : 0;
} }
static size_t inline size_t
fifo_output_play(AudioOutput *ao, const void *chunk, size_t size, FifoOutput::Play(const void *chunk, size_t size, Error &error)
Error &error)
{ {
FifoOutput *fd = (FifoOutput *)ao; if (!timer->IsStarted())
timer->Start();
if (!fd->timer->IsStarted()) timer->Add(size);
fd->timer->Start();
fd->timer->Add(size);
while (true) { while (true) {
ssize_t bytes = write(fd->output, chunk, size); ssize_t bytes = write(output, chunk, size);
if (bytes > 0) if (bytes > 0)
return (size_t)bytes; return (size_t)bytes;
@ -274,33 +264,35 @@ fifo_output_play(AudioOutput *ao, const void *chunk, size_t size,
switch (errno) { switch (errno) {
case EAGAIN: case EAGAIN:
/* The pipe is full, so empty it */ /* The pipe is full, so empty it */
fifo_output_cancel(&fd->base); Cancel();
continue; continue;
case EINTR: case EINTR:
continue; continue;
} }
error.FormatErrno("Failed to write to FIFO %s", error.FormatErrno("Failed to write to FIFO %s",
fd->path_utf8.c_str()); path_utf8.c_str());
return 0; return 0;
} }
} }
} }
typedef AudioOutputWrapper<FifoOutput> Wrapper;
const struct AudioOutputPlugin fifo_output_plugin = { const struct AudioOutputPlugin fifo_output_plugin = {
"fifo", "fifo",
nullptr, nullptr,
fifo_output_init, &Wrapper::Init,
fifo_output_finish, &Wrapper::Finish,
nullptr, nullptr,
nullptr, nullptr,
fifo_output_open, fifo_output_open,
fifo_output_close, fifo_output_close,
fifo_output_delay, &Wrapper::Delay,
nullptr, nullptr,
fifo_output_play, &Wrapper::Play,
nullptr, nullptr,
fifo_output_cancel, &Wrapper::Cancel,
nullptr, nullptr,
nullptr, nullptr,
}; };