aboutsummaryrefslogtreecommitdiffstats
path: root/src/output/plugins/FifoOutputPlugin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/output/plugins/FifoOutputPlugin.cxx')
-rw-r--r--src/output/plugins/FifoOutputPlugin.cxx150
1 files changed, 70 insertions, 80 deletions
diff --git a/src/output/plugins/FifoOutputPlugin.cxx b/src/output/plugins/FifoOutputPlugin.cxx
index 9df5a74dd..d4019df53 100644
--- a/src/output/plugins/FifoOutputPlugin.cxx
+++ b/src/output/plugins/FifoOutputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,9 +21,11 @@
#include "FifoOutputPlugin.hxx"
#include "config/ConfigError.hxx"
#include "../OutputAPI.hxx"
+#include "../Wrapper.hxx"
#include "../Timer.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/FileSystem.hxx"
+#include "fs/FileInfo.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
@@ -33,9 +35,9 @@
#include <errno.h>
#include <unistd.h>
-#define FIFO_BUFFER_SIZE 65536 /* pipe capacity on Linux >= 2.6.11 */
+class FifoOutput {
+ friend struct AudioOutputWrapper<FifoOutput>;
-struct FifoOutput {
AudioOutput base;
AllocatedPath path;
@@ -46,21 +48,35 @@ struct FifoOutput {
bool created;
Timer *timer;
+public:
FifoOutput()
:base(fifo_output_plugin),
path(AllocatedPath::Null()), input(-1), output(-1),
created(false) {}
- bool Initialize(const config_param &param, Error &error) {
- return base.Configure(param, error);
+ ~FifoOutput() {
+ CloseFifo();
}
+ bool Initialize(const ConfigBlock &block, Error &error) {
+ return base.Configure(block, error);
+ }
+
+ static FifoOutput *Create(const ConfigBlock &block, Error &error);
+
bool Create(Error &error);
bool Check(Error &error);
void Delete();
- bool Open(Error &error);
+ bool OpenFifo(Error &error);
+ void CloseFifo();
+
+ bool Open(AudioFormat &audio_format, Error &error);
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");
@@ -82,7 +98,7 @@ FifoOutput::Delete()
}
void
-FifoOutput::Close()
+FifoOutput::CloseFifo()
{
if (input >= 0) {
close(input);
@@ -94,8 +110,8 @@ FifoOutput::Close()
output = -1;
}
- struct stat st;
- if (created && StatFile(path, st))
+ FileInfo fi;
+ if (created && GetFileInfo(path, fi))
Delete();
}
@@ -138,7 +154,7 @@ FifoOutput::Check(Error &error)
}
inline bool
-FifoOutput::Open(Error &error)
+FifoOutput::OpenFifo(Error &error)
{
if (!Check(error))
return false;
@@ -147,7 +163,7 @@ FifoOutput::Open(Error &error)
if (input < 0) {
error.FormatErrno("Could not open FIFO \"%s\" for reading",
path_utf8.c_str());
- Close();
+ CloseFifo();
return false;
}
@@ -155,25 +171,19 @@ FifoOutput::Open(Error &error)
if (output < 0) {
error.FormatErrno("Could not open FIFO \"%s\" for writing",
path_utf8.c_str());
- Close();
+ CloseFifo();
return false;
}
return true;
}
-static bool
-fifo_open(FifoOutput *fd, Error &error)
-{
- return fd->Open(error);
-}
-
-static AudioOutput *
-fifo_output_init(const config_param &param, Error &error)
+inline FifoOutput *
+FifoOutput::Create(const ConfigBlock &block, Error &error)
{
FifoOutput *fd = new FifoOutput();
- fd->path = param.GetBlockPath("path", error);
+ fd->path = block.GetBlockPath("path", error);
if (fd->path.IsNull()) {
delete fd;
@@ -185,89 +195,67 @@ fifo_output_init(const config_param &param, Error &error)
fd->path_utf8 = fd->path.ToUTF8();
- if (!fd->Initialize(param, error)) {
+ if (!fd->Initialize(block, error)) {
delete fd;
return nullptr;
}
- if (!fifo_open(fd, error)) {
+ if (!fd->OpenFifo(error)) {
delete fd;
return nullptr;
}
- return &fd->base;
-}
-
-static void
-fifo_output_finish(AudioOutput *ao)
-{
- FifoOutput *fd = (FifoOutput *)ao;
-
- fd->Close();
- delete fd;
+ return fd;
}
-static bool
-fifo_output_open(AudioOutput *ao, AudioFormat &audio_format,
- gcc_unused Error &error)
+bool
+FifoOutput::Open(AudioFormat &audio_format, gcc_unused Error &error)
{
- FifoOutput *fd = (FifoOutput *)ao;
-
- fd->timer = new Timer(audio_format);
-
+ timer = new Timer(audio_format);
return true;
}
-static void
-fifo_output_close(AudioOutput *ao)
+void
+FifoOutput::Close()
{
- FifoOutput *fd = (FifoOutput *)ao;
-
- delete fd->timer;
+ delete timer;
}
-static void
-fifo_output_cancel(AudioOutput *ao)
+inline void
+FifoOutput::Cancel()
{
- FifoOutput *fd = (FifoOutput *)ao;
- char buf[FIFO_BUFFER_SIZE];
- int bytes = 1;
-
- fd->timer->Reset();
+ timer->Reset();
- while (bytes > 0 && errno != EINTR)
- bytes = read(fd->input, buf, FIFO_BUFFER_SIZE);
+ ssize_t bytes;
+ do {
+ char buffer[16384];
+ bytes = read(input, buffer, sizeof(buffer));
+ } while (bytes > 0 && errno != EINTR);
if (bytes < 0 && errno != EAGAIN) {
FormatErrno(fifo_output_domain,
"Flush of FIFO \"%s\" failed",
- fd->path_utf8.c_str());
+ path_utf8.c_str());
}
}
-static unsigned
-fifo_output_delay(AudioOutput *ao)
+inline unsigned
+FifoOutput::Delay() const
{
- FifoOutput *fd = (FifoOutput *)ao;
-
- return fd->timer->IsStarted()
- ? fd->timer->GetDelay()
+ return timer->IsStarted()
+ ? timer->GetDelay()
: 0;
}
-static size_t
-fifo_output_play(AudioOutput *ao, const void *chunk, size_t size,
- Error &error)
+inline size_t
+FifoOutput::Play(const void *chunk, size_t size, Error &error)
{
- FifoOutput *fd = (FifoOutput *)ao;
- ssize_t bytes;
-
- if (!fd->timer->IsStarted())
- fd->timer->Start();
- fd->timer->Add(size);
+ if (!timer->IsStarted())
+ timer->Start();
+ timer->Add(size);
while (true) {
- bytes = write(fd->output, chunk, size);
+ ssize_t bytes = write(output, chunk, size);
if (bytes > 0)
return (size_t)bytes;
@@ -275,33 +263,35 @@ fifo_output_play(AudioOutput *ao, const void *chunk, size_t size,
switch (errno) {
case EAGAIN:
/* The pipe is full, so empty it */
- fifo_output_cancel(&fd->base);
+ Cancel();
continue;
case EINTR:
continue;
}
error.FormatErrno("Failed to write to FIFO %s",
- fd->path_utf8.c_str());
+ path_utf8.c_str());
return 0;
}
}
}
+typedef AudioOutputWrapper<FifoOutput> Wrapper;
+
const struct AudioOutputPlugin fifo_output_plugin = {
"fifo",
nullptr,
- fifo_output_init,
- fifo_output_finish,
+ &Wrapper::Init,
+ &Wrapper::Finish,
nullptr,
nullptr,
- fifo_output_open,
- fifo_output_close,
- fifo_output_delay,
+ &Wrapper::Open,
+ &Wrapper::Close,
+ &Wrapper::Delay,
nullptr,
- fifo_output_play,
+ &Wrapper::Play,
nullptr,
- fifo_output_cancel,
+ &Wrapper::Cancel,
nullptr,
nullptr,
};