InputStream: make various methods abstract

Replace InputPlugin attributes.
This commit is contained in:
Max Kellermann 2014-05-11 17:14:49 +02:00
parent 82337dec44
commit d4b625b48e
19 changed files with 258 additions and 649 deletions

View File

@ -102,6 +102,10 @@ struct Bzip2InputStream final : public InputStream {
~Bzip2InputStream(); ~Bzip2InputStream();
bool Open(Error &error); bool Open(Error &error);
/* virtual methods from InputStream */
bool IsEOF() override;
size_t Read(void *ptr, size_t size, Error &error) override;
}; };
extern const InputPlugin bz2_inputplugin; extern const InputPlugin bz2_inputplugin;
@ -198,30 +202,26 @@ bz2_fillbuffer(Bzip2InputStream *bis, Error &error)
return true; return true;
} }
static size_t size_t
bz2_is_read(InputStream *is, void *ptr, size_t length, Bzip2InputStream::Read(void *ptr, size_t length, Error &error)
Error &error)
{ {
Bzip2InputStream *bis = (Bzip2InputStream *)is;
bz_stream *bzstream;
int bz_result; int bz_result;
size_t nbytes = 0; size_t nbytes = 0;
if (bis->eof) if (eof)
return 0; return 0;
bzstream = &bis->bzstream; bzstream.next_out = (char *)ptr;
bzstream->next_out = (char *)ptr; bzstream.avail_out = length;
bzstream->avail_out = length;
do { do {
if (!bz2_fillbuffer(bis, error)) if (!bz2_fillbuffer(this, error))
return 0; return 0;
bz_result = BZ2_bzDecompress(bzstream); bz_result = BZ2_bzDecompress(&bzstream);
if (bz_result == BZ_STREAM_END) { if (bz_result == BZ_STREAM_END) {
bis->eof = true; eof = true;
break; break;
} }
@ -230,20 +230,18 @@ bz2_is_read(InputStream *is, void *ptr, size_t length,
"BZ2_bzDecompress() has failed"); "BZ2_bzDecompress() has failed");
return 0; return 0;
} }
} while (bzstream->avail_out == length); } while (bzstream.avail_out == length);
nbytes = length - bzstream->avail_out; nbytes = length - bzstream.avail_out;
is->offset += nbytes; offset += nbytes;
return nbytes; return nbytes;
} }
static bool bool
bz2_is_eof(InputStream *is) Bzip2InputStream::IsEOF()
{ {
Bzip2InputStream *bis = (Bzip2InputStream *)is; return eof;
return bis->eof;
} }
/* exported structures */ /* exported structures */
@ -258,13 +256,6 @@ const InputPlugin bz2_inputplugin = {
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
bz2_is_read,
bz2_is_eof,
nullptr,
}; };
const ArchivePlugin bz2_archive_plugin = { const ArchivePlugin bz2_archive_plugin = {

View File

@ -162,7 +162,9 @@ public:
archive.Unref(); archive.Unref();
} }
size_t Read(void *ptr, size_t size, Error &error); /* virtual methods from InputStream */
bool IsEOF() override;
size_t Read(void *ptr, size_t size, Error &error) override;
}; };
InputStream * InputStream *
@ -181,7 +183,7 @@ Iso9660ArchiveFile::OpenStream(const char *pathname,
statbuf); statbuf);
} }
inline size_t size_t
Iso9660InputStream::Read(void *ptr, size_t read_size, Error &error) Iso9660InputStream::Read(void *ptr, size_t read_size, Error &error)
{ {
int readed = 0; int readed = 0;
@ -216,18 +218,10 @@ Iso9660InputStream::Read(void *ptr, size_t read_size, Error &error)
return readed; return readed;
} }
static size_t bool
iso9660_input_read(InputStream *is, void *ptr, size_t size, Iso9660InputStream::IsEOF()
Error &error)
{ {
Iso9660InputStream *iis = (Iso9660InputStream *)is; return offset == size;
return iis->Read(ptr, size, error);
}
static bool
iso9660_input_eof(InputStream *is)
{
return is->offset == is->size;
} }
/* exported structures */ /* exported structures */
@ -242,13 +236,6 @@ const InputPlugin iso9660_input_plugin = {
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
iso9660_input_read,
iso9660_input_eof,
nullptr,
}; };
const ArchivePlugin iso9660_archive_plugin = { const ArchivePlugin iso9660_archive_plugin = {

View File

@ -123,6 +123,11 @@ struct ZzipInputStream final : public InputStream {
zzip_file_close(file); zzip_file_close(file);
archive->Unref(); archive->Unref();
} }
/* virtual methods from InputStream */
bool IsEOF() override;
size_t Read(void *ptr, size_t size, Error &error) override;
bool Seek(offset_type offset, int whence, Error &error) override;
}; };
InputStream * InputStream *
@ -142,41 +147,32 @@ ZzipArchiveFile::OpenStream(const char *pathname,
_file); _file);
} }
static size_t size_t
zzip_input_read(InputStream *is, void *ptr, size_t size, ZzipInputStream::Read(void *ptr, size_t read_size, Error &error)
Error &error)
{ {
ZzipInputStream *zis = (ZzipInputStream *)is; int ret = zzip_file_read(file, ptr, read_size);
int ret;
ret = zzip_file_read(zis->file, ptr, size);
if (ret < 0) { if (ret < 0) {
error.Set(zzip_domain, "zzip_file_read() has failed"); error.Set(zzip_domain, "zzip_file_read() has failed");
return 0; return 0;
} }
is->offset = zzip_tell(zis->file); offset = zzip_tell(file);
return ret; return ret;
} }
static bool bool
zzip_input_eof(InputStream *is) ZzipInputStream::IsEOF()
{ {
ZzipInputStream *zis = (ZzipInputStream *)is; return (InputPlugin::offset_type)zzip_tell(file) == size;
return (InputPlugin::offset_type)zzip_tell(zis->file) == is->size;
} }
static bool bool
zzip_input_seek(InputStream *is, InputPlugin::offset_type offset, ZzipInputStream::Seek(offset_type new_offset, int whence, Error &error)
int whence, Error &error)
{ {
ZzipInputStream *zis = (ZzipInputStream *)is; zzip_off_t ofs = zzip_seek(file, new_offset, whence);
zzip_off_t ofs = zzip_seek(zis->file, offset, whence);
if (ofs != -1) { if (ofs != -1) {
error.Set(zzip_domain, "zzip_seek() has failed"); error.Set(zzip_domain, "zzip_seek() has failed");
is->offset = ofs; offset = ofs;
return true; return true;
} }
return false; return false;
@ -194,13 +190,6 @@ const InputPlugin zzip_input_plugin = {
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
zzip_input_read,
zzip_input_eof,
zzip_input_seek,
}; };
const ArchivePlugin zzip_archive_plugin = { const ArchivePlugin zzip_archive_plugin = {

View File

@ -82,38 +82,6 @@ struct InputPlugin {
InputStream *(*open)(const char *uri, InputStream *(*open)(const char *uri,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
Error &error); Error &error);
/**
* Check for errors that may have occurred in the I/O thread.
* May be unimplemented for synchronous plugins.
*
* @return false on error
*/
bool (*check)(InputStream *is, Error &error);
/**
* Update the public attributes. Call before access. Can be
* nullptr if the plugin always keeps its attributes up to date.
*/
void (*update)(InputStream *is);
Tag *(*tag)(InputStream *is);
/**
* Returns true if the next read operation will not block:
* either data is available, or end-of-stream has been
* reached, or an error has occurred.
*
* If this method is unimplemented, then it is assumed that
* reading will never block.
*/
bool (*available)(InputStream *is);
size_t (*read)(InputStream *is, void *ptr, size_t size,
Error &error);
bool (*eof)(InputStream *is);
bool (*seek)(InputStream *is, offset_type offset, int whence,
Error &error);
}; };
#endif #endif

View File

@ -45,10 +45,6 @@ InputStream::Open(const char *url,
is = plugin->open(url, mutex, cond, error); is = plugin->open(url, mutex, cond, error);
if (is != nullptr) { if (is != nullptr) {
assert(is->plugin.read != nullptr);
assert(is->plugin.eof != nullptr);
assert(!is->seekable || is->plugin.seek != nullptr);
is = input_rewind_open(is); is = input_rewind_open(is);
return is; return is;
@ -83,16 +79,14 @@ InputStream::OpenReady(const char *uri,
} }
bool bool
InputStream::Check(Error &error) InputStream::Check(gcc_unused Error &error)
{ {
return plugin.check == nullptr || plugin.check(this, error); return true;
} }
void void
InputStream::Update() InputStream::Update()
{ {
if (plugin.update != nullptr)
plugin.update(this);
} }
void void
@ -130,20 +124,15 @@ InputStream::CheapSeeking() const
} }
bool bool
InputStream::Seek(offset_type _offset, int whence, Error &error) InputStream::Seek(gcc_unused offset_type new_offset, gcc_unused int whence,
gcc_unused Error &error)
{ {
if (plugin.seek == nullptr) return false;
return false;
return plugin.seek(this, _offset, whence, error);
} }
bool bool
InputStream::LockSeek(offset_type _offset, int whence, Error &error) InputStream::LockSeek(offset_type _offset, int whence, Error &error)
{ {
if (plugin.seek == nullptr)
return false;
const ScopeLock protect(mutex); const ScopeLock protect(mutex);
return Seek(_offset, whence, error); return Seek(_offset, whence, error);
} }
@ -163,17 +152,12 @@ InputStream::LockRewind(Error &error)
Tag * Tag *
InputStream::ReadTag() InputStream::ReadTag()
{ {
return plugin.tag != nullptr return nullptr;
? plugin.tag(this)
: nullptr;
} }
Tag * Tag *
InputStream::LockReadTag() InputStream::LockReadTag()
{ {
if (plugin.tag == nullptr)
return nullptr;
const ScopeLock protect(mutex); const ScopeLock protect(mutex);
return ReadTag(); return ReadTag();
} }
@ -181,18 +165,7 @@ InputStream::LockReadTag()
bool bool
InputStream::IsAvailable() InputStream::IsAvailable()
{ {
return plugin.available != nullptr return true;
? plugin.available(this)
: true;
}
size_t
InputStream::Read(void *ptr, size_t _size, Error &error)
{
assert(ptr != nullptr);
assert(_size > 0);
return plugin.read(this, ptr, _size, error);
} }
size_t size_t
@ -205,12 +178,6 @@ InputStream::LockRead(void *ptr, size_t _size, Error &error)
return Read(ptr, _size, error); return Read(ptr, _size, error);
} }
bool
InputStream::IsEOF()
{
return plugin.eof(this);
}
bool bool
InputStream::LockIsEOF() InputStream::LockIsEOF()
{ {

View File

@ -166,13 +166,13 @@ public:
* *
* @return false on error * @return false on error
*/ */
bool Check(Error &error); virtual bool Check(Error &error);
/** /**
* Update the public attributes. Call before accessing attributes * Update the public attributes. Call before accessing attributes
* such as "ready" or "offset". * such as "ready" or "offset".
*/ */
void Update(); virtual void Update();
void SetReady(); void SetReady();
@ -272,7 +272,7 @@ public:
* @param offset the relative offset * @param offset the relative offset
* @param whence the base of the seek, one of SEEK_SET, SEEK_CUR, SEEK_END * @param whence the base of the seek, one of SEEK_SET, SEEK_CUR, SEEK_END
*/ */
bool Seek(offset_type offset, int whence, Error &error); virtual bool Seek(offset_type offset, int whence, Error &error);
/** /**
* Wrapper for Seek() which locks and unlocks the mutex; the * Wrapper for Seek() which locks and unlocks the mutex; the
@ -293,7 +293,7 @@ public:
* The caller must lock the mutex. * The caller must lock the mutex.
*/ */
gcc_pure gcc_pure
bool IsEOF(); virtual bool IsEOF() = 0;
/** /**
* Wrapper for IsEOF() which locks and unlocks the mutex; the * Wrapper for IsEOF() which locks and unlocks the mutex; the
@ -311,7 +311,7 @@ public:
* nullptr if the tag has not changed since the last call * nullptr if the tag has not changed since the last call
*/ */
gcc_malloc gcc_malloc
Tag *ReadTag(); virtual Tag *ReadTag();
/** /**
* Wrapper for ReadTag() which locks and unlocks the mutex; * Wrapper for ReadTag() which locks and unlocks the mutex;
@ -328,7 +328,7 @@ public:
* The caller must lock the mutex. * The caller must lock the mutex.
*/ */
gcc_pure gcc_pure
bool IsAvailable(); virtual bool IsAvailable();
/** /**
* Reads data from the stream into the caller-supplied buffer. * Reads data from the stream into the caller-supplied buffer.
@ -342,7 +342,7 @@ public:
* @return the number of bytes read * @return the number of bytes read
*/ */
gcc_nonnull_all gcc_nonnull_all
size_t Read(void *ptr, size_t size, Error &error); virtual size_t Read(void *ptr, size_t size, Error &error) = 0;
/** /**
* Wrapper for Read() which locks and unlocks the mutex; * Wrapper for Read() which locks and unlocks the mutex;

View File

@ -116,8 +116,8 @@ ThreadInputStream::ThreadFunc(void *ctx)
tis.ThreadFunc(); tis.ThreadFunc();
} }
inline bool bool
ThreadInputStream::Check2(Error &error) ThreadInputStream::Check(Error &error)
{ {
if (postponed_error.IsDefined()) { if (postponed_error.IsDefined()) {
error = std::move(postponed_error); error = std::move(postponed_error);
@ -128,27 +128,13 @@ ThreadInputStream::Check2(Error &error)
} }
bool bool
ThreadInputStream::Check(InputStream *is, Error &error) ThreadInputStream::IsAvailable()
{
ThreadInputStream &tis = *(ThreadInputStream *)is;
return tis.Check2(error);
}
inline bool
ThreadInputStream::Available2()
{ {
return !buffer->IsEmpty() || eof || postponed_error.IsDefined(); return !buffer->IsEmpty() || eof || postponed_error.IsDefined();
} }
bool
ThreadInputStream::Available(InputStream *is)
{
ThreadInputStream &tis = *(ThreadInputStream *)is;
return tis.Available2();
}
inline size_t inline size_t
ThreadInputStream::Read2(void *ptr, size_t read_size, Error &error) ThreadInputStream::Read(void *ptr, size_t read_size, Error &error)
{ {
while (true) { while (true) {
if (postponed_error.IsDefined()) { if (postponed_error.IsDefined()) {
@ -173,23 +159,8 @@ ThreadInputStream::Read2(void *ptr, size_t read_size, Error &error)
} }
} }
size_t bool
ThreadInputStream::Read(InputStream *is, void *ptr, size_t size, ThreadInputStream::IsEOF()
Error &error)
{
ThreadInputStream &tis = *(ThreadInputStream *)is;
return tis.Read2(ptr, size, error);
}
inline bool
ThreadInputStream::IsEOF2()
{ {
return eof; return eof;
} }
bool
ThreadInputStream::IsEOF(InputStream *is)
{
ThreadInputStream &tis = *(ThreadInputStream *)is;
return tis.IsEOF2();
}

View File

@ -82,6 +82,12 @@ public:
*/ */
InputStream *Start(Error &error); InputStream *Start(Error &error);
/* virtual methods from InputStream */
bool Check(Error &error) override final;
bool IsEOF() override final;
bool IsAvailable() override final;
size_t Read(void *ptr, size_t size, Error &error) override final;
protected: protected:
void SetMimeType(const char *_mime) { void SetMimeType(const char *_mime) {
assert(thread.IsInside()); assert(thread.IsInside());
@ -110,7 +116,7 @@ protected:
* *
* @return 0 on end-of-file or on error * @return 0 on end-of-file or on error
*/ */
virtual size_t Read(void *ptr, size_t size, Error &error) = 0; virtual size_t ThreadRead(void *ptr, size_t size, Error &error) = 0;
/** /**
* Optional deinitialization before leaving the thread. * Optional deinitialization before leaving the thread.
@ -130,19 +136,6 @@ protected:
private: private:
void ThreadFunc(); void ThreadFunc();
static void ThreadFunc(void *ctx); static void ThreadFunc(void *ctx);
bool Check2(Error &error);
bool Available2();
size_t Read2(void *ptr, size_t size, Error &error);
bool IsEOF2();
public:
/* InputPlugin callbacks */
static bool Check(InputStream *is, Error &error);
static bool Available(InputStream *is);
static size_t Read(InputStream *is, void *ptr, size_t size,
Error &error);
static bool IsEOF(InputStream *is);
}; };
#endif #endif

View File

@ -116,7 +116,13 @@ public:
static InputStream *Create(const char *uri, Mutex &mutex, Cond &cond, static InputStream *Create(const char *uri, Mutex &mutex, Cond &cond,
Error &error); Error &error);
bool Available() { /* virtual methods from InputStream */
bool IsEOF() override {
return eof;
}
bool IsAvailable() override {
if (snd_pcm_avail(capture_handle) > frames_to_read) if (snd_pcm_avail(capture_handle) > frames_to_read)
return true; return true;
@ -126,11 +132,7 @@ public:
return false; return false;
} }
size_t Read(void *ptr, size_t size, Error &error); size_t Read(void *ptr, size_t size, Error &error) override;
bool IsEOF() {
return eof;
}
private: private:
static snd_pcm_t *OpenDevice(const char *device, int rate, static snd_pcm_t *OpenDevice(const char *device, int rate,
@ -181,7 +183,7 @@ AlsaInputStream::Create(const char *uri, Mutex &mutex, Cond &cond,
handle, frame_size); handle, frame_size);
} }
inline size_t size_t
AlsaInputStream::Read(void *ptr, size_t read_size, Error &error) AlsaInputStream::Read(void *ptr, size_t read_size, Error &error)
{ {
assert(ptr != nullptr); assert(ptr != nullptr);
@ -373,37 +375,9 @@ alsa_input_open(const char *uri, Mutex &mutex, Cond &cond, Error &error)
return AlsaInputStream::Create(uri, mutex, cond, error); return AlsaInputStream::Create(uri, mutex, cond, error);
} }
static bool
alsa_input_available(InputStream *is)
{
AlsaInputStream *ais = (AlsaInputStream *)is;
return ais->Available();
}
static size_t
alsa_input_read(InputStream *is, void *ptr, size_t size, Error &error)
{
AlsaInputStream *ais = (AlsaInputStream *)is;
return ais->Read(ptr, size, error);
}
static bool
alsa_input_eof(gcc_unused InputStream *is)
{
AlsaInputStream *ais = (AlsaInputStream *)is;
return ais->IsEOF();
}
const struct InputPlugin input_plugin_alsa = { const struct InputPlugin input_plugin_alsa = {
"alsa", "alsa",
nullptr, nullptr,
nullptr, nullptr,
alsa_input_open, alsa_input_open,
nullptr,
nullptr,
nullptr,
alsa_input_available,
alsa_input_read,
alsa_input_eof,
nullptr,
}; };

View File

@ -89,11 +89,4 @@ const InputPlugin input_plugin_archive = {
nullptr, nullptr,
nullptr, nullptr,
input_archive_open, input_archive_open,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
}; };

