aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/decoder_control.c3
-rw-r--r--src/decoder_control.h51
-rw-r--r--src/decoder_error.h35
-rw-r--r--src/decoder_thread.c18
4 files changed, 106 insertions, 1 deletions
diff --git a/src/decoder_control.c b/src/decoder_control.c
index 70f34b331..caa3705f5 100644
--- a/src/decoder_control.c
+++ b/src/decoder_control.c
@@ -52,6 +52,8 @@ dc_new(GCond *client_cond)
void
dc_free(struct decoder_control *dc)
{
+ dc_clear_error(dc);
+
g_cond_free(dc->cond);
g_mutex_free(dc->mutex);
g_free(dc->mixramp_start);
@@ -79,6 +81,7 @@ static void
dc_command(struct decoder_control *dc, enum decoder_command cmd)
{
decoder_lock(dc);
+ dc_clear_error(dc);
dc_command_locked(dc, cmd);
decoder_unlock(dc);
}
diff --git a/src/decoder_control.h b/src/decoder_control.h
index 566b153ee..164875ae0 100644
--- a/src/decoder_control.h
+++ b/src/decoder_control.h
@@ -67,6 +67,14 @@ struct decoder_control {
enum decoder_state state;
enum decoder_command command;
+ /**
+ * The error that occurred in the decoder thread. This
+ * attribute is only valid if #state is #DECODE_STATE_ERROR.
+ * The object must be freed when this object transitions to
+ * any other state (usually #DECODE_STATE_START).
+ */
+ GError *error;
+
bool quit;
bool seek_error;
bool seekable;
@@ -188,6 +196,49 @@ decoder_has_failed(const struct decoder_control *dc)
return dc->state == DECODE_STATE_ERROR;
}
+/**
+ * Checks whether an error has occurred, and if so, returns a newly
+ * allocated copy of the #GError object.
+ *
+ * Caller must lock the object.
+ */
+static inline GError *
+dc_get_error(const struct decoder_control *dc)
+{
+ assert(dc != NULL);
+ assert(dc->command == DECODE_COMMAND_NONE);
+
+ return dc->state == DECODE_STATE_ERROR
+ ? g_error_copy(dc->error)
+ : NULL;
+}
+
+/**
+ * Like dc_get_error(), but locks and unlocks the object.
+ */
+static inline GError *
+dc_lock_get_error(struct decoder_control *dc)
+{
+ decoder_lock(dc);
+ GError *error = dc_get_error(dc);
+ decoder_unlock(dc);
+ return error;
+}
+
+/**
+ * Clear the error condition and free the #GError object (if any).
+ *
+ * Caller must lock the object.
+ */
+static inline void
+dc_clear_error(struct decoder_control *dc)
+{
+ if (dc->state == DECODE_STATE_ERROR) {
+ g_error_free(dc->error);
+ dc->state = DECODE_STATE_STOP;
+ }
+}
+
static inline bool
decoder_lock_is_idle(struct decoder_control *dc)
{
diff --git a/src/decoder_error.h b/src/decoder_error.h
new file mode 100644
index 000000000..a12a31937
--- /dev/null
+++ b/src/decoder_error.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2003-2012 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_DECODER_ERROR_H
+#define MPD_DECODER_ERROR_H
+
+#include <glib.h>
+
+/**
+ * Quark for GError.domain.
+ */
+G_GNUC_CONST
+static inline GQuark
+decoder_quark(void)
+{
+ return g_quark_from_static_string("decoder");
+}
+
+#endif
diff --git a/src/decoder_thread.c b/src/decoder_thread.c
index 1440fc272..11d96b35c 100644
--- a/src/decoder_thread.c
+++ b/src/decoder_thread.c
@@ -19,6 +19,7 @@
#include "config.h"
#include "decoder_thread.h"
+#include "decoder_error.h"
#include "decoder_control.h"
#include "decoder_internal.h"
#include "decoder_list.h"
@@ -428,12 +429,27 @@ decoder_run_song(struct decoder_control *dc,
decoder_lock(dc);
- dc->state = ret ? DECODE_STATE_STOP : DECODE_STATE_ERROR;
+ if (ret)
+ dc->state = DECODE_STATE_STOP;
+ else {
+ dc->state = DECODE_STATE_ERROR;
+
+ const char *error_uri = song->uri;
+ char *allocated = uri_remove_auth(error_uri);
+ if (allocated != NULL)
+ error_uri = allocated;
+
+ dc->error = g_error_new(decoder_quark(), 0,
+ "Failed to decode %s", error_uri);
+ g_free(allocated);
+ }
}
static void
decoder_run(struct decoder_control *dc)
{
+ dc_clear_error(dc);
+
const struct song *song = dc->song;
char *uri;