aboutsummaryrefslogtreecommitdiffstats
path: root/src/input
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-12-30 23:27:37 +0100
committerMax Kellermann <max@duempel.org>2010-01-01 17:25:07 +0100
commitd3b763a48c09a60a0c0b5ccb6cccd9376875c470 (patch)
tree83b8794f78ef8941806cf5757888d8abf2eaa126 /src/input
parent816b6ad4a71c3ade95e62b62396f2b0415c03f20 (diff)
downloadmpd-d3b763a48c09a60a0c0b5ccb6cccd9376875c470.tar.gz
mpd-d3b763a48c09a60a0c0b5ccb6cccd9376875c470.tar.xz
mpd-d3b763a48c09a60a0c0b5ccb6cccd9376875c470.zip
input_stream: return allocated input_stream objects
Major API redesign: don't let the caller allocate the input_stream object. Let each input plugin allocate its own (derived/extended) input_stream pointer. The "data" attribute can now be removed, and all input plugins simply cast the input_stream pointer to their own structure (with an "struct input_stream base" as the first attribute).
Diffstat (limited to '')
-rw-r--r--src/input/archive_input_plugin.c19
-rw-r--r--src/input/curl_input_plugin.c97
-rw-r--r--src/input/file_input_plugin.c44
-rw-r--r--src/input/mms_input_plugin.c27
-rw-r--r--src/input/rewind_input_plugin.c77
-rw-r--r--src/input/rewind_input_plugin.h6
-rw-r--r--src/input_plugin.h3
-rw-r--r--src/input_stream.c24
-rw-r--r--src/input_stream.h27
9 files changed, 162 insertions, 162 deletions
diff --git a/src/input/archive_input_plugin.c b/src/input/archive_input_plugin.c
index 9e3e79692..97e4836ff 100644
--- a/src/input/archive_input_plugin.c
+++ b/src/input/archive_input_plugin.c
@@ -33,24 +33,23 @@
* parent_stream so tar plugin fetches file data from gzip
* plugin and gzip fetches file from disk
*/
-static bool
-input_archive_open(struct input_stream *is, const char *pathname,
- GError **error_r)
+static struct input_stream *
+input_archive_open(const char *pathname, GError **error_r)
{
const struct archive_plugin *arplug;
struct archive_file *file;
char *archive, *filename, *suffix, *pname;
- bool opened;
+ struct input_stream *is;
if (!g_path_is_absolute(pathname))
- return false;
+ return NULL;
pname = g_strdup(pathname);
// archive_lookup will modify pname when true is returned
if (!archive_lookup(pname, &archive, &filename, &suffix)) {
g_debug("not an archive, lookup %s failed\n", pname);
g_free(pname);
- return false;
+ return NULL;
}
//check which archive plugin to use (by ext)
@@ -58,19 +57,19 @@ input_archive_open(struct input_stream *is, const char *pathname,
if (!arplug) {
g_warning("can't handle archive %s\n",archive);
g_free(pname);
- return false;
+ return NULL;
}
file = archive_file_open(arplug, archive, error_r);
if (file == NULL)
- return false;
+ return NULL;
//setup fileops
- opened = archive_file_open_stream(file, is, filename, error_r);
+ is = archive_file_open_stream(file, filename, error_r);
archive_file_close(file);
g_free(pname);
- return opened;
+ return is;
}
const struct input_plugin input_plugin_archive = {
diff --git a/src/input/curl_input_plugin.c b/src/input/curl_input_plugin.c
index 53f2e0404..c54d994e8 100644
--- a/src/input/curl_input_plugin.c
+++ b/src/input/curl_input_plugin.c
@@ -57,6 +57,8 @@ struct buffer {
};
struct input_curl {
+ struct input_stream base;
+
/* some buffers which were passed to libcurl, which we have
too free */
char *url, *range;
@@ -179,10 +181,8 @@ input_curl_easy_free(struct input_curl *c)
* Frees this stream (but not the input_stream struct itself).
*/
static void
-input_curl_free(struct input_stream *is)
+input_curl_free(struct input_curl *c)
{
- struct input_curl *c = is->data;
-
if (c->tag != NULL)
tag_free(c->tag);
g_free(c->meta_name);
@@ -201,7 +201,7 @@ input_curl_free(struct input_stream *is)
static struct tag *
input_curl_tag(struct input_stream *is)
{
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)is;
struct tag *tag = c->tag;
c->tag = NULL;
@@ -209,9 +209,8 @@ input_curl_tag(struct input_stream *is)
}
static bool
-input_curl_multi_info_read(struct input_stream *is, GError **error_r)
+input_curl_multi_info_read(struct input_curl *c, GError **error_r)
{
- struct input_curl *c = is->data;
CURLMsg *msg;
int msgs_in_queue;
@@ -219,7 +218,7 @@ input_curl_multi_info_read(struct input_stream *is, GError **error_r)
&msgs_in_queue)) != NULL) {
if (msg->msg == CURLMSG_DONE) {
c->eof = true;
- is->ready = true;
+ c->base.ready = true;
if (msg->data.result != CURLE_OK) {
g_set_error(error_r, curl_quark(),
@@ -279,7 +278,7 @@ input_curl_select(struct input_curl *c, GError **error_r)
static bool
fill_buffer(struct input_stream *is, GError **error_r)
{
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)is;
CURLMcode mcode = CURLM_CALL_MULTI_PERFORM;
while (!c->eof && g_queue_is_empty(c->buffers)) {
@@ -305,7 +304,7 @@ fill_buffer(struct input_stream *is, GError **error_r)
return false;
}
- bret = input_curl_multi_info_read(is, error_r);
+ bret = input_curl_multi_info_read(c, error_r);
if (!bret)
return false;
}
@@ -407,7 +406,7 @@ static size_t
input_curl_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
{
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)is;
bool success;
size_t nbytes = 0;
char *dest = ptr;
@@ -441,13 +440,15 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size,
static void
input_curl_close(struct input_stream *is)
{
- input_curl_free(is);
+ struct input_curl *c = (struct input_curl *)is;
+
+ input_curl_free(c);
}
static bool
input_curl_eof(G_GNUC_UNUSED struct input_stream *is)
{
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)is;
return c->eof && g_queue_is_empty(c->buffers);
}
@@ -455,7 +456,7 @@ input_curl_eof(G_GNUC_UNUSED struct input_stream *is)
static int
input_curl_buffer(struct input_stream *is, GError **error_r)
{
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)is;
CURLMcode mcode;
int running_handles;
bool ret;
@@ -483,7 +484,7 @@ input_curl_buffer(struct input_stream *is, GError **error_r)
return -1;
}
- ret = input_curl_multi_info_read(is, error_r);
+ ret = input_curl_multi_info_read(c, error_r);
if (!ret)
return -1;
@@ -494,8 +495,7 @@ input_curl_buffer(struct input_stream *is, GError **error_r)
static size_t
input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
- struct input_stream *is = stream;
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)stream;
const char *header = ptr, *end, *value;
char name[64];
@@ -524,7 +524,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
if (g_ascii_strcasecmp(name, "accept-ranges") == 0) {
/* a stream with icy-metadata is not seekable */
if (!icy_defined(&c->icy_metadata))
- is->seekable = true;
+ c->base.seekable = true;
} else if (g_ascii_strcasecmp(name, "content-length") == 0) {
char buffer[64];
@@ -534,10 +534,10 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
memcpy(buffer, value, end - value);
buffer[end - value] = 0;
- is->size = is->offset + g_ascii_strtoull(buffer, NULL, 10);
+ c->base.size = c->base.offset + g_ascii_strtoull(buffer, NULL, 10);
} else if (g_ascii_strcasecmp(name, "content-type") == 0) {
- g_free(is->mime);
- is->mime = g_strndup(value, end - value);
+ g_free(c->base.mime);
+ c->base.mime = g_strndup(value, end - value);
} else if (g_ascii_strcasecmp(name, "icy-name") == 0 ||
g_ascii_strcasecmp(name, "ice-name") == 0 ||
g_ascii_strcasecmp(name, "x-audiocast-name") == 0) {
@@ -568,7 +568,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
/* a stream with icy-metadata is not
seekable */
- is->seekable = false;
+ c->base.seekable = false;
}
}
@@ -579,8 +579,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
static size_t
input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
- struct input_stream *is = stream;
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)stream;
struct buffer *buffer;
size *= nmemb;
@@ -594,15 +593,14 @@ input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
g_queue_push_tail(c->buffers, buffer);
c->buffered = true;
- is->ready = true;
+ c->base.ready = true;
return size;
}
static bool
-input_curl_easy_init(struct input_stream *is, GError **error_r)
+input_curl_easy_init(struct input_curl *c, GError **error_r)
{
- struct input_curl *c = is->data;
CURLcode code;
CURLMcode mcode;
@@ -627,10 +625,10 @@ input_curl_easy_init(struct input_stream *is, GError **error_r)
"Music Player Daemon " VERSION);
curl_easy_setopt(c->easy, CURLOPT_HEADERFUNCTION,
input_curl_headerfunction);
- curl_easy_setopt(c->easy, CURLOPT_WRITEHEADER, is);
+ curl_easy_setopt(c->easy, CURLOPT_WRITEHEADER, c);
curl_easy_setopt(c->easy, CURLOPT_WRITEFUNCTION,
input_curl_writefunction);
- curl_easy_setopt(c->easy, CURLOPT_WRITEDATA, is);
+ curl_easy_setopt(c->easy, CURLOPT_WRITEDATA, c);
curl_easy_setopt(c->easy, CURLOPT_HTTP200ALIASES, http_200_aliases);
curl_easy_setopt(c->easy, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(c->easy, CURLOPT_MAXREDIRS, 5);
@@ -669,9 +667,9 @@ input_curl_easy_init(struct input_stream *is, GError **error_r)
void
input_curl_reinit(struct input_stream *is)
{
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)is;
- assert(is->plugin == &input_plugin_curl);
+ assert(c->base.plugin == &input_plugin_curl);
assert(c->easy != NULL);
curl_easy_setopt(c->easy, CURLOPT_WRITEHEADER, is);
@@ -702,7 +700,7 @@ static bool
input_curl_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r)
{
- struct input_curl *c = is->data;
+ struct input_curl *c = (struct input_curl *)is;
bool ret;
assert(is->ready);
@@ -774,7 +772,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
return true;
}
- ret = input_curl_easy_init(is, error_r);
+ ret = input_curl_easy_init(c, error_r);
if (!ret)
return false;
@@ -789,55 +787,54 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
if (!ret)
return false;
- return input_curl_multi_info_read(is, error_r);
+ return input_curl_multi_info_read(c, error_r);
}
-static bool
-input_curl_open(struct input_stream *is, const char *url, GError **error_r)
+static struct input_stream *
+input_curl_open(const char *url, GError **error_r)
{
struct input_curl *c;
bool ret;
if (strncmp(url, "http://", 7) != 0)
- return false;
+ return NULL;
c = g_new0(struct input_curl, 1);
+ input_stream_init(&c->base, &input_plugin_curl);
+
c->url = g_strdup(url);
c->buffers = g_queue_new();
- is->plugin = &input_plugin_curl;
- is->data = c;
-
c->multi = curl_multi_init();
if (c->multi == NULL) {
g_set_error(error_r, curl_quark(), 0,
"curl_multi_init() failed");
- input_curl_free(is);
- return false;
+ input_curl_free(c);
+ return NULL;
}
icy_clear(&c->icy_metadata);
c->tag = NULL;
- ret = input_curl_easy_init(is, error_r);
+ ret = input_curl_easy_init(c, error_r);
if (!ret) {
- input_curl_free(is);
- return false;
+ input_curl_free(c);
+ return NULL;
}
ret = input_curl_send_request(c, error_r);
if (!ret) {
- input_curl_free(is);
- return false;
+ input_curl_free(c);
+ return NULL;
}
- ret = input_curl_multi_info_read(is, error_r);
+ ret = input_curl_multi_info_read(c, error_r);
if (!ret) {
- input_curl_free(is);
- return false;
+ input_curl_free(c);
+ return NULL;
}
- return true;
+ return &c->base;
}
const struct input_plugin input_plugin_curl = {
diff --git a/src/input/file_input_plugin.c b/src/input/file_input_plugin.c
index 92da42290..1c5813f88 100644
--- a/src/input/file_input_plugin.c
+++ b/src/input/file_input_plugin.c
@@ -32,18 +32,24 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "input_file"
+struct file_input_stream {
+ struct input_stream base;
+
+ int fd;
+};
+
static inline GQuark
file_quark(void)
{
return g_quark_from_static_string("file");
}
-static bool
-input_file_open(struct input_stream *is, const char *filename,
- GError **error_r)
+static struct input_stream *
+input_file_open(const char *filename, GError **error_r)
{
int fd, ret;
struct stat st;
+ struct file_input_stream *fis;
if (!g_path_is_absolute(filename))
return false;
@@ -57,8 +63,6 @@ input_file_open(struct input_stream *is, const char *filename,
return false;
}
- is->seekable = true;
-
ret = fstat(fd, &st);
if (ret < 0) {
g_set_error(error_r, file_quark(), errno,
@@ -75,26 +79,29 @@ input_file_open(struct input_stream *is, const char *filename,
return false;
}
- is->size = st.st_size;
-
#ifdef POSIX_FADV_SEQUENTIAL
- posix_fadvise(fd, (off_t)0, is->size, POSIX_FADV_SEQUENTIAL);
+ posix_fadvise(fd, (off_t)0, st.st_size, POSIX_FADV_SEQUENTIAL);
#endif
- is->plugin = &input_plugin_file;
- is->data = GINT_TO_POINTER(fd);
- is->ready = true;
+ fis = g_new(struct file_input_stream, 1);
+ input_stream_init(&fis->base, &input_plugin_file);
- return true;
+ fis->base.size = st.st_size;
+ fis->base.seekable = true;
+ fis->base.ready = true;
+
+ fis->fd = fd;
+
+ return &fis->base;
}
static bool
input_file_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r)
{
- int fd = GPOINTER_TO_INT(is->data);
+ struct file_input_stream *fis = (struct file_input_stream *)is;
- offset = (goffset)lseek(fd, (off_t)offset, whence);
+ offset = (goffset)lseek(fis->fd, (off_t)offset, whence);
if (offset < 0) {
g_set_error(error_r, file_quark(), errno,
"Failed to seek: %s", g_strerror(errno));
@@ -109,10 +116,10 @@ static size_t
input_file_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
{
- int fd = GPOINTER_TO_INT(is->data);
+ struct file_input_stream *fis = (struct file_input_stream *)is;
ssize_t nbytes;
- nbytes = read(fd, ptr, size);
+ nbytes = read(fis->fd, ptr, size);
if (nbytes < 0) {
g_set_error(error_r, file_quark(), errno,
"Failed to read: %s", g_strerror(errno));
@@ -126,9 +133,10 @@ input_file_read(struct input_stream *is, void *ptr, size_t size,
static void
input_file_close(struct input_stream *is)
{
- int fd = GPOINTER_TO_INT(is->data);
+ struct file_input_stream *fis = (struct file_input_stream *)is;
- close(fd);
+ close(fis->fd);
+ g_free(fis);
}
static bool
diff --git a/src/input/mms_input_plugin.c b/src/input/mms_input_plugin.c
index e7dc56bc8..5055eb05e 100644
--- a/src/input/mms_input_plugin.c
+++ b/src/input/mms_input_plugin.c
@@ -31,6 +31,8 @@
#define G_LOG_DOMAIN "input_mms"
struct input_mms {
+ struct input_stream base;
+
mmsx_t *mms;
bool eof;
@@ -42,8 +44,8 @@ mms_quark(void)
return g_quark_from_static_string("mms");
}
-static bool
-input_mms_open(struct input_stream *is, const char *url, GError **error_r)
+static struct input_stream *
+input_mms_open(const char *url, GError **error_r)
{
struct input_mms *m;
@@ -51,30 +53,31 @@ input_mms_open(struct input_stream *is, const char *url, GError **error_r)
!g_str_has_prefix(url, "mmsh://") &&
!g_str_has_prefix(url, "mmst://") &&
!g_str_has_prefix(url, "mmsu://"))
- return false;
+ return NULL;
m = g_new(struct input_mms, 1);
+ input_stream_init(&m->base, &input_plugin_mms);
+
m->mms = mmsx_connect(NULL, NULL, url, 128 * 1024);
if (m->mms == NULL) {
g_set_error(error_r, mms_quark(), 0, "mmsx_connect() failed");
- return false;
+ return NULL;
}
/* XX is this correct? at least this selects the ffmpeg
decoder, which seems to work fine*/
- is->mime = g_strdup("audio/x-ms-wma");
+ m->base.mime = g_strdup("audio/x-ms-wma");
+
+ m->base.ready = true;
- is->plugin = &input_plugin_mms;
- is->data = m;
- is->ready = true;
- return true;
+ return &m->base;
}
static size_t
input_mms_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
{
- struct input_mms *m = is->data;
+ struct input_mms *m = (struct input_mms *)is;
int ret;
ret = mmsx_read(NULL, m->mms, ptr, size);
@@ -97,7 +100,7 @@ input_mms_read(struct input_stream *is, void *ptr, size_t size,
static void
input_mms_close(struct input_stream *is)
{
- struct input_mms *m = is->data;
+ struct input_mms *m = (struct input_mms *)is;
mmsx_close(m->mms);
g_free(m);
@@ -106,7 +109,7 @@ input_mms_close(struct input_stream *is)
static bool
input_mms_eof(struct input_stream *is)
{
- struct input_mms *m = is->data;
+ struct input_mms *m = (struct input_mms *)is;
return m->eof;
}
diff --git a/src/input/rewind_input_plugin.c b/src/input/rewind_input_plugin.c
index 54efa75fb..68b3e8036 100644
--- a/src/input/rewind_input_plugin.c
+++ b/src/input/rewind_input_plugin.c
@@ -32,7 +32,9 @@
#define G_LOG_DOMAIN "input_rewind"
struct input_rewind {
- struct input_stream input;
+ struct input_stream base;
+
+ struct input_stream *input;
/**
* The read position within the buffer. Undefined as long as
@@ -61,11 +63,9 @@ struct input_rewind {
* contain more data for the next read operation?
*/
static bool
-reading_from_buffer(const struct input_stream *is)
+reading_from_buffer(const struct input_rewind *r)
{
- const struct input_rewind *r = is->data;
-
- return r->tail > 0 && is->offset < r->input.offset;
+ return r->tail > 0 && r->base.offset < r->input->offset;
}
/**
@@ -75,10 +75,10 @@ reading_from_buffer(const struct input_stream *is)
* attributes.
*/
static void
-copy_attributes(struct input_stream *dest)
+copy_attributes(struct input_rewind *r)
{
- const struct input_rewind *r = dest->data;
- const struct input_stream *src = &r->input;
+ struct input_stream *dest = &r->base;
+ const struct input_stream *src = r->input;
dest->ready = src->ready;
dest->seekable = src->seekable;
@@ -94,9 +94,9 @@ copy_attributes(struct input_stream *dest)
static void
input_rewind_close(struct input_stream *is)
{
- struct input_rewind *r = is->data;
+ struct input_rewind *r = (struct input_rewind *)is;
- input_stream_close(&r->input);
+ input_stream_close(r->input);
g_free(r);
}
@@ -104,19 +104,19 @@ input_rewind_close(struct input_stream *is)
static struct tag *
input_rewind_tag(struct input_stream *is)
{
- struct input_rewind *r = is->data;
+ struct input_rewind *r = (struct input_rewind *)is;
- return input_stream_tag(&r->input);
+ return input_stream_tag(r->input);
}
static int
input_rewind_buffer(struct input_stream *is, GError **error_r)
{
- struct input_rewind *r = is->data;
+ struct input_rewind *r = (struct input_rewind *)is;
- int ret = input_stream_buffer(&r->input, error_r);
- if (ret < 0 || !reading_from_buffer(is))
- copy_attributes(is);
+ int ret = input_stream_buffer(r->input, error_r);
+ if (ret < 0 || !reading_from_buffer(r))
+ copy_attributes(r);
return ret;
}
@@ -125,13 +125,13 @@ static size_t
input_rewind_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
{
- struct input_rewind *r = is->data;
+ struct input_rewind *r = (struct input_rewind *)is;
- if (reading_from_buffer(is)) {
+ if (reading_from_buffer(r)) {
/* buffered read */
assert(r->head == (size_t)is->offset);
- assert(r->tail == (size_t)r->input.offset);
+ assert(r->tail == (size_t)r->input->offset);
if (size > r->tail - r->head)
size = r->tail - r->head;
@@ -144,9 +144,9 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size,
} else {
/* pass method call to underlying stream */
- size_t nbytes = input_stream_read(&r->input, ptr, size, error_r);
+ size_t nbytes = input_stream_read(r->input, ptr, size, error_r);
- if (r->input.offset > (goffset)sizeof(r->buffer))
+ if (r->input->offset > (goffset)sizeof(r->buffer))
/* disable buffering */
r->tail = 0;
else if (r->tail == (size_t)is->offset) {
@@ -155,46 +155,46 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size,
memcpy(r->buffer + r->tail, ptr, nbytes);
r->tail += nbytes;
- assert(r->tail == (size_t)r->input.offset);
+ assert(r->tail == (size_t)r->input->offset);
}
- copy_attributes(is);
+ copy_attributes(r);
return nbytes;
}
}
static bool
-input_rewind_eof(G_GNUC_UNUSED struct input_stream *is)
+input_rewind_eof(struct input_stream *is)
{
- struct input_rewind *r = is->data;
+ struct input_rewind *r = (struct input_rewind *)is;
- return !reading_from_buffer(is) && input_stream_eof(&r->input);
+ return !reading_from_buffer(r) && input_stream_eof(r->input);
}
static bool
input_rewind_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r)
{
- struct input_rewind *r = is->data;
+ struct input_rewind *r = (struct input_rewind *)is;
assert(is->ready);
if (whence == SEEK_SET && r->tail > 0 && offset <= (goffset)r->tail) {
/* buffered seek */
- assert(!reading_from_buffer(is) ||
+ assert(!reading_from_buffer(r) ||
r->head == (size_t)is->offset);
- assert(r->tail == (size_t)r->input.offset);
+ assert(r->tail == (size_t)r->input->offset);
r->head = (size_t)offset;
is->offset = offset;
return true;
} else {
- bool success = input_stream_seek(&r->input, offset, whence,
+ bool success = input_stream_seek(r->input, offset, whence,
error_r);
- copy_attributes(is);
+ copy_attributes(r);
/* disable the buffer, because r->input has left the
buffered range now */
@@ -213,7 +213,7 @@ static const struct input_plugin rewind_input_plugin = {
.seek = input_rewind_seek,
};
-void
+struct input_stream *
input_rewind_open(struct input_stream *is)
{
struct input_rewind *c;
@@ -224,17 +224,12 @@ input_rewind_open(struct input_stream *is)
if (is->plugin != &input_plugin_curl)
/* due to limitations in the input_plugin API, we only
(explicitly) support the CURL input plugin */
- return;
+ return is;
c = g_new(struct input_rewind, 1);
+ input_stream_init(&c->base, &rewind_input_plugin);
c->tail = 0;
+ c->input = is;
- /* move the CURL input stream to c->input */
- c->input = *is;
- input_curl_reinit(&c->input);
-
- /* convert the existing input_stream pointer to a "rewind"
- input stream */
- is->plugin = &rewind_input_plugin;
- is->data = c;
+ return &c->base;
}
diff --git a/src/input/rewind_input_plugin.h b/src/input/rewind_input_plugin.h
index 83152e588..27ad169b6 100644
--- a/src/input/rewind_input_plugin.h
+++ b/src/input/rewind_input_plugin.h
@@ -33,15 +33,15 @@ struct input_stream;
#ifdef ENABLE_CURL
-void
+struct input_stream *
input_rewind_open(struct input_stream *is);
#else
-static inline void
+static inline struct input_stream *
input_rewind_open(struct input_stream *is)
{
- (void)is;
+ return is;
}
#endif
diff --git a/src/input_plugin.h b/src/input_plugin.h
index bc48b9d4b..10be48dbb 100644
--- a/src/input_plugin.h
+++ b/src/input_plugin.h
@@ -48,8 +48,7 @@ struct input_plugin {
*/
void (*finish)(void);
- bool (*open)(struct input_stream *is, const char *url,
- GError **error_r);
+ struct input_stream *(*open)(const char *uri, GError **error_r);
void (*close)(struct input_stream *is);
struct tag *(*tag)(struct input_stream *is);
diff --git a/src/input_stream.c b/src/input_stream.c
index 0cf0558d6..96c692176 100644
--- a/src/input_stream.c
+++ b/src/input_stream.c
@@ -32,38 +32,34 @@ input_quark(void)
return g_quark_from_static_string("input");
}
-bool
-input_stream_open(struct input_stream *is, const char *url, GError **error_r)
+struct input_stream *
+input_stream_open(const char *url, GError **error_r)
{
GError *error = NULL;
assert(error_r == NULL || *error_r == NULL);
- is->seekable = false;
- is->ready = false;
- is->offset = 0;
- is->size = -1;
- is->mime = NULL;
-
for (unsigned i = 0; input_plugins[i] != NULL; ++i) {
const struct input_plugin *plugin = input_plugins[i];
+ struct input_stream *is;
if (!input_plugins_enabled[i])
continue;
- if (plugin->open(is, url, &error)) {
+ is = plugin->open(url, &error);
+ if (is != NULL) {
assert(is->plugin != NULL);
assert(is->plugin->close != NULL);
assert(is->plugin->read != NULL);
assert(is->plugin->eof != NULL);
assert(!is->seekable || is->plugin->seek != NULL);
- input_rewind_open(is);
+ is = input_rewind_open(is);
- return true;
+ return is;
} else if (error != NULL) {
g_propagate_error(error_r, error);
- return false;
+ return NULL;
}
}
@@ -103,9 +99,9 @@ input_stream_read(struct input_stream *is, void *ptr, size_t size,
void input_stream_close(struct input_stream *is)
{
- is->plugin->close(is);
-
g_free(is->mime);
+
+ is->plugin->close(is);
}
bool input_stream_eof(struct input_stream *is)
diff --git a/src/input_stream.h b/src/input_stream.h
index 069a9f581..e48f7eb26 100644
--- a/src/input_stream.h
+++ b/src/input_stream.h
@@ -39,11 +39,6 @@ struct input_stream {
const struct input_plugin *plugin;
/**
- * an opaque pointer managed by the plugin
- */
- void *data;
-
- /**
* indicates whether the stream is ready for reading and
* whether the other attributes in this struct are valid
*/
@@ -70,20 +65,28 @@ struct input_stream {
char *mime;
};
+static inline void
+input_stream_init(struct input_stream *is, const struct input_plugin *plugin)
+{
+ is->plugin = plugin;
+ is->ready = false;
+ is->seekable = false;
+ is->size = -1;
+ is->offset = 0;
+ is->mime = NULL;
+}
+
/**
* Opens a new input stream. You may not access it until the "ready"
* flag is set.
*
- * @param is the input_stream object allocated by the caller
- * @return true on success
+ * @return an #input_stream object on success, NULL on error
*/
-bool
-input_stream_open(struct input_stream *is, const char *url, GError **error_r);
+struct input_stream *
+input_stream_open(const char *uri, GError **error_r);
/**
- * Closes the input stream and free resources. This does not free the
- * input_stream pointer itself, because it is assumed to be allocated
- * by the caller.
+ * Close the input stream and free resources.
*/
void
input_stream_close(struct input_stream *is);