View File

@ -79,6 +79,11 @@ struct CdioParanoiaInputStream final : public InputStream {
if (cdio != nullptr) if (cdio != nullptr)
cdio_destroy(cdio); cdio_destroy(cdio);
} }
/* virtual methods from InputStream */
bool IsEOF() override;
size_t Read(void *ptr, size_t size, Error &error) override;
bool Seek(offset_type offset, int whence, Error &error) override;
}; };
static constexpr Domain cdio_domain("cdio"); static constexpr Domain cdio_domain("cdio");
@ -266,48 +271,44 @@ input_cdio_open(const char *uri,
return i; return i;
} }
static bool bool
input_cdio_seek(InputStream *is, CdioParanoiaInputStream::Seek(InputPlugin::offset_type new_offset,
InputPlugin::offset_type offset, int whence, Error &error) int whence, Error &error)
{ {
CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is;
/* calculate absolute offset */ /* calculate absolute offset */
switch (whence) { switch (whence) {
case SEEK_SET: case SEEK_SET:
break; break;
case SEEK_CUR: case SEEK_CUR:
offset += cis->offset; new_offset += offset;
break; break;
case SEEK_END: case SEEK_END:
offset += cis->size; new_offset += size;
break; break;
} }
if (offset < 0 || offset > cis->size) { if (new_offset < 0 || new_offset > size) {
error.Format(cdio_domain, "Invalid offset to seek %ld (%ld)", error.Format(cdio_domain, "Invalid offset to seek %ld (%ld)",
(long int)offset, (long int)cis->size); (long int)new_offset, (long int)size);
return false; return false;
} }
/* simple case */ /* simple case */
if (offset == cis->offset) if (new_offset == offset)
return true; return true;
/* calculate current LSN */ /* calculate current LSN */
cis->lsn_relofs = offset / CDIO_CD_FRAMESIZE_RAW; lsn_relofs = new_offset / CDIO_CD_FRAMESIZE_RAW;
cis->offset = offset; offset = new_offset;
cdio_paranoia_seek(cis->para, cis->lsn_from + cis->lsn_relofs, SEEK_SET); cdio_paranoia_seek(para, lsn_from + lsn_relofs, SEEK_SET);
return true; return true;
} }
static size_t size_t
input_cdio_read(InputStream *is, void *ptr, size_t length, CdioParanoiaInputStream::Read(void *ptr, size_t length, Error &error)
Error &error)
{ {
CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is;
size_t nbytes = 0; size_t nbytes = 0;
int diff; int diff;
size_t len, maxwrite; size_t len, maxwrite;
@ -319,20 +320,20 @@ input_cdio_read(InputStream *is, void *ptr, size_t length,
/* end of track ? */ /* end of track ? */
if (cis->lsn_from + cis->lsn_relofs > cis->lsn_to) if (lsn_from + lsn_relofs > lsn_to)
break; break;
//current sector was changed ? //current sector was changed ?
if (cis->lsn_relofs != cis->buffer_lsn) { if (lsn_relofs != buffer_lsn) {
rbuf = cdio_paranoia_read(cis->para, nullptr); rbuf = cdio_paranoia_read(para, nullptr);
s_err = cdda_errors(cis->drv); s_err = cdda_errors(drv);
if (s_err) { if (s_err) {
FormatError(cdio_domain, FormatError(cdio_domain,
"paranoia_read: %s", s_err); "paranoia_read: %s", s_err);
free(s_err); free(s_err);
} }
s_mess = cdda_messages(cis->drv); s_mess = cdda_messages(drv);
if (s_mess) { if (s_mess) {
free(s_mess); free(s_mess);
} }
@ -342,15 +343,15 @@ input_cdio_read(InputStream *is, void *ptr, size_t length,
return 0; return 0;
} }
//store current buffer //store current buffer
memcpy(cis->buffer, rbuf, CDIO_CD_FRAMESIZE_RAW); memcpy(buffer, rbuf, CDIO_CD_FRAMESIZE_RAW);
cis->buffer_lsn = cis->lsn_relofs; buffer_lsn = lsn_relofs;
} else { } else {
//use cached sector //use cached sector
rbuf = (int16_t*) cis->buffer; rbuf = (int16_t *)buffer;
} }
//correct offset //correct offset
diff = cis->offset - cis->lsn_relofs * CDIO_CD_FRAMESIZE_RAW; diff = offset - lsn_relofs * CDIO_CD_FRAMESIZE_RAW;
assert(diff >= 0 && diff < CDIO_CD_FRAMESIZE_RAW); assert(diff >= 0 && diff < CDIO_CD_FRAMESIZE_RAW);
@ -364,8 +365,8 @@ input_cdio_read(InputStream *is, void *ptr, size_t length,
nbytes += len; nbytes += len;
//update offset //update offset
cis->offset += len; offset += len;
cis->lsn_relofs = cis->offset / CDIO_CD_FRAMESIZE_RAW; lsn_relofs = offset / CDIO_CD_FRAMESIZE_RAW;
//update length //update length
length -= len; length -= len;
} }
@ -373,12 +374,10 @@ input_cdio_read(InputStream *is, void *ptr, size_t length,
return nbytes; return nbytes;
} }
static bool bool
input_cdio_eof(InputStream *is) CdioParanoiaInputStream::IsEOF()
{ {
CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is; return lsn_from + lsn_relofs > lsn_to;
return (cis->lsn_from + cis->lsn_relofs > cis->lsn_to);
} }
const InputPlugin input_plugin_cdio_paranoia = { const InputPlugin input_plugin_cdio_paranoia = {
@ -386,11 +385,4 @@ const InputPlugin input_plugin_cdio_paranoia = {
input_cdio_init, input_cdio_init,
nullptr, nullptr,
input_cdio_open, input_cdio_open,
nullptr,
nullptr,
nullptr,
nullptr,
input_cdio_read,
input_cdio_eof,
input_cdio_seek,
}; };

View File

@ -120,23 +120,6 @@ struct CurlInputStream final : public InputStream {
static InputStream *Open(const char *url, Mutex &mutex, Cond &cond, static InputStream *Open(const char *url, Mutex &mutex, Cond &cond,
Error &error); Error &error);
bool Check(Error &error);
bool IsEOF() const {
return easy == nullptr && buffer.IsEmpty();
}
bool Seek(InputPlugin::offset_type offset, int whence, Error &error);
Tag *ReadTag();
bool IsAvailable() const {
return postponed_error.IsDefined() || easy == nullptr ||
!buffer.IsEmpty();
}
size_t Read(void *ptr, size_t size, Error &error);
bool InitEasy(Error &error); bool InitEasy(Error &error);
/** /**
@ -180,6 +163,23 @@ struct CurlInputStream final : public InputStream {
* Runs in the I/O thread. The caller must not hold locks. * Runs in the I/O thread. The caller must not hold locks.
*/ */
void RequestDone(CURLcode result, long status); void RequestDone(CURLcode result, long status);
/* virtual methods from InputStream */
bool Check(Error &error) override;
bool IsEOF() override {
return easy == nullptr && buffer.IsEmpty();
}
Tag *ReadTag() override;
bool IsAvailable() override {
return postponed_error.IsDefined() || easy == nullptr ||
!buffer.IsEmpty();
}
size_t Read(void *ptr, size_t size, Error &error) override;
bool Seek(offset_type offset, int whence, Error &error) override;
}; };
class CurlMulti; class CurlMulti;
@ -660,14 +660,7 @@ CurlInputStream::Check(Error &error)
return success; return success;
} }
static bool Tag *
input_curl_check(InputStream *is, Error &error)
{
CurlInputStream &c = *(CurlInputStream *)is;
return c.Check(error);
}
inline Tag *
CurlInputStream::ReadTag() CurlInputStream::ReadTag()
{ {
Tag *result = tag; Tag *result = tag;
@ -675,13 +668,6 @@ CurlInputStream::ReadTag()
return result; return result;
} }
static Tag *
input_curl_tag(InputStream *is)
{
CurlInputStream &c = *(CurlInputStream *)is;
return c.ReadTag();
}
inline bool inline bool
CurlInputStream::FillBuffer(Error &error) CurlInputStream::FillBuffer(Error &error)
{ {
@ -758,14 +744,7 @@ CurlInputStream::CopyIcyTag()
tag = new_tag; tag = new_tag;
} }
static bool size_t
input_curl_available(InputStream *is)
{
const CurlInputStream &c = *(const CurlInputStream *)is;
return c.IsAvailable();
}
inline size_t
CurlInputStream::Read(void *ptr, size_t read_size, Error &error) CurlInputStream::Read(void *ptr, size_t read_size, Error &error)
{ {
size_t nbytes; size_t nbytes;
@ -797,21 +776,6 @@ CurlInputStream::Read(void *ptr, size_t read_size, Error &error)
return nbytes; return nbytes;
} }
static size_t
input_curl_read(InputStream *is, void *ptr, size_t size,
Error &error)
{
CurlInputStream &c = *(CurlInputStream *)is;
return c.Read(ptr, size, error);
}
static bool
input_curl_eof(gcc_unused InputStream *is)
{
const CurlInputStream &c = *(const CurlInputStream *)is;
return c.IsEOF();
}
inline void inline void
CurlInputStream::HeaderReceived(const char *name, std::string &&value) CurlInputStream::HeaderReceived(const char *name, std::string &&value)
{ {
@ -1091,15 +1055,6 @@ CurlInputStream::Seek(InputPlugin::offset_type new_offset, int whence,
return true; return true;
} }
static bool
input_curl_seek(InputStream *is, InputPlugin::offset_type offset,
int whence,
Error &error)
{
CurlInputStream &c = *(CurlInputStream *)is;
return c.Seek(offset, whence, error);
}
inline InputStream * inline InputStream *
CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond, CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond,
Error &error) Error &error)
@ -1136,11 +1091,4 @@ const struct InputPlugin input_plugin_curl = {
input_curl_init, input_curl_init,
input_curl_finish, input_curl_finish,
input_curl_open, input_curl_open,
input_curl_check,
nullptr,
input_curl_tag,
input_curl_available,
input_curl_read,
input_curl_eof,
input_curl_seek,
}; };

