aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2011-09-16 21:06:12 +0200
committerMax Kellermann <max@duempel.org>2011-09-16 21:22:02 +0200
commit29241c4f835797f635816a9f37528aa981f722b5 (patch)
treeda166b242c4d960619498b9b7bd13ec44415915d
parent6f655eb9b90e0855112038c0779eb61194cb7ef6 (diff)
downloadmpd-29241c4f835797f635816a9f37528aa981f722b5.tar.gz
mpd-29241c4f835797f635816a9f37528aa981f722b5.tar.xz
mpd-29241c4f835797f635816a9f37528aa981f722b5.zip
input_plugin: add method check()
To check for errors without reading. The decoder thread wants to do that, before it passes the input stream to the plugin.
-rw-r--r--src/input/curl_input_plugin.c18
-rw-r--r--src/input/rewind_input_plugin.c9
-rw-r--r--src/input/soup_input_plugin.c18
-rw-r--r--src/input_plugin.h8
-rw-r--r--src/input_stream.c10
-rw-r--r--src/input_stream.h9
-rw-r--r--test/run_input.c6
7 files changed, 78 insertions, 0 deletions
diff --git a/src/input/curl_input_plugin.c b/src/input/curl_input_plugin.c
index 824fc9bad..4f3e9c6e4 100644
--- a/src/input/curl_input_plugin.c
+++ b/src/input/curl_input_plugin.c
@@ -774,6 +774,23 @@ input_curl_free(struct input_curl *c)
g_free(c);
}
+static bool
+input_curl_check(struct input_stream *is, GError **error_r)
+{
+ struct input_curl *c = (struct input_curl *)is;
+
+ g_mutex_lock(c->mutex);
+
+ bool success = c->postponed_error == NULL;
+ if (!success) {
+ g_propagate_error(error_r, c->postponed_error);
+ c->postponed_error = NULL;
+ }
+
+ g_mutex_unlock(c->mutex);
+ return success;
+}
+
static struct tag *
input_curl_tag(struct input_stream *is)
{
@@ -1318,6 +1335,7 @@ const struct input_plugin input_plugin_curl = {
.open = input_curl_open,
.close = input_curl_close,
+ .check = input_curl_check,
.tag = input_curl_tag,
.buffer = input_curl_buffer,
.read = input_curl_read,
diff --git a/src/input/rewind_input_plugin.c b/src/input/rewind_input_plugin.c
index fa2065d61..2a3eecf82 100644
--- a/src/input/rewind_input_plugin.c
+++ b/src/input/rewind_input_plugin.c
@@ -107,6 +107,14 @@ input_rewind_close(struct input_stream *is)
g_free(r);
}
+static bool
+input_rewind_check(struct input_stream *is, GError **error_r)
+{
+ struct input_rewind *r = (struct input_rewind *)is;
+
+ return input_stream_check(r->input, error_r);
+}
+
static void
input_rewind_update(struct input_stream *is)
{
@@ -221,6 +229,7 @@ input_rewind_seek(struct input_stream *is, goffset offset, int whence,
static const struct input_plugin rewind_input_plugin = {
.close = input_rewind_close,
+ .check = input_rewind_check,
.update = input_rewind_update,
.tag = input_rewind_tag,
.buffer = input_rewind_buffer,
diff --git a/src/input/soup_input_plugin.c b/src/input/soup_input_plugin.c
index ff73da559..23665c1a2 100644
--- a/src/input/soup_input_plugin.c
+++ b/src/input/soup_input_plugin.c
@@ -320,6 +320,23 @@ input_soup_close(struct input_stream *is)
g_free(s);
}
+static bool
+input_soup_check(struct input_stream *is, GError **error_r)
+{
+ struct input_soup *s = (struct input_soup *)is;
+
+ g_mutex_lock(s->mutex);
+
+ bool success = s->postponed_error == NULL;
+ if (!success) {
+ g_propagate_error(error_r, s->postponed_error);
+ s->postponed_error = NULL;
+ }
+
+ g_mutex_unlock(s->mutex);
+ return success;
+}
+
static int
input_soup_buffer(struct input_stream *is, GError **error_r)
{
@@ -444,6 +461,7 @@ const struct input_plugin input_plugin_soup = {
.open = input_soup_open,
.close = input_soup_close,
+ .check = input_soup_check,
.buffer = input_soup_buffer,
.read = input_soup_read,
.eof = input_soup_eof,
diff --git a/src/input_plugin.h b/src/input_plugin.h
index 3ac0bdf40..4e0993d12 100644
--- a/src/input_plugin.h
+++ b/src/input_plugin.h
@@ -52,6 +52,14 @@ struct input_plugin {
void (*close)(struct input_stream *is);
/**
+ * Check for errors that may have occurred in the I/O thread.
+ * May be unimplemented for synchronous plugins.
+ *
+ * @return false on error
+ */
+ bool (*check)(struct input_stream *is, GError **error_r);
+
+ /**
* Update the public attributes. Call before access. Can be
* NULL if the plugin always keeps its attributes up to date.
*/
diff --git a/src/input_stream.c b/src/input_stream.c
index 44ab7159f..164df9860 100644
--- a/src/input_stream.c
+++ b/src/input_stream.c
@@ -67,6 +67,16 @@ input_stream_open(const char *url, GError **error_r)
return NULL;
}
+bool
+input_stream_check(struct input_stream *is, GError **error_r)
+{
+ assert(is != NULL);
+ assert(is->plugin != NULL);
+
+ return is->plugin->check == NULL ||
+ is->plugin->check(is, error_r);
+}
+
void
input_stream_update(struct input_stream *is)
{
diff --git a/src/input_stream.h b/src/input_stream.h
index 2901f6ea6..7866562ae 100644
--- a/src/input_stream.h
+++ b/src/input_stream.h
@@ -91,6 +91,15 @@ void
input_stream_close(struct input_stream *is);
/**
+ * Check for errors that may have occurred in the I/O thread.
+ *
+ * @return false on error
+ */
+gcc_nonnull(1)
+bool
+input_stream_check(struct input_stream *is, GError **error_r);
+
+/**
* Update the public attributes. Call before accessing attributes
* such as "ready" or "offset".
*/
diff --git a/test/run_input.c b/test/run_input.c
index c00698dff..651d36480 100644
--- a/test/run_input.c
+++ b/test/run_input.c
@@ -100,6 +100,12 @@ dump_input_stream(struct input_stream *is)
break;
}
+ if (!input_stream_check(is, &error)) {
+ g_warning("%s", error->message);
+ g_error_free(error);
+ return EXIT_FAILURE;
+ }
+
return 0;
}