From fb9a2c5431daef40ae39d7c4884c3c7cc1b4b178 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 26 Dec 2017 19:43:29 +0100 Subject: [PATCH] input/Icy: manage the parser in a std::shared_ptr This resolves the circular dependency between IcyInputStream and CurlInputStream. --- src/input/IcyInputStream.cxx | 18 ++++++++++++++---- src/input/IcyInputStream.hxx | 22 ++++++++++++---------- src/input/plugins/CurlInputPlugin.cxx | 14 ++++++++------ 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/input/IcyInputStream.cxx b/src/input/IcyInputStream.cxx index cbdafb404..e097b74ef 100644 --- a/src/input/IcyInputStream.cxx +++ b/src/input/IcyInputStream.cxx @@ -19,15 +19,25 @@ #include "config.h" #include "IcyInputStream.hxx" +#include "IcyMetaDataParser.hxx" #include "tag/Tag.hxx" -IcyInputStream::IcyInputStream(InputStream *_input) noexcept - :ProxyInputStream(_input) +IcyInputStream::IcyInputStream(InputStream *_input, + std::shared_ptr _parser) noexcept + :ProxyInputStream(_input), parser(std::move(_parser)) { } IcyInputStream::~IcyInputStream() noexcept = default; +inline bool +IcyInputStream::IsEnabled() const noexcept +{ + assert(parser); + + return parser->IsDefined(); +} + void IcyInputStream::Update() noexcept { @@ -48,7 +58,7 @@ IcyInputStream::ReadTag() if (new_input_tag != nullptr) input_tag = std::move(new_input_tag); - auto new_icy_tag = parser.ReadTag(); + auto new_icy_tag = parser->ReadTag(); const bool had_new_icy_tag = !!new_icy_tag; if (new_icy_tag != nullptr) icy_tag = std::move(new_icy_tag); @@ -81,7 +91,7 @@ IcyInputStream::Read(void *ptr, size_t read_size) if (nbytes == 0) return 0; - size_t result = parser.ParseInPlace(ptr, nbytes); + size_t result = parser->ParseInPlace(ptr, nbytes); if (result > 0) { override_offset += result; offset = override_offset; diff --git a/src/input/IcyInputStream.hxx b/src/input/IcyInputStream.hxx index fdbdd54f8..dee61283a 100644 --- a/src/input/IcyInputStream.hxx +++ b/src/input/IcyInputStream.hxx @@ -21,18 +21,18 @@ #define MPD_ICY_INPUT_STREAM_HXX #include "ProxyInputStream.hxx" -#include "IcyMetaDataParser.hxx" #include "Compiler.h" #include struct Tag; +class IcyMetaDataParser; /** * An #InputStream filter that parses Icy metadata. */ class IcyInputStream final : public ProxyInputStream { - IcyMetaDataParser parser; + std::shared_ptr parser; /** * The #Tag object ready to be requested via ReadTag(). @@ -47,19 +47,21 @@ class IcyInputStream final : public ProxyInputStream { offset_type override_offset = 0; public: - IcyInputStream(InputStream *_input) noexcept; + /** + * @param _parser a IcyMetaDataParser instance which is shared + * with our input; it needs to be shared because our input + * needs to feed parameters (e.g. from the "icy-metaint" + * header) into it + */ + IcyInputStream(InputStream *_input, + std::shared_ptr _parser) noexcept; virtual ~IcyInputStream() noexcept; IcyInputStream(const IcyInputStream &) = delete; IcyInputStream &operator=(const IcyInputStream &) = delete; - void Enable(size_t _data_size) noexcept { - parser.Start(_data_size); - } - - bool IsEnabled() const noexcept { - return parser.IsDefined(); - } + gcc_pure + bool IsEnabled() const noexcept; /* virtual methods from InputStream */ void Update() noexcept override; diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index c6a62d286..0da44fff5 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -27,6 +27,7 @@ #include "lib/curl/Slist.hxx" #include "../AsyncInputStream.hxx" #include "../IcyInputStream.hxx" +#include "IcyMetaDataParser.hxx" #include "../InputPlugin.hxx" #include "config/ConfigGlobal.hxx" #include "config/Block.hxx" @@ -72,14 +73,14 @@ struct CurlInputStream final : public AsyncInputStream, CurlResponseHandler { CurlRequest *request = nullptr; /** parser for icy-metadata */ - IcyInputStream *icy; + std::shared_ptr icy; CurlInputStream(EventLoop &event_loop, const char *_url, Mutex &_mutex, Cond &_cond) :AsyncInputStream(event_loop, _url, _mutex, _cond, CURL_MAX_BUFFERED, CURL_RESUME_AT), - icy(new IcyInputStream(this)) { + icy(new IcyMetaDataParser()) { } ~CurlInputStream(); @@ -199,7 +200,7 @@ CurlInputStream::OnHeaders(unsigned status, return; } - if (!icy->IsEnabled() && + if (!icy->IsDefined() && headers.find("accept-ranges") != headers.end()) /* a stream with icy-metadata is not seekable */ seekable = true; @@ -226,7 +227,7 @@ CurlInputStream::OnHeaders(unsigned status, SetTag(tag_builder.CommitNew()); } - if (!icy->IsEnabled()) { + if (!icy->IsDefined()) { i = headers.find("icy-metaint"); if (i != headers.end()) { @@ -237,7 +238,7 @@ CurlInputStream::OnHeaders(unsigned status, #endif if (icy_metaint > 0) { - icy->Enable(icy_metaint); + icy->Start(icy_metaint); /* a stream with icy-metadata is not seekable */ @@ -450,7 +451,8 @@ CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond) throw; } - return c->icy; + auto icy = c->icy; + return new IcyInputStream(c, std::move(icy)); } static InputStream *