From 707d379b97acea36528e5dca4d60e65686926e57 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 16 Mar 2014 11:14:16 +0100 Subject: input/mms: move blocking I/O to thread --- NEWS | 1 + src/input/plugins/MmsInputPlugin.cxx | 110 ++++++++++++++++------------------- 2 files changed, 51 insertions(+), 60 deletions(-) diff --git a/NEWS b/NEWS index 79bb27b5f..896bcee23 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,7 @@ ver 0.19 (not yet released) - read tags from songs in an archive * input - alsa: new input plugin + - mms: non-blocking I/O - nfs: new input plugin - smbclient: new input plugin * filter diff --git a/src/input/plugins/MmsInputPlugin.cxx b/src/input/plugins/MmsInputPlugin.cxx index a7068cb2b..845fe5d5d 100644 --- a/src/input/plugins/MmsInputPlugin.cxx +++ b/src/input/plugins/MmsInputPlugin.cxx @@ -19,40 +19,56 @@ #include "config.h" #include "MmsInputPlugin.hxx" -#include "../InputStream.hxx" -#include "../InputPlugin.hxx" +#include "input/ThreadInputStream.hxx" +#include "input/InputPlugin.hxx" #include "util/StringUtil.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" #include -struct MmsInputStream { - InputStream base; +static constexpr size_t MMS_BUFFER_SIZE = 256 * 1024; +class MmsInputStream final : public ThreadInputStream { mmsx_t *mms; - bool eof; - - MmsInputStream(const char *uri, - Mutex &mutex, Cond &cond, - mmsx_t *_mms) - :base(input_plugin_mms, uri, mutex, cond), - mms(_mms), eof(false) { - /* XX is this correct? at least this selects the ffmpeg - decoder, which seems to work fine*/ - base.mime = "audio/x-ms-wma"; - - base.ready = true; +public: + MmsInputStream(const char *uri, Mutex &mutex, Cond &cond) + :ThreadInputStream(input_plugin_mms, uri, mutex, cond, + MMS_BUFFER_SIZE) { } - ~MmsInputStream() { +protected: + virtual bool Open(gcc_unused Error &error) override; + virtual size_t Read(void *ptr, size_t size, Error &error) override; + + virtual void Close() { mmsx_close(mms); } }; static constexpr Domain mms_domain("mms"); +bool +MmsInputStream::Open(Error &error) +{ + Unlock(); + + mms = mmsx_connect(nullptr, nullptr, GetURI(), 128 * 1024); + if (mms == nullptr) { + Lock(); + error.Set(mms_domain, "mmsx_connect() failed"); + return false; + } + + Lock(); + + /* TODO: is this correct? at least this selects the ffmpeg + decoder, which seems to work fine */ + SetMimeType("audio/x-ms-wma"); + return true; +} + static InputStream * input_mms_open(const char *url, Mutex &mutex, Cond &cond, @@ -64,51 +80,25 @@ input_mms_open(const char *url, !StringStartsWith(url, "mmsu://")) return nullptr; - const auto mms = mmsx_connect(nullptr, nullptr, url, 128 * 1024); - if (mms == nullptr) { - error.Set(mms_domain, "mmsx_connect() failed"); - return nullptr; - } + auto m = new MmsInputStream(url, mutex, cond); + auto is = m->Start(error); + if (is == nullptr) + delete m; - auto m = new MmsInputStream(url, mutex, cond, mms); - return &m->base; + return is; } -static size_t -input_mms_read(InputStream *is, void *ptr, size_t size, - Error &error) +size_t +MmsInputStream::Read(void *ptr, size_t size, Error &error) { - MmsInputStream *m = (MmsInputStream *)is; - int ret; - - ret = mmsx_read(nullptr, m->mms, (char *)ptr, size); - if (ret <= 0) { - if (ret < 0) + int nbytes = mmsx_read(nullptr, mms, (char *)ptr, size); + if (nbytes <= 0) { + if (nbytes < 0) error.SetErrno("mmsx_read() failed"); - - m->eof = true; - return false; + return 0; } - is->offset += ret; - - return (size_t)ret; -} - -static void -input_mms_close(InputStream *is) -{ - MmsInputStream *m = (MmsInputStream *)is; - - delete m; -} - -static bool -input_mms_eof(InputStream *is) -{ - MmsInputStream *m = (MmsInputStream *)is; - - return m->eof; + return (size_t)nbytes; } const InputPlugin input_plugin_mms = { @@ -116,12 +106,12 @@ const InputPlugin input_plugin_mms = { nullptr, nullptr, input_mms_open, - input_mms_close, - nullptr, - nullptr, + ThreadInputStream::Close, + ThreadInputStream::Check, nullptr, nullptr, - input_mms_read, - input_mms_eof, + ThreadInputStream::Available, + ThreadInputStream::Read, + ThreadInputStream::IsEOF, nullptr, }; -- cgit v1.2.3