player_control: add GError attribute
Rewrite of the pc_get_error_message() function, now using a GError object instead of the complicated "errored_song" attribute.
This commit is contained in:
parent
f794b1e1aa
commit
d488d796f4
1
NEWS
1
NEWS
|
@ -1,4 +1,5 @@
|
||||||
ver 0.18 (2012/??/??)
|
ver 0.18 (2012/??/??)
|
||||||
|
* improved decoder/output error reporting
|
||||||
|
|
||||||
ver 0.17.1 (2012/??/??)
|
ver 0.17.1 (2012/??/??)
|
||||||
* protocol:
|
* protocol:
|
||||||
|
|
|
@ -76,15 +76,6 @@ player_wait_decoder(struct player_control *pc, struct decoder_control *dc)
|
||||||
g_cond_wait(pc->cond, dc->mutex);
|
g_cond_wait(pc->cond, dc->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
pc_song_deleted(struct player_control *pc, const struct song *song)
|
|
||||||
{
|
|
||||||
if (pc->errored_song == song) {
|
|
||||||
pc->error_type = PLAYER_ERROR_NONE;
|
|
||||||
pc->errored_song = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
player_command_wait_locked(struct player_control *pc)
|
player_command_wait_locked(struct player_control *pc)
|
||||||
{
|
{
|
||||||
|
@ -228,43 +219,43 @@ pc_get_status(struct player_control *pc, struct player_status *status)
|
||||||
player_unlock(pc);
|
player_unlock(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pc_set_error(struct player_control *pc, enum player_error type,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
assert(pc != NULL);
|
||||||
|
assert(type != PLAYER_ERROR_NONE);
|
||||||
|
assert(error != NULL);
|
||||||
|
|
||||||
|
if (pc->error_type != PLAYER_ERROR_NONE)
|
||||||
|
g_error_free(pc->error);
|
||||||
|
|
||||||
|
pc->error_type = type;
|
||||||
|
pc->error = error;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pc_clear_error(struct player_control *pc)
|
pc_clear_error(struct player_control *pc)
|
||||||
{
|
{
|
||||||
player_lock(pc);
|
player_lock(pc);
|
||||||
pc->error_type = PLAYER_ERROR_NONE;
|
|
||||||
pc->errored_song = NULL;
|
|
||||||
player_unlock(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
if (pc->error_type != PLAYER_ERROR_NONE) {
|
||||||
pc_errored_song_uri(struct player_control *pc)
|
pc->error_type = PLAYER_ERROR_NONE;
|
||||||
{
|
g_error_free(pc->error);
|
||||||
return song_get_uri(pc->errored_song);
|
}
|
||||||
|
|
||||||
|
player_unlock(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
pc_get_error_message(struct player_control *pc)
|
pc_get_error_message(struct player_control *pc)
|
||||||
{
|
{
|
||||||
char *error;
|
player_lock(pc);
|
||||||
char *uri;
|
char *message = pc->error_type != PLAYER_ERROR_NONE
|
||||||
|
? g_strdup(pc->error->message)
|
||||||
switch (pc->error_type) {
|
: NULL;
|
||||||
case PLAYER_ERROR_NONE:
|
player_unlock(pc);
|
||||||
return NULL;
|
return message;
|
||||||
|
|
||||||
case PLAYER_ERROR_DECODER:
|
|
||||||
uri = pc_errored_song_uri(pc);
|
|
||||||
error = g_strdup_printf("problems decoding \"%s\"", uri);
|
|
||||||
g_free(uri);
|
|
||||||
return error;
|
|
||||||
|
|
||||||
case PLAYER_ERROR_OUTPUT:
|
|
||||||
return g_strdup("problems opening audio device");
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -111,12 +111,19 @@ struct player_control {
|
||||||
|
|
||||||
enum player_error error_type;
|
enum player_error error_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The error that occurred in the player thread. This
|
||||||
|
* attribute is only valid if #error is not
|
||||||
|
* #PLAYER_ERROR_NONE. The object must be freed when this
|
||||||
|
* object transitions back to #PLAYER_ERROR_NONE.
|
||||||
|
*/
|
||||||
|
GError *error;
|
||||||
|
|
||||||
uint16_t bit_rate;
|
uint16_t bit_rate;
|
||||||
struct audio_format audio_format;
|
struct audio_format audio_format;
|
||||||
float total_time;
|
float total_time;
|
||||||
float elapsed_time;
|
float elapsed_time;
|
||||||
struct song *next_song;
|
struct song *next_song;
|
||||||
const struct song *errored_song;
|
|
||||||
double seek_where;
|
double seek_where;
|
||||||
float cross_fade_seconds;
|
float cross_fade_seconds;
|
||||||
float mixramp_db;
|
float mixramp_db;
|
||||||
|
@ -191,14 +198,6 @@ player_lock_signal(struct player_control *pc)
|
||||||
player_unlock(pc);
|
player_unlock(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function when the specified song pointer is about to be
|
|
||||||
* invalidated. This makes sure that player_control.errored_song does
|
|
||||||
* not point to an invalid pointer.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
pc_song_deleted(struct player_control *pc, const struct song *song);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pc_play(struct player_control *pc, struct song *song);
|
pc_play(struct player_control *pc, struct song *song);
|
||||||
|
|
||||||
|
@ -226,6 +225,19 @@ pc_get_state(struct player_control *pc)
|
||||||
return pc->state;
|
return pc->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the error. Discards any previous error condition.
|
||||||
|
*
|
||||||
|
* Caller must lock the object.
|
||||||
|
*
|
||||||
|
* @param type the error type; must not be #PLAYER_ERROR_NONE
|
||||||
|
* @param error detailed error information; must not be NULL; the
|
||||||
|
* #player_control takes over ownership of this #GError instance
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
pc_set_error(struct player_control *pc, enum player_error type,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
void
|
void
|
||||||
pc_clear_error(struct player_control *pc);
|
pc_clear_error(struct player_control *pc);
|
||||||
|
|
||||||
|
|
|
@ -235,10 +235,10 @@ player_wait_for_decoder(struct player *player)
|
||||||
|
|
||||||
player->queued = false;
|
player->queued = false;
|
||||||
|
|
||||||
if (decoder_lock_has_failed(dc)) {
|
GError *error = dc_lock_get_error(dc);
|
||||||
|
if (error != NULL) {
|
||||||
player_lock(pc);
|
player_lock(pc);
|
||||||
pc->errored_song = dc->song;
|
pc_set_error(pc, PLAYER_ERROR_DECODER, error);
|
||||||
pc->error_type = PLAYER_ERROR_DECODER;
|
|
||||||
pc->next_song = NULL;
|
pc->next_song = NULL;
|
||||||
player_unlock(pc);
|
player_unlock(pc);
|
||||||
|
|
||||||
|
@ -318,7 +318,6 @@ player_open_output(struct player *player)
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
|
||||||
|
|
||||||
player->output_open = false;
|
player->output_open = false;
|
||||||
|
|
||||||
|
@ -327,7 +326,7 @@ player_open_output(struct player *player)
|
||||||
player->paused = true;
|
player->paused = true;
|
||||||
|
|
||||||
player_lock(pc);
|
player_lock(pc);
|
||||||
pc->error_type = PLAYER_ERROR_OUTPUT;
|
pc_set_error(pc, PLAYER_ERROR_OUTPUT, error);
|
||||||
pc->state = PLAYER_STATE_PAUSE;
|
pc->state = PLAYER_STATE_PAUSE;
|
||||||
player_unlock(pc);
|
player_unlock(pc);
|
||||||
|
|
||||||
|
@ -352,13 +351,13 @@ player_check_decoder_startup(struct player *player)
|
||||||
|
|
||||||
decoder_lock(dc);
|
decoder_lock(dc);
|
||||||
|
|
||||||
if (decoder_has_failed(dc)) {
|
GError *error = dc_get_error(dc);
|
||||||
|
if (error != NULL) {
|
||||||
/* the decoder failed */
|
/* the decoder failed */
|
||||||
decoder_unlock(dc);
|
decoder_unlock(dc);
|
||||||
|
|
||||||
player_lock(pc);
|
player_lock(pc);
|
||||||
pc->errored_song = dc->song;
|
pc_set_error(pc, PLAYER_ERROR_DECODER, error);
|
||||||
pc->error_type = PLAYER_ERROR_DECODER;
|
|
||||||
player_unlock(pc);
|
player_unlock(pc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -797,13 +796,12 @@ play_next_chunk(struct player *player)
|
||||||
if (!play_chunk(player->pc, player->song, chunk,
|
if (!play_chunk(player->pc, player->song, chunk,
|
||||||
&player->play_audio_format, &error)) {
|
&player->play_audio_format, &error)) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
|
||||||
|
|
||||||
music_buffer_return(player_buffer, chunk);
|
music_buffer_return(player_buffer, chunk);
|
||||||
|
|
||||||
player_lock(pc);
|
player_lock(pc);
|
||||||
|
|
||||||
pc->error_type = PLAYER_ERROR_OUTPUT;
|
pc_set_error(pc, PLAYER_ERROR_OUTPUT, error);
|
||||||
|
|
||||||
/* pause: the user may resume playback as soon as an
|
/* pause: the user may resume playback as soon as an
|
||||||
audio output becomes available */
|
audio output becomes available */
|
||||||
|
|
|
@ -45,14 +45,6 @@ playlist_clear(struct playlist *playlist, struct player_control *pc)
|
||||||
{
|
{
|
||||||
playlist_stop(playlist, pc);
|
playlist_stop(playlist, pc);
|
||||||
|
|
||||||
/* make sure there are no references to allocated songs
|
|
||||||
anymore */
|
|
||||||
for (unsigned i = 0; i < queue_length(&playlist->queue); i++) {
|
|
||||||
const struct song *song = queue_get(&playlist->queue, i);
|
|
||||||
if (!song_in_database(song))
|
|
||||||
pc_song_deleted(pc, song);
|
|
||||||
}
|
|
||||||
|
|
||||||
queue_clear(&playlist->queue);
|
queue_clear(&playlist->queue);
|
||||||
|
|
||||||
playlist->current = -1;
|
playlist->current = -1;
|
||||||
|
@ -287,9 +279,6 @@ playlist_delete_internal(struct playlist *playlist, struct player_control *pc,
|
||||||
|
|
||||||
/* now do it: remove the song */
|
/* now do it: remove the song */
|
||||||
|
|
||||||
if (!song_in_database(queue_get(&playlist->queue, song)))
|
|
||||||
pc_song_deleted(pc, queue_get(&playlist->queue, song));
|
|
||||||
|
|
||||||
queue_delete(&playlist->queue, song);
|
queue_delete(&playlist->queue, song);
|
||||||
|
|
||||||
/* update the "current" and "queued" variables */
|
/* update the "current" and "queued" variables */
|
||||||
|
@ -363,8 +352,6 @@ playlist_delete_song(struct playlist *playlist, struct player_control *pc,
|
||||||
for (int i = queue_length(&playlist->queue) - 1; i >= 0; --i)
|
for (int i = queue_length(&playlist->queue) - 1; i >= 0; --i)
|
||||||
if (song == queue_get(&playlist->queue, i))
|
if (song == queue_get(&playlist->queue, i))
|
||||||
playlist_delete(playlist, pc, i);
|
playlist_delete(playlist, pc, i);
|
||||||
|
|
||||||
pc_song_deleted(pc, song);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum playlist_result
|
enum playlist_result
|
||||||
|
|
Loading…
Reference in New Issue