From 114fcee2ae897bd5dd740cb04a3f12b7ae60cb3f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 17 Nov 2016 22:21:36 +0100 Subject: decoder/Client: add virtual method Read() --- src/decoder/Bridge.cxx | 31 +++++++++++++++++++++++++++++++ src/decoder/Bridge.hxx | 1 + src/decoder/Client.hxx | 11 +++++++++++ src/decoder/DecoderAPI.cxx | 41 +++++++---------------------------------- test/FakeDecoderAPI.cxx | 40 ++-------------------------------------- test/FakeDecoderAPI.hxx | 1 + 6 files changed, 53 insertions(+), 72 deletions(-) diff --git a/src/decoder/Bridge.cxx b/src/decoder/Bridge.cxx index 314c067bf..25f169d41 100644 --- a/src/decoder/Bridge.cxx +++ b/src/decoder/Bridge.cxx @@ -401,6 +401,37 @@ DecoderBridge::OpenUri(const char *uri) } } +size_t +DecoderBridge::Read(InputStream &is, void *buffer, size_t length) +try { + assert(buffer != nullptr); + assert(dc.state == DecoderState::START || + dc.state == DecoderState::DECODE); + + if (length == 0) + return 0; + + ScopeLock lock(is.mutex); + + while (true) { + if (CheckCancelRead()) + return 0; + + if (is.IsAvailable()) + break; + + is.cond.wait(is.mutex); + } + + size_t nbytes = is.Read(buffer, length); + assert(nbytes > 0 || is.IsEOF()); + + return nbytes; +} catch (const std::runtime_error &e) { + error = std::current_exception(); + return 0; +} + void DecoderBridge::SubmitTimestamp(double t) { diff --git a/src/decoder/Bridge.hxx b/src/decoder/Bridge.hxx index 49d810633..7203ce28a 100644 --- a/src/decoder/Bridge.hxx +++ b/src/decoder/Bridge.hxx @@ -140,6 +140,7 @@ public: uint64_t GetSeekFrame() override; void SeekError() override; InputStreamPtr OpenUri(const char *uri) override; + size_t Read(InputStream &is, void *buffer, size_t length) override; void SubmitTimestamp(double t) override; DecoderCommand SubmitData(InputStream *is, const void *data, size_t length, diff --git a/src/decoder/Client.hxx b/src/decoder/Client.hxx index d77f2ed8e..b0e1af0e0 100644 --- a/src/decoder/Client.hxx +++ b/src/decoder/Client.hxx @@ -98,6 +98,17 @@ public: */ virtual InputStreamPtr OpenUri(const char *uri) = 0; + /** + * Blocking read from the input stream. + * + * @param is the input stream to read from + * @param buffer the destination buffer + * @param length the maximum number of bytes to read + * @return the number of bytes read, or 0 if one of the following + * occurs: end of file; error; command (like SEEK or STOP). + */ + virtual size_t Read(InputStream &is, void *buffer, size_t length) = 0; + /** * Sets the time stamp for the next data chunk [seconds]. The MPD * core automatically counts it up, and a decoder plugin only needs to diff --git a/src/decoder/DecoderAPI.cxx b/src/decoder/DecoderAPI.cxx index 6258b2a0a..1091690ce 100644 --- a/src/decoder/DecoderAPI.cxx +++ b/src/decoder/DecoderAPI.cxx @@ -19,8 +19,6 @@ #include "config.h" #include "DecoderAPI.hxx" -#include "DecoderControl.hxx" -#include "Bridge.hxx" #include "input/InputStream.hxx" #include "Log.hxx" @@ -30,44 +28,19 @@ size_t decoder_read(DecoderClient *client, InputStream &is, void *buffer, size_t length) -try { +{ assert(buffer != nullptr); /* XXX don't allow client==nullptr */ - if (client == nullptr) - return is.LockRead(buffer, length); - - auto &bridge = *(DecoderBridge *)client; - - assert(bridge.dc.state == DecoderState::START || - bridge.dc.state == DecoderState::DECODE); + if (client != nullptr) + return client->Read(is, buffer, length); - if (length == 0) + try { + return is.LockRead(buffer, length); + } catch (const std::runtime_error &e) { + LogError(e); return 0; - - ScopeLock lock(is.mutex); - - while (true) { - if (bridge.CheckCancelRead()) - return 0; - - if (is.IsAvailable()) - break; - - is.cond.wait(is.mutex); } - - size_t nbytes = is.Read(buffer, length); - assert(nbytes > 0 || is.IsEOF()); - - return nbytes; -} catch (const std::runtime_error &e) { - auto *bridge = (DecoderBridge *)client; - if (bridge != nullptr) - bridge->error = std::current_exception(); - else - LogError(e); - return 0; } bool diff --git a/test/FakeDecoderAPI.cxx b/test/FakeDecoderAPI.cxx index cd8d52cf2..9204835fe 100644 --- a/test/FakeDecoderAPI.cxx +++ b/test/FakeDecoderAPI.cxx @@ -80,51 +80,15 @@ FakeDecoder::OpenUri(const char *uri) } size_t -decoder_read(gcc_unused DecoderClient *client, - InputStream &is, - void *buffer, size_t length) +FakeDecoder::Read(InputStream &is, void *buffer, size_t length) { try { return is.LockRead(buffer, length); - } catch (const std::runtime_error &) { + } catch (const std::runtime_error &e) { return 0; } } -bool -decoder_read_full(DecoderClient *client, InputStream &is, - void *_buffer, size_t size) -{ - uint8_t *buffer = (uint8_t *)_buffer; - - while (size > 0) { - size_t nbytes = decoder_read(client, is, buffer, size); - if (nbytes == 0) - return false; - - buffer += nbytes; - size -= nbytes; - } - - return true; -} - -bool -decoder_skip(DecoderClient *client, InputStream &is, size_t size) -{ - while (size > 0) { - char buffer[1024]; - size_t nbytes = decoder_read(client, is, buffer, - std::min(sizeof(buffer), size)); - if (nbytes == 0) - return false; - - size -= nbytes; - } - - return true; -} - void FakeDecoder::SubmitTimestamp(gcc_unused double t) { diff --git a/test/FakeDecoderAPI.hxx b/test/FakeDecoderAPI.hxx index 5b9256a74..2850e9f9a 100644 --- a/test/FakeDecoderAPI.hxx +++ b/test/FakeDecoderAPI.hxx @@ -40,6 +40,7 @@ struct FakeDecoder final : DecoderClient { uint64_t GetSeekFrame() override; void SeekError() override; InputStreamPtr OpenUri(const char *uri) override; + size_t Read(InputStream &is, void *buffer, size_t length) override; void SubmitTimestamp(double t) override; DecoderCommand SubmitData(InputStream *is, const void *data, size_t length, -- cgit v1.2.3