InputStream: convert to class

This commit is contained in:
Max Kellermann
2014-05-11 15:34:48 +02:00
parent ee2afb35dd
commit 6773adc771
31 changed files with 132 additions and 70 deletions

View File

@@ -35,7 +35,7 @@
#endif
struct config_param;
struct InputStream;
class InputStream;
class Error;
struct Tag;

View File

@@ -92,6 +92,15 @@ InputStream::Update()
plugin.update(this);
}
void
InputStream::SetReady()
{
assert(!ready);
ready = true;
cond.broadcast();
}
void
InputStream::WaitReady()
{

View File

@@ -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();
/**
@@ -168,6 +194,13 @@ struct InputStream {
*/
void LockWaitReady();
gcc_pure
bool HasMimeType() const {
assert(ready);
return !mime.empty();
}
gcc_pure
const char *GetMimeType() const {
assert(ready);
@@ -175,6 +208,19 @@ struct InputStream {
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
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);

View File

@@ -24,7 +24,7 @@
#include <string>
struct InputStream;
class InputStream;
class TextInputStream {
InputStream &is;

View File

@@ -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();

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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:

View File

@@ -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() {

View File

@@ -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 = {

View File

@@ -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->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;
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;
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;

View File

@@ -29,7 +29,7 @@
#include "check.h"
struct InputStream;
class InputStream;
InputStream *
input_rewind_open(InputStream *is);