Commit 6773adc7 authored by Max Kellermann's avatar Max Kellermann

InputStream: convert to class

parent ee2afb35
...@@ -44,10 +44,10 @@ CheckDecoderPlugin(const DecoderPlugin &plugin, ...@@ -44,10 +44,10 @@ CheckDecoderPlugin(const DecoderPlugin &plugin,
bool bool
tag_stream_scan(InputStream &is, const tag_handler &handler, void *ctx) tag_stream_scan(InputStream &is, const tag_handler &handler, void *ctx)
{ {
assert(is.ready); assert(is.IsReady());
const char *const suffix = uri_get_suffix(is.uri.c_str()); const char *const suffix = uri_get_suffix(is.GetURI());
const char *const mime = is.mime.empty() ? nullptr : is.mime.c_str(); const char *const mime = is.GetMimeType();
if (suffix == nullptr && mime == nullptr) if (suffix == nullptr && mime == nullptr)
return false; return false;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "check.h" #include "check.h"
struct InputStream; class InputStream;
struct tag_handler; struct tag_handler;
/** /**
......
...@@ -25,7 +25,7 @@ class Cond; ...@@ -25,7 +25,7 @@ class Cond;
class Error; class Error;
struct ArchivePlugin; struct ArchivePlugin;
class ArchiveVisitor; class ArchiveVisitor;
struct InputStream; class InputStream;
class ArchiveFile { class ArchiveFile {
public: public:
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
struct DecoderBuffer; struct DecoderBuffer;
struct Decoder; struct Decoder;
struct InputStream; class InputStream;
template<typename T> struct ConstBuffer; template<typename T> struct ConstBuffer;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "Compiler.h" #include "Compiler.h"
struct config_param; struct config_param;
struct InputStream; class InputStream;
struct tag_handler; struct tag_handler;
class Path; class Path;
......
...@@ -87,7 +87,7 @@ decoder_input_stream_open(DecoderControl &dc, const char *uri) ...@@ -87,7 +87,7 @@ decoder_input_stream_open(DecoderControl &dc, const char *uri)
dc.Lock(); dc.Lock();
is->Update(); is->Update();
while (!is->ready && while (!is->IsReady() &&
dc.command != DecoderCommand::STOP) { dc.command != DecoderCommand::STOP) {
dc.Wait(); dc.Wait();
...@@ -114,7 +114,7 @@ decoder_stream_decode(const DecoderPlugin &plugin, ...@@ -114,7 +114,7 @@ decoder_stream_decode(const DecoderPlugin &plugin,
assert(plugin.stream_decode != nullptr); assert(plugin.stream_decode != nullptr);
assert(decoder.stream_tag == nullptr); assert(decoder.stream_tag == nullptr);
assert(decoder.decoder_tag == nullptr); assert(decoder.decoder_tag == nullptr);
assert(input_stream.ready); assert(input_stream.IsReady());
assert(decoder.dc.state == DecoderState::START); assert(decoder.dc.state == DecoderState::START);
FormatDebug(decoder_thread_domain, "probing plugin %s", plugin.name); FormatDebug(decoder_thread_domain, "probing plugin %s", plugin.name);
...@@ -179,7 +179,8 @@ decoder_check_plugin_mime(const DecoderPlugin &plugin, const InputStream &is) ...@@ -179,7 +179,8 @@ decoder_check_plugin_mime(const DecoderPlugin &plugin, const InputStream &is)
{ {
assert(plugin.stream_decode != nullptr); assert(plugin.stream_decode != nullptr);
return !is.mime.empty() && plugin.SupportsMimeType(is.mime.c_str()); const char *mime_type = is.GetMimeType();
return mime_type != nullptr && plugin.SupportsMimeType(mime_type);
} }
gcc_pure gcc_pure
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <stdint.h> #include <stdint.h>
struct Decoder; struct Decoder;
struct InputStream; class InputStream;
struct DsdId { struct DsdId {
char value[4]; char value[4];
......
...@@ -385,7 +385,7 @@ ffmpeg_probe(Decoder *decoder, InputStream &is) ...@@ -385,7 +385,7 @@ ffmpeg_probe(Decoder *decoder, InputStream &is)
AVProbeData avpd; AVProbeData avpd;
avpd.buf = buffer; avpd.buf = buffer;
avpd.buf_size = nbytes; avpd.buf_size = nbytes;
avpd.filename = is.uri.c_str(); avpd.filename = is.GetURI();
return av_probe_input_format(&avpd, true); return av_probe_input_format(&avpd, true);
} }
...@@ -409,7 +409,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) ...@@ -409,7 +409,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
//ffmpeg works with ours "fileops" helper //ffmpeg works with ours "fileops" helper
AVFormatContext *format_context = nullptr; AVFormatContext *format_context = nullptr;
if (mpd_ffmpeg_open_input(&format_context, stream.io, if (mpd_ffmpeg_open_input(&format_context, stream.io,
input.uri.c_str(), input.GetURI(),
input_format) != 0) { input_format) != 0) {
LogError(ffmpeg_domain, "Open failed"); LogError(ffmpeg_domain, "Open failed");
return; return;
...@@ -558,7 +558,7 @@ ffmpeg_scan_stream(InputStream &is, ...@@ -558,7 +558,7 @@ ffmpeg_scan_stream(InputStream &is,
return false; return false;
AVFormatContext *f = nullptr; AVFormatContext *f = nullptr;
if (mpd_ffmpeg_open_input(&f, stream.io, is.uri.c_str(), if (mpd_ffmpeg_open_input(&f, stream.io, is.GetURI(),
input_format) != 0) input_format) != 0)
return false; return false;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <FLAC/stream_decoder.h> #include <FLAC/stream_decoder.h>
struct Decoder; struct Decoder;
struct InputStream; class InputStream;
/** /**
* This class wraps an #InputStream in libFLAC stream decoder * This class wraps an #InputStream in libFLAC stream decoder
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define MPD_OGG_CODEC_HXX #define MPD_OGG_CODEC_HXX
struct Decoder; struct Decoder;
struct InputStream; class InputStream;
enum ogg_codec { enum ogg_codec {
OGG_CODEC_UNKNOWN, OGG_CODEC_UNKNOWN,
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <stddef.h> #include <stddef.h>
struct InputStream; class InputStream;
struct Decoder; struct Decoder;
/** /**
......
...@@ -487,7 +487,7 @@ wavpack_streamdecode(Decoder &decoder, InputStream &is) ...@@ -487,7 +487,7 @@ wavpack_streamdecode(Decoder &decoder, InputStream &is)
bool can_seek = is.seekable; bool can_seek = is.seekable;
wavpack_input isp_wvc; wavpack_input isp_wvc;
InputStream *is_wvc = wavpack_open_wvc(decoder, is.uri.c_str(), InputStream *is_wvc = wavpack_open_wvc(decoder, is.GetURI(),
is.mutex, is.cond, is.mutex, is.cond,
&isp_wvc); &isp_wvc);
if (is_wvc != nullptr) { if (is_wvc != nullptr) {
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#endif #endif
struct config_param; struct config_param;
struct InputStream; class InputStream;
class Error; class Error;
struct Tag; struct Tag;
......
...@@ -93,6 +93,15 @@ InputStream::Update() ...@@ -93,6 +93,15 @@ InputStream::Update()
} }
void void
InputStream::SetReady()
{
assert(!ready);
ready = true;
cond.broadcast();
}
void
InputStream::WaitReady() InputStream::WaitReady()
{ {
while (true) { while (true) {
......
...@@ -34,9 +34,11 @@ class Error; ...@@ -34,9 +34,11 @@ class Error;
struct Tag; struct Tag;
struct InputPlugin; struct InputPlugin;
struct InputStream { class InputStream {
public:
typedef int64_t offset_type; typedef int64_t offset_type;
private:
/** /**
* the plugin which implements this input stream * the plugin which implements this input stream
*/ */
...@@ -47,6 +49,7 @@ struct InputStream { ...@@ -47,6 +49,7 @@ struct InputStream {
*/ */
std::string uri; std::string uri;
public:
/** /**
* A mutex that protects the mutable attributes of this object * A mutex that protects the mutable attributes of this object
* and its implementation. It must be locked before calling * and its implementation. It must be locked before calling
...@@ -83,16 +86,19 @@ struct InputStream { ...@@ -83,16 +86,19 @@ struct InputStream {
*/ */
offset_type size; offset_type size;
public:
/** /**
* the current offset within the stream * the current offset within the stream
*/ */
offset_type offset; offset_type offset;
private:
/** /**
* the MIME content type of the resource, or empty if unknown. * the MIME content type of the resource, or empty if unknown.
*/ */
std::string mime; std::string mime;
public:
InputStream(const InputPlugin &_plugin, InputStream(const InputPlugin &_plugin,
const char *_uri, Mutex &_mutex, Cond &_cond) const char *_uri, Mutex &_mutex, Cond &_cond)
:plugin(_plugin), uri(_uri), :plugin(_plugin), uri(_uri),
...@@ -134,6 +140,19 @@ struct InputStream { ...@@ -134,6 +140,19 @@ struct InputStream {
*/ */
void Close(); void Close();
const InputPlugin &GetPlugin() const {
return plugin;
}
/**
* The absolute URI which was used to open this stream.
*
* No lock necessary for this method.
*/
const char *GetURI() const {
return uri.c_str();
}
void Lock() { void Lock() {
mutex.lock(); mutex.lock();
} }
...@@ -155,11 +174,18 @@ struct InputStream { ...@@ -155,11 +174,18 @@ struct InputStream {
*/ */
void Update(); void Update();
void SetReady();
/** /**
* Wait until the stream becomes ready. * Return whether the stream is ready for reading and whether
* the other attributes in this struct are valid.
* *
* The caller must lock the mutex. * The caller must lock the mutex.
*/ */
bool IsReady() const {
return ready;
}
void WaitReady(); void WaitReady();
/** /**
...@@ -169,6 +195,13 @@ struct InputStream { ...@@ -169,6 +195,13 @@ struct InputStream {
void LockWaitReady(); void LockWaitReady();
gcc_pure gcc_pure
bool HasMimeType() const {
assert(ready);
return !mime.empty();
}
gcc_pure
const char *GetMimeType() const { const char *GetMimeType() const {
assert(ready); assert(ready);
...@@ -176,6 +209,19 @@ struct InputStream { ...@@ -176,6 +209,19 @@ struct InputStream {
} }
gcc_nonnull_all gcc_nonnull_all
void SetMimeType(const char *_mime) {
assert(!ready);
mime = _mime;
}
void SetMimeType(std::string &&_mime) {
assert(!ready);
mime = std::move(_mime);
}
gcc_nonnull_all
void OverrideMimeType(const char *_mime) { void OverrideMimeType(const char *_mime) {
assert(ready); assert(ready);
...@@ -189,6 +235,14 @@ struct InputStream { ...@@ -189,6 +235,14 @@ struct InputStream {
return size; return size;
} }
void AddOffset(offset_type delta) {
assert(ready);
assert(offset >= 0);
assert(delta >= 0);
offset += delta;
}
gcc_pure gcc_pure
offset_type GetOffset() const { offset_type GetOffset() const {
assert(ready); assert(ready);
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <string> #include <string>
struct InputStream; class InputStream;
class TextInputStream { class TextInputStream {
InputStream &is; InputStream &is;
......
...@@ -58,18 +58,17 @@ ThreadInputStream::Start(Error &error) ...@@ -58,18 +58,17 @@ ThreadInputStream::Start(Error &error)
inline void inline void
ThreadInputStream::ThreadFunc() ThreadInputStream::ThreadFunc()
{ {
FormatThreadName("input:%s", base.plugin.name); FormatThreadName("input:%s", base.GetPlugin().name);
base.mutex.lock(); Lock();
if (!Open(postponed_error)) { if (!Open(postponed_error)) {
base.cond.broadcast(); base.cond.broadcast();
base.mutex.unlock(); Unlock();
return; return;
} }
/* we're ready, tell it to our client */ /* we're ready, tell it to our client */
base.ready = true; base.SetReady();
base.cond.broadcast();
while (!close) { while (!close) {
assert(!postponed_error.IsDefined()); assert(!postponed_error.IsDefined());
...@@ -78,12 +77,12 @@ ThreadInputStream::ThreadFunc() ...@@ -78,12 +77,12 @@ ThreadInputStream::ThreadFunc()
if (w.IsEmpty()) { if (w.IsEmpty()) {
wake_cond.wait(base.mutex); wake_cond.wait(base.mutex);
} else { } else {
base.mutex.unlock(); Unlock();
Error error; Error error;
size_t nbytes = Read(w.data, w.size, error); size_t nbytes = Read(w.data, w.size, error);
base.mutex.lock(); Lock();
base.cond.broadcast(); base.cond.broadcast();
if (nbytes == 0) { if (nbytes == 0) {
...@@ -96,7 +95,7 @@ ThreadInputStream::ThreadFunc() ...@@ -96,7 +95,7 @@ ThreadInputStream::ThreadFunc()
} }
} }
base.mutex.unlock(); Unlock();
Close(); Close();
} }
...@@ -173,10 +172,10 @@ ThreadInputStream::Read(InputStream *is, void *ptr, size_t size, ...@@ -173,10 +172,10 @@ ThreadInputStream::Read(InputStream *is, void *ptr, size_t size,
inline void inline void
ThreadInputStream::Close2() ThreadInputStream::Close2()
{ {
base.mutex.lock(); Lock();
close = true; close = true;
wake_cond.signal(); wake_cond.signal();
base.mutex.unlock(); Unlock();
Cancel(); Cancel();
......
...@@ -87,23 +87,23 @@ public: ...@@ -87,23 +87,23 @@ public:
protected: protected:
void Lock() { void Lock() {
base.mutex.lock(); base.Lock();
} }
void Unlock() { void Unlock() {
base.mutex.unlock(); base.Unlock();
} }
const char *GetURI() const { const char *GetURI() const {
assert(thread.IsInside()); assert(thread.IsInside());
return base.uri.c_str(); return base.GetURI();
} }
void SetMimeType(const char *mime) { void SetMimeType(const char *mime) {
assert(thread.IsInside()); assert(thread.IsInside());
base.mime = mime; base.SetMimeType(mime);
} }
/* to be implemented by the plugin */ /* to be implemented by the plugin */
......
...@@ -96,8 +96,9 @@ public: ...@@ -96,8 +96,9 @@ public:
/* this mime type forces use of the PcmDecoderPlugin. /* this mime type forces use of the PcmDecoderPlugin.
Needs to be generalised when/if that decoder is Needs to be generalised when/if that decoder is
updated to support other audio formats */ updated to support other audio formats */
base.mime = "audio/x-mpd-cdda-pcm"; base.SetMimeType("audio/x-mpd-cdda-pcm");
base.ready = true; base.SetReady();
frames_to_read = read_buffer_size / frame_size; frames_to_read = read_buffer_size / frame_size;
snd_pcm_start(capture_handle); snd_pcm_start(capture_handle);
......
...@@ -269,9 +269,9 @@ input_cdio_open(const char *uri, ...@@ -269,9 +269,9 @@ input_cdio_open(const char *uri,
i->base.size = (i->lsn_to - i->lsn_from + 1) * CDIO_CD_FRAMESIZE_RAW; i->base.size = (i->lsn_to - i->lsn_from + 1) * CDIO_CD_FRAMESIZE_RAW;
/* hack to make MPD select the "pcm" decoder plugin */ /* hack to make MPD select the "pcm" decoder plugin */
i->base.mime = reverse_endian i->base.SetMimeType(reverse_endian
? "audio/x-mpd-cdda-pcm-reverse" ? "audio/x-mpd-cdda-pcm-reverse"
: "audio/x-mpd-cdda-pcm"; : "audio/x-mpd-cdda-pcm");
return &i->base; return &i->base;
} }
......
...@@ -497,8 +497,7 @@ CurlInputStream::RequestDone(CURLcode result, long status) ...@@ -497,8 +497,7 @@ CurlInputStream::RequestDone(CURLcode result, long status)
status); status);
} }
base.ready = true; base.SetReady();
base.cond.broadcast();
} }
static void static void
...@@ -833,7 +832,7 @@ CurlInputStream::HeaderReceived(const char *name, std::string &&value) ...@@ -833,7 +832,7 @@ CurlInputStream::HeaderReceived(const char *name, std::string &&value)
} else if (StringEqualsCaseASCII(name, "content-length")) { } else if (StringEqualsCaseASCII(name, "content-length")) {
base.size = base.offset + ParseUint64(value.c_str()); base.size = base.offset + ParseUint64(value.c_str());
} else if (StringEqualsCaseASCII(name, "content-type")) { } else if (StringEqualsCaseASCII(name, "content-type")) {
base.mime = std::move(value); base.SetMimeType(std::move(value));
} else if (StringEqualsCaseASCII(name, "icy-name") || } else if (StringEqualsCaseASCII(name, "icy-name") ||
StringEqualsCaseASCII(name, "ice-name") || StringEqualsCaseASCII(name, "ice-name") ||
StringEqualsCaseASCII(name, "x-audiocast-name")) { StringEqualsCaseASCII(name, "x-audiocast-name")) {
...@@ -987,7 +986,7 @@ CurlInputStream::InitEasy(Error &error) ...@@ -987,7 +986,7 @@ CurlInputStream::InitEasy(Error &error)
curl_easy_setopt(easy, CURLOPT_PROXYUSERPWD, proxy_auth_str); curl_easy_setopt(easy, CURLOPT_PROXYUSERPWD, proxy_auth_str);
} }
CURLcode code = curl_easy_setopt(easy, CURLOPT_URL, base.uri.c_str()); CURLcode code = curl_easy_setopt(easy, CURLOPT_URL, base.GetURI());
if (code != CURLE_OK) { if (code != CURLE_OK) {
error.Format(curl_domain, code, error.Format(curl_domain, code,
"curl_easy_setopt() failed: %s", "curl_easy_setopt() failed: %s",
...@@ -1091,9 +1090,7 @@ CurlInputStream::Seek(InputPlugin::offset_type offset, int whence, ...@@ -1091,9 +1090,7 @@ CurlInputStream::Seek(InputPlugin::offset_type offset, int whence,
return false; return false;
base.mutex.lock(); base.mutex.lock();
base.WaitReady();
while (!base.ready)
base.cond.wait(base.mutex);
if (postponed_error.IsDefined()) { if (postponed_error.IsDefined()) {
error = std::move(postponed_error); error = std::move(postponed_error);
......
...@@ -58,8 +58,8 @@ class DespotifyInputStream { ...@@ -58,8 +58,8 @@ class DespotifyInputStream {
memset(&pcm, 0, sizeof(pcm)); memset(&pcm, 0, sizeof(pcm));
/* Despotify outputs pcm data */ /* Despotify outputs pcm data */
base.mime = "audio/x-mpd-cdda-pcm"; base.SetMimeType("audio/x-mpd-cdda-pcm");
base.ready = true; base.SetReady();
} }
public: public:
......
...@@ -52,7 +52,7 @@ struct FfmpegInputStream { ...@@ -52,7 +52,7 @@ struct FfmpegInputStream {
- since avio.h doesn't tell us the MIME type of the - since avio.h doesn't tell us the MIME type of the
resource, we can't select a decoder plugin, but the resource, we can't select a decoder plugin, but the
"ffmpeg" plugin is quite good at auto-detection */ "ffmpeg" plugin is quite good at auto-detection */
base.mime = "audio/x-mpd-ffmpeg"; base.SetMimeType("audio/x-mpd-ffmpeg");
} }
~FfmpegInputStream() { ~FfmpegInputStream() {
......
...@@ -44,7 +44,7 @@ struct FileInputStream { ...@@ -44,7 +44,7 @@ struct FileInputStream {
fd(_fd) { fd(_fd) {
base.size = size; base.size = size;
base.seekable = true; base.seekable = true;
base.ready = true; base.SetReady();
} }
~FileInputStream() { ~FileInputStream() {
...@@ -138,7 +138,7 @@ input_file_close(InputStream *is) ...@@ -138,7 +138,7 @@ input_file_close(InputStream *is)
static bool static bool
input_file_eof(InputStream *is) input_file_eof(InputStream *is)
{ {
return is->offset >= is->size; return is->GetOffset() >= is->GetSize();
} }
const InputPlugin input_plugin_file = { const InputPlugin input_plugin_file = {
......
...@@ -55,7 +55,7 @@ struct RewindInputStream { ...@@ -55,7 +55,7 @@ struct RewindInputStream {
char buffer[64 * 1024]; char buffer[64 * 1024];
RewindInputStream(InputStream *_input) RewindInputStream(InputStream *_input)
:base(rewind_input_plugin, _input->uri.c_str(), :base(rewind_input_plugin, _input->GetURI(),
_input->mutex, _input->cond), _input->mutex, _input->cond),
input(_input), tail(0) { input(_input), tail(0) {
} }
...@@ -84,15 +84,16 @@ struct RewindInputStream { ...@@ -84,15 +84,16 @@ struct RewindInputStream {
assert(dest != src); assert(dest != src);
bool dest_ready = dest->ready; if (!dest->IsReady() && src->IsReady()) {
if (src->HasMimeType())
dest->SetMimeType(src->GetMimeType());
dest->ready = src->ready; dest->size = src->GetSize();
dest->seekable = src->seekable; dest->seekable = src->IsSeekable();
dest->size = src->size; dest->SetReady();
dest->offset = src->offset; }
if (!dest_ready && src->ready) dest->offset = src->offset;
dest->mime = src->mime;
} }
}; };
...@@ -195,7 +196,7 @@ input_rewind_seek(InputStream *is, InputPlugin::offset_type offset, ...@@ -195,7 +196,7 @@ input_rewind_seek(InputStream *is, InputPlugin::offset_type offset,
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
assert(is->ready); assert(is->IsReady());
if (whence == SEEK_SET && r->tail > 0 && if (whence == SEEK_SET && r->tail > 0 &&
offset <= (InputPlugin::offset_type)r->tail) { offset <= (InputPlugin::offset_type)r->tail) {
...@@ -242,7 +243,7 @@ input_rewind_open(InputStream *is) ...@@ -242,7 +243,7 @@ input_rewind_open(InputStream *is)
assert(is != nullptr); assert(is != nullptr);
assert(is->offset == 0); assert(is->offset == 0);
if (is->seekable) if (is->IsReady() && is->IsSeekable())
/* seekable resources don't need this plugin */ /* seekable resources don't need this plugin */
return is; return is;
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "check.h" #include "check.h"
struct InputStream; class InputStream;
InputStream * InputStream *
input_rewind_open(InputStream *is); input_rewind_open(InputStream *is);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <expat.h> #include <expat.h>
struct InputStream; class InputStream;
class Error; class Error;
class ExpatParser final { class ExpatParser final {
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "SongEnumerator.hxx" #include "SongEnumerator.hxx"
#include "Compiler.h" #include "Compiler.h"
struct InputStream; class InputStream;
/** /**
* A #SongEnumerator wrapper that closes an #InputStream automatically * A #SongEnumerator wrapper that closes an #InputStream automatically
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#define MPD_PLAYLIST_PLUGIN_HXX #define MPD_PLAYLIST_PLUGIN_HXX
struct config_param; struct config_param;
struct InputStream; class InputStream;
struct Tag; struct Tag;
class Mutex; class Mutex;
class Cond; class Cond;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
class Mutex; class Mutex;
class Cond; class Cond;
class SongEnumerator; class SongEnumerator;
struct InputStream; class InputStream;
extern const struct playlist_plugin *const playlist_plugins[]; extern const struct playlist_plugin *const playlist_plugins[];
......
...@@ -52,8 +52,8 @@ dump_input_stream(InputStream *is) ...@@ -52,8 +52,8 @@ dump_input_stream(InputStream *is)
/* print meta data */ /* print meta data */
if (!is->mime.empty()) if (is->HasMimeType())
fprintf(stderr, "MIME type: %s\n", is->mime.c_str()); fprintf(stderr, "MIME type: %s\n", is->GetMimeType());
/* read data and tags from the stream */ /* read data and tags from the stream */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment