decoder_control: add GError attribute

This commit is contained in:
Max Kellermann 2012-08-08 21:54:54 +02:00
parent 0b9e912297
commit 8c425c758c
5 changed files with 107 additions and 1 deletions

View File

@ -247,6 +247,7 @@ src_mpd_SOURCES = \
src/conf.c \
src/crossfade.c \
src/cue/cue_parser.c src/cue/cue_parser.h \
src/decoder_error.h \
src/decoder_thread.c \
src/decoder_control.c \
src/decoder_api.c \

View File

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

View File

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

35
src/decoder_error.h Normal file
View File

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

View File

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