diff options
31 files changed, 132 insertions, 70 deletions
diff --git a/src/TagStream.cxx b/src/TagStream.cxx index b84166825..98cbe193b 100644 --- a/src/TagStream.cxx +++ b/src/TagStream.cxx @@ -44,10 +44,10 @@ CheckDecoderPlugin(const DecoderPlugin &plugin, bool 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 mime = is.mime.empty() ? nullptr : is.mime.c_str(); + const char *const suffix = uri_get_suffix(is.GetURI()); + const char *const mime = is.GetMimeType(); if (suffix == nullptr && mime == nullptr) return false; diff --git a/src/TagStream.hxx b/src/TagStream.hxx index 2f93768ee..71dd71ff7 100644 --- a/src/TagStream.hxx +++ b/src/TagStream.hxx @@ -22,7 +22,7 @@ #include "check.h" -struct InputStream; +class InputStream; struct tag_handler; /** diff --git a/src/archive/ArchiveFile.hxx b/src/archive/ArchiveFile.hxx index 7d6c9e17c..473eef70b 100644 --- a/src/archive/ArchiveFile.hxx +++ b/src/archive/ArchiveFile.hxx @@ -25,7 +25,7 @@ class Cond; class Error; struct ArchivePlugin; class ArchiveVisitor; -struct InputStream; +class InputStream; class ArchiveFile { public: diff --git a/src/decoder/DecoderBuffer.hxx b/src/decoder/DecoderBuffer.hxx index 4cadd7740..d6f303c36 100644 --- a/src/decoder/DecoderBuffer.hxx +++ b/src/decoder/DecoderBuffer.hxx @@ -32,7 +32,7 @@ struct DecoderBuffer; struct Decoder; -struct InputStream; +class InputStream; template<typename T> struct ConstBuffer; diff --git a/src/decoder/DecoderPlugin.hxx b/src/decoder/DecoderPlugin.hxx index fd255ffb8..dbf3db9aa 100644 --- a/src/decoder/DecoderPlugin.hxx +++ b/src/decoder/DecoderPlugin.hxx @@ -23,7 +23,7 @@ #include "Compiler.h" struct config_param; -struct InputStream; +class InputStream; struct tag_handler; class Path; diff --git a/src/decoder/DecoderThread.cxx b/src/decoder/DecoderThread.cxx index 37b45bd24..4dd3c215c 100644 --- a/src/decoder/DecoderThread.cxx +++ b/src/decoder/DecoderThread.cxx @@ -87,7 +87,7 @@ decoder_input_stream_open(DecoderControl &dc, const char *uri) dc.Lock(); is->Update(); - while (!is->ready && + while (!is->IsReady() && dc.command != DecoderCommand::STOP) { dc.Wait(); @@ -114,7 +114,7 @@ decoder_stream_decode(const DecoderPlugin &plugin, assert(plugin.stream_decode != nullptr); assert(decoder.stream_tag == nullptr); assert(decoder.decoder_tag == nullptr); - assert(input_stream.ready); + assert(input_stream.IsReady()); assert(decoder.dc.state == DecoderState::START); 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); - 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 diff --git a/src/decoder/plugins/DsdLib.hxx b/src/decoder/plugins/DsdLib.hxx index 4c5e83114..88a76d72a 100644 --- a/src/decoder/plugins/DsdLib.hxx +++ b/src/decoder/plugins/DsdLib.hxx @@ -27,7 +27,7 @@ #include <stdint.h> struct Decoder; -struct InputStream; +class InputStream; struct DsdId { char value[4]; diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx index 6310ea7fe..3a0fa7389 100644 --- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx +++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx @@ -385,7 +385,7 @@ ffmpeg_probe(Decoder *decoder, InputStream &is) AVProbeData avpd; avpd.buf = buffer; avpd.buf_size = nbytes; - avpd.filename = is.uri.c_str(); + avpd.filename = is.GetURI(); return av_probe_input_format(&avpd, true); } @@ -409,7 +409,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) //ffmpeg works with ours "fileops" helper AVFormatContext *format_context = nullptr; if (mpd_ffmpeg_open_input(&format_context, stream.io, - input.uri.c_str(), + input.GetURI(), input_format) != 0) { LogError(ffmpeg_domain, "Open failed"); return; @@ -558,7 +558,7 @@ ffmpeg_scan_stream(InputStream &is, return false; 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) return false; diff --git a/src/decoder/plugins/FlacInput.hxx b/src/decoder/plugins/FlacInput.hxx index 30ed55fd0..427abccb4 100644 --- a/src/decoder/plugins/FlacInput.hxx +++ b/src/decoder/plugins/FlacInput.hxx @@ -23,7 +23,7 @@ #include <FLAC/stream_decoder.h> struct Decoder; -struct InputStream; +class InputStream; /** * This class wraps an #InputStream in libFLAC stream decoder diff --git a/src/decoder/plugins/OggCodec.hxx b/src/decoder/plugins/OggCodec.hxx index 6643d85ad..3b096561c 100644 --- a/src/decoder/plugins/OggCodec.hxx +++ b/src/decoder/plugins/OggCodec.hxx @@ -25,7 +25,7 @@ #define MPD_OGG_CODEC_HXX struct Decoder; -struct InputStream; +class InputStream; enum ogg_codec { OGG_CODEC_UNKNOWN, diff --git a/src/decoder/plugins/OggUtil.hxx b/src/decoder/plugins/OggUtil.hxx index 3289702a3..94c380ef4 100644 --- a/src/decoder/plugins/OggUtil.hxx +++ b/src/decoder/plugins/OggUtil.hxx @@ -26,7 +26,7 @@ #include <stddef.h> -struct InputStream; +class InputStream; struct Decoder; /** diff --git a/src/decoder/plugins/WavpackDecoderPlugin.cxx b/src/decoder/plugins/WavpackDecoderPlugin.cxx index 27bede56c..070a913f2 100644 --- a/src/decoder/plugins/WavpackDecoderPlugin.cxx +++ b/src/decoder/plugins/WavpackDecoderPlugin.cxx @@ -487,7 +487,7 @@ wavpack_streamdecode(Decoder &decoder, InputStream &is) bool can_seek = is.seekable; 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, &isp_wvc); if (is_wvc != nullptr) { diff --git a/src/input/InputPlugin.hxx b/src/input/InputPlugin.hxx index 090c73df8..412ca4cf9 100644 --- a/src/input/InputPlugin.hxx +++ b/src/input/InputPlugin.hxx @@ -35,7 +35,7 @@ #endif struct config_param; -struct InputStream; +class InputStream; class Error; struct Tag; diff --git a/src/input/InputStream.cxx b/src/input/InputStream.cxx index 0621437c4..d54eca643 100644 --- a/src/input/InputStream.cxx +++ b/src/input/InputStream.cxx @@ -93,6 +93,15 @@ InputStream::Update() } void +InputStream::SetReady() +{ + assert(!ready); + + ready = true; + cond.broadcast(); +} + +void InputStream::WaitReady() { while (true) { diff --git a/src/input/InputStream.hxx b/src/input/InputStream.hxx index c66091687..65840ba27 100644 --- a/src/input/InputStream.hxx +++ b/src/input/InputStream.hxx @@ -34,9 +34,11 @@ class Error; struct Tag; struct InputPlugin; -struct InputStream { +class InputStream { +public: typedef int64_t offset_type; +private: /** * the plugin which implements this input stream */ @@ -47,6 +49,7 @@ struct InputStream { */ std::string uri; +public: /** * A mutex that protects the mutable attributes of this object * and its implementation. It must be locked before calling @@ -83,16 +86,19 @@ struct InputStream { */ offset_type size; +public: /** * the current offset within the stream */ offset_type offset; +private: /** * the MIME content type of the resource, or empty if unknown. */ std::string mime; +public: InputStream(const InputPlugin &_plugin, const char *_uri, Mutex &_mutex, Cond &_cond) :plugin(_plugin), uri(_uri), @@ -134,6 +140,19 @@ struct InputStream { */ 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() { mutex.lock(); } @@ -155,11 +174,18 @@ struct InputStream { */ 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. */ + bool IsReady() const { + return ready; + } + void WaitReady(); /** @@ -169,6 +195,13 @@ struct InputStream { void LockWaitReady(); gcc_pure + bool HasMimeType() const { + assert(ready); + + return !mime.empty(); + } + + gcc_pure const char *GetMimeType() const { assert(ready); @@ -176,6 +209,19 @@ struct InputStream { } 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) { assert(ready); @@ -189,6 +235,14 @@ struct InputStream { return size; } + void AddOffset(offset_type delta) { + assert(ready); + assert(offset >= 0); + assert(delta >= 0); + + offset += delta; + } + gcc_pure offset_type GetOffset() const { assert(ready); diff --git a/src/input/TextInputStream.hxx b/src/input/TextInputStream.hxx index 86ae16e41..c67423da1 100644 --- a/src/input/TextInputStream.hxx +++ b/src/input/TextInputStream.hxx @@ -24,7 +24,7 @@ #include <string> -struct InputStream; +class InputStream; class TextInputStream { InputStream &is; diff --git a/src/input/ThreadInputStream.cxx b/src/input/ThreadInputStream.cxx index 5271171ef..fde9bd08e 100644 --- a/src/input/ThreadInputStream.cxx +++ b/src/input/ThreadInputStream.cxx @@ -58,18 +58,17 @@ ThreadInputStream::Start(Error &error) inline void ThreadInputStream::ThreadFunc() { - FormatThreadName("input:%s", base.plugin.name); + FormatThreadName("input:%s", base.GetPlugin().name); - base.mutex.lock(); + Lock(); if (!Open(postponed_error)) { base.cond.broadcast(); - base.mutex.unlock(); + Unlock(); return; } /* we're ready, tell it to our client */ - base.ready = true; - base.cond.broadcast(); + base.SetReady(); while (!close) { assert(!postponed_error.IsDefined()); @@ -78,12 +77,12 @@ ThreadInputStream::ThreadFunc() if (w.IsEmpty()) { wake_cond.wait(base.mutex); } else { - base.mutex.unlock(); + Unlock(); Error error; size_t nbytes = Read(w.data, w.size, error); - base.mutex.lock(); + Lock(); base.cond.broadcast(); if (nbytes == 0) { @@ -96,7 +95,7 @@ ThreadInputStream::ThreadFunc() } } - base.mutex.unlock(); + Unlock(); Close(); } @@ -173,10 +172,10 @@ ThreadInputStream::Read(InputStream *is, void *ptr, size_t size, inline void ThreadInputStream::Close2() { - base.mutex.lock(); + Lock(); close = true; wake_cond.signal(); - base.mutex.unlock(); + Unlock(); Cancel(); diff --git a/src/input/ThreadInputStream.hxx b/src/input/ThreadInputStream.hxx index 01428d717..8bae93a05 100644 --- a/src/input/ThreadInputStream.hxx +++ b/src/input/ThreadInputStream.hxx @@ -87,23 +87,23 @@ public: protected: void Lock() { - base.mutex.lock(); + base.Lock(); } void Unlock() { - base.mutex.unlock(); + base.Unlock(); } const char *GetURI() const { assert(thread.IsInside()); - return base.uri.c_str(); + return base.GetURI(); } void SetMimeType(const char *mime) { assert(thread.IsInside()); - base.mime = mime; + base.SetMimeType(mime); } /* to be implemented by the plugin */ diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx index eae06ba6c..129219c01 100644 --- a/src/input/plugins/AlsaInputPlugin.cxx +++ b/src/input/plugins/AlsaInputPlugin.cxx @@ -96,8 +96,9 @@ public: /* this mime type forces use of the PcmDecoderPlugin. Needs to be generalised when/if that decoder is updated to support other audio formats */ - base.mime = "audio/x-mpd-cdda-pcm"; - base.ready = true; + base.SetMimeType("audio/x-mpd-cdda-pcm"); + base.SetReady(); + frames_to_read = read_buffer_size / frame_size; snd_pcm_start(capture_handle); diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx index 767b2600f..5b4ce2ec6 100644 --- a/src/input/plugins/CdioParanoiaInputPlugin.cxx +++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx @@ -269,9 +269,9 @@ input_cdio_open(const char *uri, i->base.size = (i->lsn_to - i->lsn_from + 1) * CDIO_CD_FRAMESIZE_RAW; /* hack to make MPD select the "pcm" decoder plugin */ - i->base.mime = reverse_endian - ? "audio/x-mpd-cdda-pcm-reverse" - : "audio/x-mpd-cdda-pcm"; + i->base.SetMimeType(reverse_endian + ? "audio/x-mpd-cdda-pcm-reverse" + : "audio/x-mpd-cdda-pcm"); return &i->base; } diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index 37509e998..5f8b9150a 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -497,8 +497,7 @@ CurlInputStream::RequestDone(CURLcode result, long status) status); } - base.ready = true; - base.cond.broadcast(); + base.SetReady(); } static void @@ -833,7 +832,7 @@ CurlInputStream::HeaderReceived(const char *name, std::string &&value) } else if (StringEqualsCaseASCII(name, "content-length")) { base.size = base.offset + ParseUint64(value.c_str()); } else if (StringEqualsCaseASCII(name, "content-type")) { - base.mime = std::move(value); + base.SetMimeType(std::move(value)); } else if (StringEqualsCaseASCII(name, "icy-name") || StringEqualsCaseASCII(name, "ice-name") || StringEqualsCaseASCII(name, "x-audiocast-name")) { @@ -987,7 +986,7 @@ CurlInputStream::InitEasy(Error &error) 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) { error.Format(curl_domain, code, "curl_easy_setopt() failed: %s", @@ -1091,9 +1090,7 @@ CurlInputStream::Seek(InputPlugin::offset_type offset, int whence, return false; base.mutex.lock(); - - while (!base.ready) - base.cond.wait(base.mutex); + base.WaitReady(); if (postponed_error.IsDefined()) { error = std::move(postponed_error); diff --git a/src/input/plugins/DespotifyInputPlugin.cxx b/src/input/plugins/DespotifyInputPlugin.cxx index 152fda95f..702ebc132 100644 --- a/src/input/plugins/DespotifyInputPlugin.cxx +++ b/src/input/plugins/DespotifyInputPlugin.cxx @@ -58,8 +58,8 @@ class DespotifyInputStream { memset(&pcm, 0, sizeof(pcm)); /* Despotify outputs pcm data */ - base.mime = "audio/x-mpd-cdda-pcm"; - base.ready = true; + base.SetMimeType("audio/x-mpd-cdda-pcm"); + base.SetReady(); } public: diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx index dab4b59fb..d06d4705a 100644 --- a/src/input/plugins/FfmpegInputPlugin.cxx +++ b/src/input/plugins/FfmpegInputPlugin.cxx @@ -52,7 +52,7 @@ struct FfmpegInputStream { - since avio.h doesn't tell us the MIME type of the resource, we can't select a decoder plugin, but the "ffmpeg" plugin is quite good at auto-detection */ - base.mime = "audio/x-mpd-ffmpeg"; + base.SetMimeType("audio/x-mpd-ffmpeg"); } ~FfmpegInputStream() { diff --git a/src/input/plugins/FileInputPlugin.cxx b/src/input/plugins/FileInputPlugin.cxx index 780e93263..49dc3df7e 100644 --- a/src/input/plugins/FileInputPlugin.cxx +++ b/src/input/plugins/FileInputPlugin.cxx @@ -44,7 +44,7 @@ struct FileInputStream { fd(_fd) { base.size = size; base.seekable = true; - base.ready = true; + base.SetReady(); } ~FileInputStream() { @@ -138,7 +138,7 @@ input_file_close(InputStream *is) static bool input_file_eof(InputStream *is) { - return is->offset >= is->size; + return is->GetOffset() >= is->GetSize(); } const InputPlugin input_plugin_file = { diff --git a/src/input/plugins/RewindInputPlugin.cxx b/src/input/plugins/RewindInputPlugin.cxx index 1a930ac53..1cc146d3f 100644 --- a/src/input/plugins/RewindInputPlugin.cxx +++ b/src/input/plugins/RewindInputPlugin.cxx @@ -55,7 +55,7 @@ struct RewindInputStream { char buffer[64 * 1024]; RewindInputStream(InputStream *_input) - :base(rewind_input_plugin, _input->uri.c_str(), + :base(rewind_input_plugin, _input->GetURI(), _input->mutex, _input->cond), input(_input), tail(0) { } @@ -84,15 +84,16 @@ struct RewindInputStream { 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->seekable = src->seekable; - dest->size = src->size; - dest->offset = src->offset; + dest->size = src->GetSize(); + dest->seekable = src->IsSeekable(); + dest->SetReady(); + } - if (!dest_ready && src->ready) - dest->mime = src->mime; + dest->offset = src->offset; } }; @@ -195,7 +196,7 @@ input_rewind_seek(InputStream *is, InputPlugin::offset_type offset, { RewindInputStream *r = (RewindInputStream *)is; - assert(is->ready); + assert(is->IsReady()); if (whence == SEEK_SET && r->tail > 0 && offset <= (InputPlugin::offset_type)r->tail) { @@ -242,7 +243,7 @@ input_rewind_open(InputStream *is) assert(is != nullptr); assert(is->offset == 0); - if (is->seekable) + if (is->IsReady() && is->IsSeekable()) /* seekable resources don't need this plugin */ return is; diff --git a/src/input/plugins/RewindInputPlugin.hxx b/src/input/plugins/RewindInputPlugin.hxx index f19705154..56b01b585 100644 --- a/src/input/plugins/RewindInputPlugin.hxx +++ b/src/input/plugins/RewindInputPlugin.hxx @@ -29,7 +29,7 @@ #include "check.h" -struct InputStream; +class InputStream; InputStream * input_rewind_open(InputStream *is); diff --git a/src/lib/expat/ExpatParser.hxx b/src/lib/expat/ExpatParser.hxx index d57a85533..9d2ac65e5 100644 --- a/src/lib/expat/ExpatParser.hxx +++ b/src/lib/expat/ExpatParser.hxx @@ -25,7 +25,7 @@ #include <expat.h> -struct InputStream; +class InputStream; class Error; class ExpatParser final { diff --git a/src/playlist/CloseSongEnumerator.hxx b/src/playlist/CloseSongEnumerator.hxx index 5a95cc28b..17f015394 100644 --- a/src/playlist/CloseSongEnumerator.hxx +++ b/src/playlist/CloseSongEnumerator.hxx @@ -23,7 +23,7 @@ #include "SongEnumerator.hxx" #include "Compiler.h" -struct InputStream; +class InputStream; /** * A #SongEnumerator wrapper that closes an #InputStream automatically diff --git a/src/playlist/PlaylistPlugin.hxx b/src/playlist/PlaylistPlugin.hxx index d3c44f1f4..fd779ad8d 100644 --- a/src/playlist/PlaylistPlugin.hxx +++ b/src/playlist/PlaylistPlugin.hxx @@ -21,7 +21,7 @@ #define MPD_PLAYLIST_PLUGIN_HXX struct config_param; -struct InputStream; +class InputStream; struct Tag; class Mutex; class Cond; diff --git a/src/playlist/PlaylistRegistry.hxx b/src/playlist/PlaylistRegistry.hxx index f1833b925..7ce559baa 100644 --- a/src/playlist/PlaylistRegistry.hxx +++ b/src/playlist/PlaylistRegistry.hxx @@ -23,7 +23,7 @@ class Mutex; class Cond; class SongEnumerator; -struct InputStream; +class InputStream; extern const struct playlist_plugin *const playlist_plugins[]; diff --git a/test/run_input.cxx b/test/run_input.cxx index 539171ad8..4a35e1479 100644 --- a/test/run_input.cxx +++ b/test/run_input.cxx @@ -52,8 +52,8 @@ dump_input_stream(InputStream *is) /* print meta data */ - if (!is->mime.empty()) - fprintf(stderr, "MIME type: %s\n", is->mime.c_str()); + if (is->HasMimeType()) + fprintf(stderr, "MIME type: %s\n", is->GetMimeType()); /* read data and tags from the stream */ |