input/Icy: manage the parser in a std::shared_ptr

This resolves the circular dependency between IcyInputStream and
CurlInputStream.
This commit is contained in:
Max Kellermann 2017-12-26 19:43:29 +01:00
parent cd38aa3b2a
commit fb9a2c5431
3 changed files with 34 additions and 20 deletions

View File

@ -19,15 +19,25 @@
#include "config.h" #include "config.h"
#include "IcyInputStream.hxx" #include "IcyInputStream.hxx"
#include "IcyMetaDataParser.hxx"
#include "tag/Tag.hxx" #include "tag/Tag.hxx"
IcyInputStream::IcyInputStream(InputStream *_input) noexcept IcyInputStream::IcyInputStream(InputStream *_input,
:ProxyInputStream(_input) std::shared_ptr<IcyMetaDataParser> _parser) noexcept
:ProxyInputStream(_input), parser(std::move(_parser))
{ {
} }
IcyInputStream::~IcyInputStream() noexcept = default; IcyInputStream::~IcyInputStream() noexcept = default;
inline bool
IcyInputStream::IsEnabled() const noexcept
{
assert(parser);
return parser->IsDefined();
}
void void
IcyInputStream::Update() noexcept IcyInputStream::Update() noexcept
{ {
@ -48,7 +58,7 @@ IcyInputStream::ReadTag()
if (new_input_tag != nullptr) if (new_input_tag != nullptr)
input_tag = std::move(new_input_tag); 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; const bool had_new_icy_tag = !!new_icy_tag;
if (new_icy_tag != nullptr) if (new_icy_tag != nullptr)
icy_tag = std::move(new_icy_tag); icy_tag = std::move(new_icy_tag);
@ -81,7 +91,7 @@ IcyInputStream::Read(void *ptr, size_t read_size)
if (nbytes == 0) if (nbytes == 0)
return 0; return 0;
size_t result = parser.ParseInPlace(ptr, nbytes); size_t result = parser->ParseInPlace(ptr, nbytes);
if (result > 0) { if (result > 0) {
override_offset += result; override_offset += result;
offset = override_offset; offset = override_offset;

View File

@ -21,18 +21,18 @@
#define MPD_ICY_INPUT_STREAM_HXX #define MPD_ICY_INPUT_STREAM_HXX
#include "ProxyInputStream.hxx" #include "ProxyInputStream.hxx"
#include "IcyMetaDataParser.hxx"
#include "Compiler.h" #include "Compiler.h"
#include <memory> #include <memory>
struct Tag; struct Tag;
class IcyMetaDataParser;
/** /**
* An #InputStream filter that parses Icy metadata. * An #InputStream filter that parses Icy metadata.
*/ */
class IcyInputStream final : public ProxyInputStream { class IcyInputStream final : public ProxyInputStream {
IcyMetaDataParser parser; std::shared_ptr<IcyMetaDataParser> parser;
/** /**
* The #Tag object ready to be requested via ReadTag(). * The #Tag object ready to be requested via ReadTag().
@ -47,19 +47,21 @@ class IcyInputStream final : public ProxyInputStream {
offset_type override_offset = 0; offset_type override_offset = 0;
public: 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<IcyMetaDataParser> _parser) noexcept;
virtual ~IcyInputStream() noexcept; virtual ~IcyInputStream() noexcept;
IcyInputStream(const IcyInputStream &) = delete; IcyInputStream(const IcyInputStream &) = delete;
IcyInputStream &operator=(const IcyInputStream &) = delete; IcyInputStream &operator=(const IcyInputStream &) = delete;
void Enable(size_t _data_size) noexcept { gcc_pure
parser.Start(_data_size); bool IsEnabled() const noexcept;
}
bool IsEnabled() const noexcept {
return parser.IsDefined();
}
/* virtual methods from InputStream */ /* virtual methods from InputStream */
void Update() noexcept override; void Update() noexcept override;

View File

@ -27,6 +27,7 @@
#include "lib/curl/Slist.hxx" #include "lib/curl/Slist.hxx"
#include "../AsyncInputStream.hxx" #include "../AsyncInputStream.hxx"
#include "../IcyInputStream.hxx" #include "../IcyInputStream.hxx"
#include "IcyMetaDataParser.hxx"
#include "../InputPlugin.hxx" #include "../InputPlugin.hxx"
#include "config/ConfigGlobal.hxx" #include "config/ConfigGlobal.hxx"
#include "config/Block.hxx" #include "config/Block.hxx"
@ -72,14 +73,14 @@ struct CurlInputStream final : public AsyncInputStream, CurlResponseHandler {
CurlRequest *request = nullptr; CurlRequest *request = nullptr;
/** parser for icy-metadata */ /** parser for icy-metadata */
IcyInputStream *icy; std::shared_ptr<IcyMetaDataParser> icy;
CurlInputStream(EventLoop &event_loop, const char *_url, CurlInputStream(EventLoop &event_loop, const char *_url,
Mutex &_mutex, Cond &_cond) Mutex &_mutex, Cond &_cond)
:AsyncInputStream(event_loop, _url, _mutex, _cond, :AsyncInputStream(event_loop, _url, _mutex, _cond,
CURL_MAX_BUFFERED, CURL_MAX_BUFFERED,
CURL_RESUME_AT), CURL_RESUME_AT),
icy(new IcyInputStream(this)) { icy(new IcyMetaDataParser()) {
} }
~CurlInputStream(); ~CurlInputStream();
@ -199,7 +200,7 @@ CurlInputStream::OnHeaders(unsigned status,
return; return;
} }
if (!icy->IsEnabled() && if (!icy->IsDefined() &&
headers.find("accept-ranges") != headers.end()) headers.find("accept-ranges") != headers.end())
/* a stream with icy-metadata is not seekable */ /* a stream with icy-metadata is not seekable */
seekable = true; seekable = true;
@ -226,7 +227,7 @@ CurlInputStream::OnHeaders(unsigned status,
SetTag(tag_builder.CommitNew()); SetTag(tag_builder.CommitNew());
} }
if (!icy->IsEnabled()) { if (!icy->IsDefined()) {
i = headers.find("icy-metaint"); i = headers.find("icy-metaint");
if (i != headers.end()) { if (i != headers.end()) {
@ -237,7 +238,7 @@ CurlInputStream::OnHeaders(unsigned status,
#endif #endif
if (icy_metaint > 0) { if (icy_metaint > 0) {
icy->Enable(icy_metaint); icy->Start(icy_metaint);
/* a stream with icy-metadata is not /* a stream with icy-metadata is not
seekable */ seekable */
@ -450,7 +451,8 @@ CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond)
throw; throw;
} }
return c->icy; auto icy = c->icy;
return new IcyInputStream(c, std::move(icy));
} }
static InputStream * static InputStream *