diff options
Diffstat (limited to 'src/output/plugins/FifoOutputPlugin.cxx')
-rw-r--r-- | src/output/plugins/FifoOutputPlugin.cxx | 150 |
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 ¶m, 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 ¶m, 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 ¶m, 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, }; |