InputStream: convert to class
This commit is contained in:
		| @@ -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 @@ | |||||||
|  |  | ||||||
| #include "check.h" | #include "check.h" | ||||||
|  |  | ||||||
| struct InputStream; | class InputStream; | ||||||
| struct tag_handler; | struct tag_handler; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -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 @@ | |||||||
| 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 @@ | |||||||
| #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) | |||||||
| 	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, | |||||||
| 	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) | |||||||
| { | { | ||||||
| 	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 @@ | |||||||
| #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) | |||||||
| 	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) | |||||||
| 	//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, | |||||||
| 		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 @@ | |||||||
| #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 @@ | |||||||
| #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 @@ | |||||||
|  |  | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
|  |  | ||||||
| struct InputStream; | class InputStream; | ||||||
| struct Decoder; | struct Decoder; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -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 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| struct config_param; | struct config_param; | ||||||
| struct InputStream; | class InputStream; | ||||||
| class Error; | class Error; | ||||||
| struct Tag; | struct Tag; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -92,6 +92,15 @@ InputStream::Update() | |||||||
| 		plugin.update(this); | 		plugin.update(this); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | InputStream::SetReady() | ||||||
|  | { | ||||||
|  | 	assert(!ready); | ||||||
|  |  | ||||||
|  | 	ready = true; | ||||||
|  | 	cond.broadcast(); | ||||||
|  | } | ||||||
|  |  | ||||||
| void | void | ||||||
| InputStream::WaitReady() | InputStream::WaitReady() | ||||||
| { | { | ||||||
|   | |||||||
| @@ -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 { | |||||||
| 	 */ | 	 */ | ||||||
| 	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 { | |||||||
| 	 */ | 	 */ | ||||||
| 	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 { | |||||||
| 	 */ | 	 */ | ||||||
| 	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 { | |||||||
| 	 */ | 	 */ | ||||||
| 	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(); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -168,6 +194,13 @@ struct InputStream { | |||||||
| 	 */ | 	 */ | ||||||
| 	void LockWaitReady(); | 	void LockWaitReady(); | ||||||
|  |  | ||||||
|  | 	gcc_pure | ||||||
|  | 	bool HasMimeType() const { | ||||||
|  | 		assert(ready); | ||||||
|  |  | ||||||
|  | 		return !mime.empty(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	gcc_pure | 	gcc_pure | ||||||
| 	const char *GetMimeType() const { | 	const char *GetMimeType() const { | ||||||
| 		assert(ready); | 		assert(ready); | ||||||
| @@ -175,6 +208,19 @@ struct InputStream { | |||||||
| 		return mime.empty() ? nullptr : mime.c_str(); | 		return mime.empty() ? nullptr : mime.c_str(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	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 | 	gcc_nonnull_all | ||||||
| 	void OverrideMimeType(const char *_mime) { | 	void OverrideMimeType(const char *_mime) { | ||||||
| 		assert(ready); | 		assert(ready); | ||||||
| @@ -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 @@ | |||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
| struct InputStream; | class InputStream; | ||||||
|  |  | ||||||
| class TextInputStream { | class TextInputStream { | ||||||
| 	InputStream &is; | 	InputStream &is; | ||||||
|   | |||||||
| @@ -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() | |||||||
| 		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() | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	base.mutex.unlock(); | 	Unlock(); | ||||||
|  |  | ||||||
| 	Close(); | 	Close(); | ||||||
| } | } | ||||||
| @@ -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: | |||||||
|  |  | ||||||
| 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: | |||||||
| 		/* 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, | |||||||
| 	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) | |||||||
| 				       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) | |||||||
| 	} 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) | |||||||
| 		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, | |||||||
| 		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 { | |||||||
| 		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 { | |||||||
| 		   - 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 { | |||||||
| 		 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) | |||||||
| 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 { | |||||||
| 	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 { | |||||||
|  |  | ||||||
| 		assert(dest != src); | 		assert(dest != src); | ||||||
|  |  | ||||||
| 		bool dest_ready = dest->ready; | 		if (!dest->IsReady() && src->IsReady()) { | ||||||
|  | 			if (src->HasMimeType()) | ||||||
|  | 				dest->SetMimeType(src->GetMimeType()); | ||||||
|  |  | ||||||
|  | 			dest->size = src->GetSize(); | ||||||
|  | 			dest->seekable = src->IsSeekable(); | ||||||
|  | 			dest->SetReady(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		dest->ready = src->ready; |  | ||||||
| 		dest->seekable = src->seekable; |  | ||||||
| 		dest->size = src->size; |  | ||||||
| 		dest->offset = src->offset; | 		dest->offset = src->offset; | ||||||
|  |  | ||||||
| 		if (!dest_ready && src->ready) |  | ||||||
| 			dest->mime = src->mime; |  | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -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) | |||||||
| 	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 @@ | |||||||
|  |  | ||||||
| #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 @@ | |||||||
|  |  | ||||||
| #include <expat.h> | #include <expat.h> | ||||||
|  |  | ||||||
| struct InputStream; | class InputStream; | ||||||
| class Error; | class Error; | ||||||
|  |  | ||||||
| class ExpatParser final { | class ExpatParser final { | ||||||
|   | |||||||
| @@ -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 @@ | |||||||
| #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 @@ | |||||||
| 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) | |||||||
|  |  | ||||||
| 	/* 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 */ | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann