output/fifo: migrate from class Error to C++ exceptions

This commit is contained in:
Max Kellermann 2016-11-05 15:13:14 +01:00
parent c8aa7afdc6
commit 543c5034af

View File

@ -19,15 +19,14 @@
#include "config.h" #include "config.h"
#include "FifoOutputPlugin.hxx" #include "FifoOutputPlugin.hxx"
#include "config/ConfigError.hxx"
#include "../OutputAPI.hxx" #include "../OutputAPI.hxx"
#include "../Wrapper.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"
#include "fs/FileInfo.hxx" #include "fs/FileInfo.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "util/RuntimeError.hxx"
#include "Log.hxx" #include "Log.hxx"
#include "open.h" #include "open.h"
@ -40,35 +39,28 @@ class FifoOutput {
AudioOutput base; AudioOutput base;
AllocatedPath path; const AllocatedPath path;
std::string path_utf8; std::string path_utf8;
int input; int input = -1;
int output; int output = -1;
bool created; bool created = false;
Timer *timer; Timer *timer;
public: public:
FifoOutput() FifoOutput(const ConfigBlock &block);
:base(fifo_output_plugin),
path(AllocatedPath::Null()), input(-1), output(-1),
created(false) {}
~FifoOutput() { ~FifoOutput() {
CloseFifo(); CloseFifo();
} }
bool Initialize(const ConfigBlock &block, Error &error) {
return base.Configure(block, error);
}
static FifoOutput *Create(const ConfigBlock &block, Error &error); static FifoOutput *Create(const ConfigBlock &block, Error &error);
bool Create(Error &error); void Create();
bool Check(Error &error); void Check();
void Delete(); void Delete();
bool OpenFifo(Error &error); void OpenFifo();
void CloseFifo(); void CloseFifo();
bool Open(AudioFormat &audio_format, Error &error); bool Open(AudioFormat &audio_format, Error &error);
@ -81,6 +73,18 @@ public:
static constexpr Domain fifo_output_domain("fifo_output"); static constexpr Domain fifo_output_domain("fifo_output");
FifoOutput::FifoOutput(const ConfigBlock &block)
:base(fifo_output_plugin, block),
path(block.GetPath("path"))
{
if (path.IsNull())
throw std::runtime_error("No \"path\" parameter specified");
path_utf8 = path.ToUTF8();
OpenFifo();
}
inline void inline void
FifoOutput::Delete() FifoOutput::Delete()
{ {
@ -115,93 +119,59 @@ FifoOutput::CloseFifo()
Delete(); Delete();
} }
inline bool inline void
FifoOutput::Create(Error &error) FifoOutput::Create()
{ {
if (!MakeFifo(path, 0666)) { if (!MakeFifo(path, 0666))
error.FormatErrno("Couldn't create FIFO \"%s\"", throw FormatErrno("Couldn't create FIFO \"%s\"",
path_utf8.c_str()); path_utf8.c_str());
return false;
}
created = true; created = true;
return true;
} }
inline bool inline void
FifoOutput::Check(Error &error) FifoOutput::Check()
{ {
struct stat st; struct stat st;
if (!StatFile(path, st)) { if (!StatFile(path, st)) {
if (errno == ENOENT) { if (errno == ENOENT) {
/* Path doesn't exist */ /* Path doesn't exist */
return Create(error); Create();
return;
} }
error.FormatErrno("Failed to stat FIFO \"%s\"", throw FormatErrno("Failed to stat FIFO \"%s\"",
path_utf8.c_str()); path_utf8.c_str());
return false;
} }
if (!S_ISFIFO(st.st_mode)) { if (!S_ISFIFO(st.st_mode))
error.Format(fifo_output_domain, throw FormatRuntimeError("\"%s\" already exists, but is not a FIFO",
"\"%s\" already exists, but is not a FIFO", path_utf8.c_str());
path_utf8.c_str());
return false;
}
return true;
} }
inline bool inline void
FifoOutput::OpenFifo(Error &error) FifoOutput::OpenFifo()
{ try {
if (!Check(error)) Check();
return false;
input = OpenFile(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0); input = OpenFile(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0);
if (input < 0) { if (input < 0)
error.FormatErrno("Could not open FIFO \"%s\" for reading", throw FormatErrno("Could not open FIFO \"%s\" for reading",
path_utf8.c_str()); path_utf8.c_str());
CloseFifo();
return false;
}
output = OpenFile(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0); output = OpenFile(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0);
if (output < 0) { if (output < 0)
error.FormatErrno("Could not open FIFO \"%s\" for writing", throw FormatErrno("Could not open FIFO \"%s\" for writing",
path_utf8.c_str()); path_utf8.c_str());
CloseFifo(); } catch (...) {
return false; CloseFifo();
} throw;
return true;
} }
inline FifoOutput * inline FifoOutput *
FifoOutput::Create(const ConfigBlock &block, Error &error) FifoOutput::Create(const ConfigBlock &block, Error &)
{ {
FifoOutput *fd = new FifoOutput(); return new FifoOutput(block);
fd->path = block.GetPath("path");
if (fd->path.IsNull()) {
delete fd;
throw std::runtime_error("No \"path\" parameter specified");
}
fd->path_utf8 = fd->path.ToUTF8();
if (!fd->Initialize(block, error)) {
delete fd;
return nullptr;
}
if (!fd->OpenFifo(error)) {
delete fd;
return nullptr;
}
return fd;
} }
bool bool
@ -244,7 +214,7 @@ FifoOutput::Delay() const
} }
inline size_t inline size_t
FifoOutput::Play(const void *chunk, size_t size, Error &error) FifoOutput::Play(const void *chunk, size_t size, Error &)
{ {
if (!timer->IsStarted()) if (!timer->IsStarted())
timer->Start(); timer->Start();
@ -265,9 +235,8 @@ FifoOutput::Play(const void *chunk, size_t size, Error &error)
continue; continue;
} }
error.FormatErrno("Failed to write to FIFO %s", throw FormatErrno("Failed to write to FIFO %s",
path_utf8.c_str()); path_utf8.c_str());
return 0;
} }
} }
} }