View File

@ -66,13 +66,15 @@ public:
static InputStream *Open(const char *url, Mutex &mutex, Cond &cond, static InputStream *Open(const char *url, Mutex &mutex, Cond &cond,
Error &error); Error &error);
bool IsEOF() const { void Callback(int sig);
/* virtual methods from InputStream */
bool IsEOF() override {
return eof; return eof;
} }
size_t Read(void *ptr, size_t size, Error &error); Tag *ReadTag() override {
Tag *ReadTag() {
if (tag.IsEmpty()) if (tag.IsEmpty())
return nullptr; return nullptr;
@ -81,7 +83,7 @@ public:
return result; return result;
} }
void Callback(int sig); size_t Read(void *ptr, size_t size, Error &error) override;
private: private:
void FillBuffer(); void FillBuffer();
@ -201,7 +203,7 @@ input_despotify_open(const char *url, Mutex &mutex, Cond &cond, Error &error)
return DespotifyInputStream::Open(url, mutex, cond, error); return DespotifyInputStream::Open(url, mutex, cond, error);
} }
inline size_t size_t
DespotifyInputStream::Read(void *ptr, size_t read_size, DespotifyInputStream::Read(void *ptr, size_t read_size,
gcc_unused Error &error) gcc_unused Error &error)
{ {
@ -217,39 +219,9 @@ DespotifyInputStream::Read(void *ptr, size_t read_size,
return to_cpy; return to_cpy;
} }
static size_t
input_despotify_read(InputStream *is, void *ptr, size_t size, Error &error)
{
DespotifyInputStream *ctx = (DespotifyInputStream *)is;
return ctx->Read(ptr, size, error);
}
static bool
input_despotify_eof(InputStream *is)
{
DespotifyInputStream *ctx = (DespotifyInputStream *)is;
return ctx->IsEOF();
}
static Tag *
input_despotify_tag(InputStream *is)
{
DespotifyInputStream *ctx = (DespotifyInputStream *)is;
return ctx->ReadTag();
}
const InputPlugin input_plugin_despotify = { const InputPlugin input_plugin_despotify = {
"despotify", "despotify",
nullptr, nullptr,
nullptr, nullptr,
input_despotify_open, input_despotify_open,
nullptr,
nullptr,
input_despotify_tag,
nullptr,
input_despotify_read,
input_despotify_eof,
nullptr,
}; };

View File

@ -56,6 +56,11 @@ struct FfmpegInputStream final : public InputStream {
~FfmpegInputStream() { ~FfmpegInputStream() {
avio_close(h); avio_close(h);
} }
/* virtual methods from InputStream */
bool IsEOF() override;
size_t Read(void *ptr, size_t size, Error &error) override;
bool Seek(offset_type offset, int whence, Error &error) override;
}; };
static constexpr Domain ffmpeg_domain("ffmpeg"); static constexpr Domain ffmpeg_domain("ffmpeg");
@ -106,43 +111,35 @@ input_ffmpeg_open(const char *uri,
return new FfmpegInputStream(uri, mutex, cond, h); return new FfmpegInputStream(uri, mutex, cond, h);
} }
static size_t size_t
input_ffmpeg_read(InputStream *is, void *ptr, size_t size, FfmpegInputStream::Read(void *ptr, size_t read_size, Error &error)
Error &error)
{ {
FfmpegInputStream *i = (FfmpegInputStream *)is; int ret = avio_read(h, (unsigned char *)ptr, read_size);
int ret = avio_read(i->h, (unsigned char *)ptr, size);
if (ret <= 0) { if (ret <= 0) {
if (ret < 0) if (ret < 0)
error.Set(ffmpeg_domain, "avio_read() failed"); error.Set(ffmpeg_domain, "avio_read() failed");
i->eof = true; eof = true;
return false; return false;
} }
is->offset += ret; offset += ret;
return (size_t)ret; return (size_t)ret;
} }
static bool bool
input_ffmpeg_eof(InputStream *is) FfmpegInputStream::IsEOF()
{ {
FfmpegInputStream *i = (FfmpegInputStream *)is; return eof;
return i->eof;
} }
static bool bool
input_ffmpeg_seek(InputStream *is, InputPlugin::offset_type offset, FfmpegInputStream::Seek(offset_type new_offset, int whence, Error &error)
int whence,
Error &error)
{ {
FfmpegInputStream *i = (FfmpegInputStream *)is; int64_t ret = avio_seek(h, new_offset, whence);
int64_t ret = avio_seek(i->h, offset, whence);
if (ret >= 0) { if (ret >= 0) {
i->eof = false; eof = false;
return true; return true;
} else { } else {
error.Set(ffmpeg_domain, "avio_seek() failed"); error.Set(ffmpeg_domain, "avio_seek() failed");
@ -155,11 +152,4 @@ const InputPlugin input_plugin_ffmpeg = {
input_ffmpeg_init, input_ffmpeg_init,
nullptr, nullptr,
input_ffmpeg_open, input_ffmpeg_open,
nullptr,
nullptr,
nullptr,
nullptr,
input_ffmpeg_read,
input_ffmpeg_eof,
input_ffmpeg_seek,
}; };

View File

@ -48,6 +48,15 @@ struct FileInputStream final : public InputStream {
~FileInputStream() { ~FileInputStream() {
close(fd); close(fd);
} }
/* virtual methods from InputStream */
bool IsEOF() override {
return GetOffset() >= GetSize();
}
size_t Read(void *ptr, size_t size, Error &error) override;
bool Seek(offset_type offset, int whence, Error &error) override;
}; };
static InputStream * static InputStream *
@ -89,56 +98,37 @@ input_file_open(const char *filename,
return new FileInputStream(filename, fd, st.st_size, mutex, cond); return new FileInputStream(filename, fd, st.st_size, mutex, cond);
} }
static bool bool
input_file_seek(InputStream *is, InputPlugin::offset_type offset, FileInputStream::Seek(InputPlugin::offset_type new_offset, int whence,
int whence, Error &error)
Error &error)
{ {
FileInputStream *fis = (FileInputStream *)is; new_offset = (InputPlugin::offset_type)lseek(fd, (off_t)new_offset,
whence);
offset = (InputPlugin::offset_type)lseek(fis->fd, (off_t)offset, whence); if (new_offset < 0) {
if (offset < 0) {
error.SetErrno("Failed to seek"); error.SetErrno("Failed to seek");
return false; return false;
} }
is->offset = offset; offset = new_offset;
return true; return true;
} }
static size_t size_t
input_file_read(InputStream *is, void *ptr, size_t size, FileInputStream::Read(void *ptr, size_t read_size, Error &error)
Error &error)
{ {
FileInputStream *fis = (FileInputStream *)is; ssize_t nbytes = read(fd, ptr, read_size);
ssize_t nbytes;
nbytes = read(fis->fd, ptr, size);
if (nbytes < 0) { if (nbytes < 0) {
error.SetErrno("Failed to read"); error.SetErrno("Failed to read");
return 0; return 0;
} }
is->offset += nbytes; offset += nbytes;
return (size_t)nbytes; return (size_t)nbytes;
} }
static bool
input_file_eof(InputStream *is)
{
return is->GetOffset() >= is->GetSize();
}
const InputPlugin input_plugin_file = { const InputPlugin input_plugin_file = {
"file", "file",
nullptr, nullptr,
nullptr, nullptr,
input_file_open, input_file_open,
nullptr,
nullptr,
nullptr,
nullptr,
input_file_read,
input_file_eof,
input_file_seek,
}; };

View File

@ -40,7 +40,8 @@ public:
protected: protected:
virtual bool Open(gcc_unused Error &error) override; virtual bool Open(gcc_unused Error &error) override;
virtual size_t Read(void *ptr, size_t size, Error &error) override; virtual size_t ThreadRead(void *ptr, size_t size,
Error &error) override;
virtual void Close() { virtual void Close() {
mmsx_close(mms); mmsx_close(mms);
@ -89,7 +90,7 @@ input_mms_open(const char *url,
} }
size_t size_t
MmsInputStream::Read(void *ptr, size_t read_size, Error &error) MmsInputStream::ThreadRead(void *ptr, size_t read_size, Error &error)
{ {
int nbytes = mmsx_read(nullptr, mms, (char *)ptr, read_size); int nbytes = mmsx_read(nullptr, mms, (char *)ptr, read_size);
if (nbytes <= 0) { if (nbytes <= 0) {
@ -106,11 +107,4 @@ const InputPlugin input_plugin_mms = {
nullptr, nullptr,
nullptr, nullptr,
input_mms_open, input_mms_open,
ThreadInputStream::Check,
nullptr,
nullptr,
ThreadInputStream::Available,
ThreadInputStream::Read,
ThreadInputStream::IsEOF,
nullptr,
}; };

View File

@ -54,34 +54,43 @@ public:
nfs_destroy_context(ctx); nfs_destroy_context(ctx);
} }
bool IsEOF() const { /* virtual methods from InputStream */
bool IsEOF() override {
return offset >= size; return offset >= size;
} }
size_t Read(void *ptr, size_t read_size, Error &error) { size_t Read(void *ptr, size_t size, Error &error) override;
int nbytes = nfs_read(ctx, fh, read_size, (char *)ptr); bool Seek(offset_type offset, int whence, Error &error) override;
if (nbytes < 0) {
error.SetErrno(-nbytes, "nfs_read() failed");
nbytes = 0;
}
return nbytes;
}
bool Seek(InputStream::offset_type new_offset, int whence, Error &error) {
uint64_t current_offset;
int result = nfs_lseek(ctx, fh, new_offset, whence,
&current_offset);
if (result < 0) {
error.SetErrno(-result, "smbc_lseek() failed");
return false;
}
offset = current_offset;
return true;
}
}; };
size_t
NfsInputStream::Read(void *ptr, size_t read_size, Error &error)
{
int nbytes = nfs_read(ctx, fh, read_size, (char *)ptr);
if (nbytes < 0) {
error.SetErrno(-nbytes, "nfs_read() failed");
nbytes = 0;
}
return nbytes;
}
bool
NfsInputStream::Seek(offset_type new_offset, int whence, Error &error)
{
uint64_t current_offset;
int result = nfs_lseek(ctx, fh, new_offset, whence,
&current_offset);
if (result < 0) {
error.SetErrno(-result, "smbc_lseek() failed");
return false;
}
offset = current_offset;
return true;
}
/* /*
* InputPlugin methods * InputPlugin methods
* *
@ -148,40 +157,9 @@ input_nfs_open(const char *uri,
return new NfsInputStream(uri, mutex, cond, ctx, fh, st.st_size); return new NfsInputStream(uri, mutex, cond, ctx, fh, st.st_size);
} }
static size_t
input_nfs_read(InputStream *is, void *ptr, size_t size,
Error &error)
{
NfsInputStream &s = *(NfsInputStream *)is;
return s.Read(ptr, size, error);
}
static bool
input_nfs_eof(InputStream *is)
{
NfsInputStream &s = *(NfsInputStream *)is;
return s.IsEOF();
}
static bool
input_nfs_seek(InputStream *is,
InputPlugin::offset_type offset, int whence,
Error &error)
{
NfsInputStream &s = *(NfsInputStream *)is;
return s.Seek(offset, whence, error);
}
const InputPlugin input_plugin_nfs = { const InputPlugin input_plugin_nfs = {
"nfs", "nfs",
nullptr, nullptr,
nullptr, nullptr,
input_nfs_open, input_nfs_open,
nullptr,
nullptr,
nullptr,
nullptr,
input_nfs_read,
input_nfs_eof,
input_nfs_seek,
}; };

View File

@ -26,7 +26,12 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
extern const InputPlugin rewind_input_plugin; static const InputPlugin rewind_input_plugin = {
nullptr,
nullptr,
nullptr,
nullptr,
};
class RewindInputStream final : public InputStream { class RewindInputStream final : public InputStream {
InputStream *input; InputStream *input;
@ -63,30 +68,31 @@ public:
delete input; delete input;
} }
bool Check(Error &error) { /* virtual methods from InputStream */
bool Check(Error &error) override {
return input->Check(error); return input->Check(error);
} }
void Update() { void Update() override {
if (!ReadingFromBuffer()) if (!ReadingFromBuffer())
CopyAttributes(); CopyAttributes();
} }
Tag *ReadTag() { bool IsEOF() override {
return input->ReadTag();
}
bool IsAvailable() {
return input->IsAvailable();
}
size_t Read(void *ptr, size_t size, Error &error);
bool IsEOF() {
return !ReadingFromBuffer() && input->IsEOF(); return !ReadingFromBuffer() && input->IsEOF();
} }
bool Seek(InputPlugin::offset_type offset, int whence, Error &error); Tag *ReadTag() override {
return input->ReadTag();
}
bool IsAvailable() override {
return input->IsAvailable();
}
size_t Read(void *ptr, size_t size, Error &error) override;
bool Seek(offset_type offset, int whence, Error &error) override;
private: private:
/** /**
@ -121,39 +127,7 @@ private:
} }
}; };
static bool size_t
input_rewind_check(InputStream *is, Error &error)
{
RewindInputStream *r = (RewindInputStream *)is;
return r->Check(error);
}
static void
input_rewind_update(InputStream *is)
{
RewindInputStream *r = (RewindInputStream *)is;
r->Update();
}
static Tag *
input_rewind_tag(InputStream *is)
{
RewindInputStream *r = (RewindInputStream *)is;
return r->ReadTag();
}
static bool
input_rewind_available(InputStream *is)
{
RewindInputStream *r = (RewindInputStream *)is;
return r->IsAvailable();
}
inline size_t
RewindInputStream::Read(void *ptr, size_t read_size, Error &error) RewindInputStream::Read(void *ptr, size_t read_size, Error &error)
{ {
if (ReadingFromBuffer()) { if (ReadingFromBuffer()) {
@ -193,23 +167,6 @@ RewindInputStream::Read(void *ptr, size_t read_size, Error &error)
} }
} }
static size_t
input_rewind_read(InputStream *is, void *ptr, size_t size,
Error &error)
{
RewindInputStream *r = (RewindInputStream *)is;
return r->Read(ptr, size, error);
}
static bool
input_rewind_eof(InputStream *is)
{
RewindInputStream *r = (RewindInputStream *)is;
return r->IsEOF();
}
inline bool inline bool
RewindInputStream::Seek(InputPlugin::offset_type new_offset, int whence, RewindInputStream::Seek(InputPlugin::offset_type new_offset, int whence,
Error &error) Error &error)
@ -240,30 +197,6 @@ RewindInputStream::Seek(InputPlugin::offset_type new_offset, int whence,
} }
} }
static bool
input_rewind_seek(InputStream *is, InputPlugin::offset_type offset,
int whence,
Error &error)
{
RewindInputStream *r = (RewindInputStream *)is;
return r->Seek(offset, whence, error);
}
const InputPlugin rewind_input_plugin = {
nullptr,
nullptr,
nullptr,
nullptr,
input_rewind_check,
input_rewind_update,
input_rewind_tag,
input_rewind_available,
input_rewind_read,
input_rewind_eof,
input_rewind_seek,
};
InputStream * InputStream *
input_rewind_open(InputStream *is) input_rewind_open(InputStream *is)
{ {

View File

@ -50,34 +50,14 @@ public:
smbclient_mutex.unlock(); smbclient_mutex.unlock();
} }
bool IsEOF() const { /* virtual methods from InputStream */
bool IsEOF() override {
return offset >= size; return offset >= size;
} }
size_t Read(void *ptr, size_t read_size, Error &error) { size_t Read(void *ptr, size_t size, Error &error) override;
smbclient_mutex.lock(); bool Seek(offset_type offset, int whence, Error &error) override;
ssize_t nbytes = smbc_read(fd, ptr, read_size);
smbclient_mutex.unlock();
if (nbytes < 0) {
error.SetErrno("smbc_read() failed");
nbytes = 0;
}
return nbytes;
}
bool Seek(InputStream::offset_type new_offset, int whence, Error &error) {
smbclient_mutex.lock();
off_t result = smbc_lseek(fd, new_offset, whence);
smbclient_mutex.unlock();
if (result < 0) {
error.SetErrno("smbc_lseek() failed");
return false;
}
offset = result;
return true;
}
}; };
/* /*
@ -141,28 +121,34 @@ input_smbclient_open(const char *uri,
return new SmbclientInputStream(uri, mutex, cond, ctx, fd, st); return new SmbclientInputStream(uri, mutex, cond, ctx, fd, st);
} }
static size_t size_t
input_smbclient_read(InputStream *is, void *ptr, size_t size, SmbclientInputStream::Read(void *ptr, size_t read_size, Error &error)
Error &error)
{ {
SmbclientInputStream &s = *(SmbclientInputStream *)is; smbclient_mutex.lock();
return s.Read(ptr, size, error); ssize_t nbytes = smbc_read(fd, ptr, read_size);
smbclient_mutex.unlock();
if (nbytes < 0) {
error.SetErrno("smbc_read() failed");
nbytes = 0;
}
return nbytes;
} }
static bool bool
input_smbclient_eof(InputStream *is) SmbclientInputStream::Seek(InputStream::offset_type new_offset,
int whence, Error &error)
{ {
SmbclientInputStream &s = *(SmbclientInputStream *)is; smbclient_mutex.lock();
return s.IsEOF(); off_t result = smbc_lseek(fd, new_offset, whence);
} smbclient_mutex.unlock();
if (result < 0) {
error.SetErrno("smbc_lseek() failed");
return false;
}
static bool offset = result;
input_smbclient_seek(InputStream *is, return true;
InputPlugin::offset_type offset, int whence,
Error &error)
{
SmbclientInputStream &s = *(SmbclientInputStream *)is;
return s.Seek(offset, whence, error);
} }
const InputPlugin input_plugin_smbclient = { const InputPlugin input_plugin_smbclient = {
@ -170,11 +156,4 @@ const InputPlugin input_plugin_smbclient = {
input_smbclient_init, input_smbclient_init,
nullptr, nullptr,
input_smbclient_open, input_smbclient_open,
nullptr,
nullptr,
nullptr,
nullptr,
input_smbclient_read,
input_smbclient_eof,
input_smbclient_seek,
}; };