diff options
Diffstat (limited to '')
-rw-r--r-- | src/decoder/_flac_common.h | 2 | ||||
-rw-r--r-- | src/decoder/sidplay_decoder_plugin.cxx | 8 | ||||
-rw-r--r-- | src/decoder_control.c | 3 | ||||
-rw-r--r-- | src/decoder_control.h | 51 | ||||
-rw-r--r-- | src/decoder_error.h | 35 | ||||
-rw-r--r-- | src/decoder_thread.c | 18 |
6 files changed, 110 insertions, 7 deletions
diff --git a/src/decoder/_flac_common.h b/src/decoder/_flac_common.h index 0d90ba656..c898a47cf 100644 --- a/src/decoder/_flac_common.h +++ b/src/decoder/_flac_common.h @@ -27,8 +27,6 @@ #include "decoder_api.h" #include "pcm_buffer.h" -#include <glib.h> - #include <FLAC/stream_decoder.h> #include <FLAC/metadata.h> diff --git a/src/decoder/sidplay_decoder_plugin.cxx b/src/decoder/sidplay_decoder_plugin.cxx index 5d162f179..de2e599e9 100644 --- a/src/decoder/sidplay_decoder_plugin.cxx +++ b/src/decoder/sidplay_decoder_plugin.cxx @@ -104,7 +104,7 @@ sidplay_init(const struct config_param *param) return true; } -void +static void sidplay_finish() { g_pattern_spec_free(path_with_subtune); @@ -136,7 +136,7 @@ get_container_name(const char *path_fs) * returns tune number from file.sid/tune_xxx.sid style path or 1 if * no subtune is appended */ -static int +static unsigned get_song_num(const char *path_fs) { if(g_pattern_match(path_with_subtune, @@ -172,7 +172,7 @@ get_song_length(const char *path_fs) char md5sum[SIDTUNE_MD5_LENGTH+1]; tune.createMD5(md5sum); - int song_num=get_song_num(path_fs); + const unsigned song_num = get_song_num(path_fs); gsize num_items; gchar **values=g_key_file_get_string_list(songlength_database, @@ -330,7 +330,7 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs) decoder_command_finished(decoder); } - if (song_len > 0 && player.time() >= song_len) + if (song_len > 0 && player.time() >= (unsigned)song_len) break; } while (cmd != DECODE_COMMAND_STOP); 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; |