diff options
Diffstat (limited to '')
-rw-r--r-- | src/PlayerThread.cxx (renamed from src/player_thread.c) | 150 |
1 files changed, 92 insertions, 58 deletions
diff --git a/src/player_thread.c b/src/PlayerThread.cxx index 707fb27ae..fb7432368 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,23 @@ */ #include "config.h" -#include "player_thread.h" -#include "player_control.h" -#include "decoder_control.h" -#include "decoder_thread.h" -#include "output_all.h" -#include "pcm_volume.h" -#include "path.h" -#include "event_pipe.h" -#include "crossfade.h" +#include "PlayerThread.hxx" +#include "DecoderThread.hxx" +#include "DecoderControl.hxx" +#include "MusicPipe.hxx" +#include "MusicBuffer.hxx" +#include "MusicChunk.hxx" #include "song.h" -#include "tag.h" -#include "pipe.h" -#include "chunk.h" -#include "idle.h" -#include "main.h" -#include "buffer.h" +#include "Main.hxx" #include "mpd_error.h" +#include "CrossFade.hxx" +#include "PlayerControl.hxx" +#include "OutputAll.hxx" +#include "tag.h" +#include "Idle.hxx" +#include "GlobalEvents.hxx" + +#include <cmath> #include <glib.h> @@ -123,6 +123,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; @@ -133,7 +147,7 @@ player_command_finished_locked(struct player_control *pc) assert(pc->command != PLAYER_COMMAND_NONE); pc->command = PLAYER_COMMAND_NONE; - g_cond_signal(main_cond); + pc->cond.signal(); } static void @@ -162,7 +176,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 +249,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; @@ -265,7 +285,7 @@ player_wait_for_decoder(struct player *player) player_unlock(pc); /* call syncPlaylistWithQueue() in the main thread */ - event_pipe_emit(PIPE_EVENT_PLAYLIST); + GlobalEvents::Emit(GlobalEvents::PLAYLIST); return true; } @@ -305,7 +325,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 +337,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 +346,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 +371,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 +453,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 +480,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 +506,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 +627,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); @@ -635,7 +665,7 @@ update_song_tag(struct song *song, const struct tag *new_tag) /* the main thread will update the playlist version when he receives this event */ - event_pipe_emit(PIPE_EVENT_TAG); + GlobalEvents::Emit(GlobalEvents::TAG); /* notify all clients that the tag of the current song has changed */ @@ -652,9 +682,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 +701,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 / @@ -727,14 +758,14 @@ play_next_chunk(struct player *player) other_chunk->tag); other_chunk->tag = NULL; - if (isnan(pc->mixramp_delay_seconds)) { + if (std::isnan(pc->mixramp_delay_seconds)) { chunk->mix_ratio = ((float)cross_fade_position) / player->cross_fade_chunks; } else { 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 +816,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 +896,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,10 +904,12 @@ 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); - event_pipe_emit(PIPE_EVENT_PLAYLIST); + GlobalEvents::Emit(GlobalEvents::PLAYLIST); player_lock(pc); return; } @@ -1049,10 +1071,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; } @@ -1060,7 +1086,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc) player_unlock(pc); - event_pipe_emit(PIPE_EVENT_PLAYLIST); + GlobalEvents::Emit(GlobalEvents::PLAYLIST); player_lock(pc); } @@ -1068,9 +1094,9 @@ 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); + struct decoder_control *dc = dc_new(); decoder_thread_start(dc); player_buffer = music_buffer_new(pc->buffer_chunks); @@ -1094,7 +1120,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 +1165,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; |