diff options
Diffstat (limited to '')
-rw-r--r-- | src/PlayerThread.cxx (renamed from src/player_thread.c) | 133 |
1 files changed, 84 insertions, 49 deletions
diff --git a/src/player_thread.c b/src/PlayerThread.cxx index 707fb27ae..0343b9fcd 100644 --- a/src/player_thread.c +++ b/src/PlayerThread.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,23 +18,24 @@ */ #include "config.h" -#include "player_thread.h" -#include "player_control.h" -#include "decoder_control.h" -#include "decoder_thread.h" +#include "PlayerThread.hxx" +#include "DecoderThread.hxx" +#include "DecoderControl.hxx" +#include "MusicPipe.hxx" +#include "MusicBuffer.hxx" +#include "MusicChunk.hxx" +#include "song.h" +#include "Main.hxx" +#include "mpd_error.h" +#include "CrossFade.hxx" +#include "PlayerControl.hxx" + +extern "C" { #include "output_all.h" -#include "pcm_volume.h" -#include "path.h" #include "event_pipe.h" -#include "crossfade.h" -#include "song.h" #include "tag.h" -#include "pipe.h" -#include "chunk.h" #include "idle.h" -#include "main.h" -#include "buffer.h" -#include "mpd_error.h" +} #include <glib.h> @@ -123,6 +124,20 @@ struct player { * precisely. */ float elapsed_time; + + player(player_control *_pc, decoder_control *_dc) + :pc(_pc), dc(_dc), + buffering(false), + decoder_starting(false), + paused(false), + queued(true), + output_open(false), + song(NULL), + xfade(XFADE_UNKNOWN), + cross_fading(false), + cross_fade_chunks(0), + cross_fade_tag(NULL), + elapsed_time(0.0) {} }; static struct music_buffer *player_buffer; @@ -162,7 +177,7 @@ player_dc_start(struct player *player, struct music_pipe *pipe) if (pc->command == PLAYER_COMMAND_SEEK) start_ms += (unsigned)(pc->seek_where * 1000); - dc_start(dc, pc->next_song, + dc_start(dc, song_dup_detached(pc->next_song), start_ms, pc->next_song->end_ms, player_buffer, pipe); } @@ -235,16 +250,22 @@ player_wait_for_decoder(struct player *player) player->queued = false; - if (decoder_lock_has_failed(dc)) { + GError *error = dc_lock_get_error(dc); + if (error != NULL) { player_lock(pc); - pc->errored_song = dc->song; - pc->error = PLAYER_ERROR_FILE; + pc_set_error(pc, PLAYER_ERROR_DECODER, error); + + song_free(pc->next_song); pc->next_song = NULL; + player_unlock(pc); return false; } + if (player->song != NULL) + song_free(player->song); + player->song = pc->next_song; player->elapsed_time = 0.0; @@ -305,7 +326,9 @@ player_open_output(struct player *player) assert(pc->state == PLAYER_STATE_PLAY || pc->state == PLAYER_STATE_PAUSE); - if (audio_output_all_open(&player->play_audio_format, player_buffer)) { + GError *error = NULL; + if (audio_output_all_open(&player->play_audio_format, player_buffer, + &error)) { player->output_open = true; player->paused = false; @@ -315,6 +338,8 @@ player_open_output(struct player *player) return true; } else { + g_warning("%s", error->message); + player->output_open = false; /* pause: the user may resume playback as soon as an @@ -322,7 +347,7 @@ player_open_output(struct player *player) player->paused = true; player_lock(pc); - pc->error = PLAYER_ERROR_AUDIO; + pc_set_error(pc, PLAYER_ERROR_OUTPUT, error); pc->state = PLAYER_STATE_PAUSE; player_unlock(pc); @@ -347,13 +372,13 @@ player_check_decoder_startup(struct player *player) decoder_lock(dc); - if (decoder_has_failed(dc)) { + GError *error = dc_get_error(dc); + if (error != NULL) { /* the decoder failed */ decoder_unlock(dc); player_lock(pc); - pc->errored_song = dc->song; - pc->error = PLAYER_ERROR_FILE; + pc_set_error(pc, PLAYER_ERROR_DECODER, error); player_unlock(pc); return false; @@ -429,7 +454,11 @@ player_send_silence(struct player *player) chunk->length = num_frames * frame_size; memset(chunk->data, 0, chunk->length); - if (!audio_output_all_play(chunk)) { + GError *error = NULL; + if (!audio_output_all_play(chunk, &error)) { + g_warning("%s", error->message); + g_error_free(error); + music_buffer_return(player_buffer, chunk); return false; } @@ -452,7 +481,7 @@ static bool player_seek_decoder(struct player *player) const unsigned start_ms = song->start_ms; - if (decoder_current_song(dc) != song) { + if (!decoder_lock_is_current_song(dc, song)) { /* the decoder is already decoding the "next" song - stop it and start the previous song again */ @@ -478,6 +507,7 @@ static bool player_seek_decoder(struct player *player) player->pipe = dc->pipe; } + song_free(pc->next_song); pc->next_song = NULL; player->queued = false; } @@ -598,6 +628,7 @@ static void player_process_command(struct player *player) player_lock(pc); } + song_free(pc->next_song); pc->next_song = NULL; player->queued = false; player_command_finished_locked(pc); @@ -652,9 +683,10 @@ update_song_tag(struct song *song, const struct tag *new_tag) static bool play_chunk(struct player_control *pc, struct song *song, struct music_chunk *chunk, - const struct audio_format *format) + const struct audio_format *format, + GError **error_r) { - assert(music_chunk_check_format(chunk, format)); + assert(chunk->CheckFormat(*format)); if (chunk->tag != NULL) update_song_tag(song, chunk->tag); @@ -670,7 +702,7 @@ play_chunk(struct player_control *pc, /* send the chunk to the audio outputs */ - if (!audio_output_all_play(chunk)) + if (!audio_output_all_play(chunk, error_r)) return false; pc->total_play_time += (double)chunk->length / @@ -734,7 +766,7 @@ play_next_chunk(struct player *player) chunk->mix_ratio = nan(""); } - if (music_chunk_is_empty(other_chunk)) { + if (other_chunk->IsEmpty()) { /* the "other" chunk was a music_chunk which had only a tag, but no music data - we cannot cross-fade that; @@ -785,13 +817,16 @@ play_next_chunk(struct player *player) /* play the current chunk */ + GError *error = NULL; if (!play_chunk(player->pc, player->song, chunk, - &player->play_audio_format)) { + &player->play_audio_format, &error)) { + g_warning("%s", error->message); + music_buffer_return(player_buffer, chunk); player_lock(pc); - pc->error = PLAYER_ERROR_AUDIO; + pc_set_error(pc, PLAYER_ERROR_OUTPUT, error); /* pause: the user may resume playback as soon as an audio output becomes available */ @@ -862,21 +897,7 @@ player_song_border(struct player *player) */ static void do_play(struct player_control *pc, struct decoder_control *dc) { - struct player player = { - .pc = pc, - .dc = dc, - .buffering = true, - .decoder_starting = false, - .paused = false, - .queued = true, - .output_open = false, - .song = NULL, - .xfade = XFADE_UNKNOWN, - .cross_fading = false, - .cross_fade_chunks = 0, - .cross_fade_tag = NULL, - .elapsed_time = 0.0, - }; + player player(pc, dc); player_unlock(pc); @@ -884,6 +905,8 @@ static void do_play(struct player_control *pc, struct decoder_control *dc) player_dc_start(&player, player.pipe); if (!player_wait_for_decoder(&player)) { + assert(player.song == NULL); + player_dc_stop(&player); player_command_finished(pc); music_pipe_free(player.pipe); @@ -1049,10 +1072,14 @@ static void do_play(struct player_control *pc, struct decoder_control *dc) if (player.cross_fade_tag != NULL) tag_free(player.cross_fade_tag); + if (player.song != NULL) + song_free(player.song); + player_lock(pc); if (player.queued) { assert(pc->next_song != NULL); + song_free(pc->next_song); pc->next_song = NULL; } @@ -1068,7 +1095,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc) static gpointer player_task(gpointer arg) { - struct player_control *pc = arg; + struct player_control *pc = (struct player_control *)arg; struct decoder_control *dc = dc_new(pc->cond); decoder_thread_start(dc); @@ -1094,7 +1121,11 @@ player_task(gpointer arg) /* fall through */ case PLAYER_COMMAND_PAUSE: - pc->next_song = NULL; + if (pc->next_song != NULL) { + song_free(pc->next_song); + pc->next_song = NULL; + } + player_command_finished_locked(pc); break; @@ -1135,7 +1166,11 @@ player_task(gpointer arg) return NULL; case PLAYER_COMMAND_CANCEL: - pc->next_song = NULL; + if (pc->next_song != NULL) { + song_free(pc->next_song); + pc->next_song = NULL; + } + player_command_finished_locked(pc); break; |