diff options
Diffstat (limited to 'src/decoder_control.h')
-rw-r--r-- | src/decoder_control.h | 184 |
1 files changed, 151 insertions, 33 deletions
diff --git a/src/decoder_control.h b/src/decoder_control.h index febf53335..449e974b7 100644 --- a/src/decoder_control.h +++ b/src/decoder_control.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2009 The Music Player Daemon Project + * Copyright (C) 2003-2010 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,8 @@ #include "decoder_command.h" #include "audio_format.h" -#include "notify.h" + +#include <glib.h> #include <assert.h> @@ -45,14 +46,25 @@ struct decoder_control { thread isn't running */ GThread *thread; - struct notify notify; + /** + * This lock protects #state and #command. + */ + GMutex *mutex; + + /** + * Trigger this object after you have modified #command. This + * is also used by the decoder thread to notify the caller + * when it has finished a command. + */ + GCond *cond; + + enum decoder_state state; + enum decoder_command command; - volatile enum decoder_state state; - volatile enum decoder_command command; bool quit; bool seek_error; bool seekable; - volatile double seek_where; + double seek_where; /** the format of the song file */ struct audio_format in_audio_format; @@ -60,54 +72,145 @@ struct decoder_control { /** the format being sent to the music pipe */ struct audio_format out_audio_format; - struct song *current_song; - struct song *next_song; + /** + * The song currently being decoded. This attribute is set by + * the player thread, when it sends the #DECODE_COMMAND_START + * command. + */ + const struct song *song; + float total_time; /** the #music_chunk allocator */ struct music_buffer *buffer; - /** the destination pipe for decoded chunks */ + /** + * The destination pipe for decoded chunks. The caller thread + * owns this object, and is responsible for freeing it. + */ struct music_pipe *pipe; + + float replay_gain_db; + float replay_gain_prev_db; + char *mixramp_start; + char *mixramp_end; + char *mixramp_prev_end; }; -extern struct decoder_control dc; +void +dc_init(struct decoder_control *dc); -void dc_init(void); +void +dc_deinit(struct decoder_control *dc); -void dc_deinit(void); +/** + * Locks the #decoder_control object. + */ +static inline void +decoder_lock(struct decoder_control *dc) +{ + g_mutex_lock(dc->mutex); +} -static inline bool decoder_is_idle(void) +/** + * Unlocks the #decoder_control object. + */ +static inline void +decoder_unlock(struct decoder_control *dc) { - return (dc.state == DECODE_STATE_STOP || - dc.state == DECODE_STATE_ERROR) && - dc.command != DECODE_COMMAND_START; + g_mutex_unlock(dc->mutex); } -static inline bool decoder_is_starting(void) +/** + * Waits for a signal on the #decoder_control object. This function + * is only valid in the decoder thread. The object must be locked + * prior to calling this function. + */ +static inline void +decoder_wait(struct decoder_control *dc) { - return dc.command == DECODE_COMMAND_START || - dc.state == DECODE_STATE_START; + g_cond_wait(dc->cond, dc->mutex); } -static inline bool decoder_has_failed(void) +/** + * Signals the #decoder_control object. This function is only valid + * in the player thread. The object should be locked prior to calling + * this function. + */ +static inline void +decoder_signal(struct decoder_control *dc) { - assert(dc.command == DECODE_COMMAND_NONE); + g_cond_signal(dc->cond); +} + +static inline bool +decoder_is_idle(const struct decoder_control *dc) +{ + return dc->state == DECODE_STATE_STOP || + dc->state == DECODE_STATE_ERROR; +} - return dc.state == DECODE_STATE_ERROR; +static inline bool +decoder_is_starting(const struct decoder_control *dc) +{ + return dc->state == DECODE_STATE_START; } -static inline struct song * -decoder_current_song(void) +static inline bool +decoder_has_failed(const struct decoder_control *dc) { - switch (dc.state) { + assert(dc->command == DECODE_COMMAND_NONE); + + return dc->state == DECODE_STATE_ERROR; +} + +static inline bool +decoder_lock_is_idle(struct decoder_control *dc) +{ + bool ret; + + decoder_lock(dc); + ret = decoder_is_idle(dc); + decoder_unlock(dc); + + return ret; +} + +static inline bool +decoder_lock_is_starting(struct decoder_control *dc) +{ + bool ret; + + decoder_lock(dc); + ret = decoder_is_starting(dc); + decoder_unlock(dc); + + return ret; +} + +static inline bool +decoder_lock_has_failed(struct decoder_control *dc) +{ + bool ret; + + decoder_lock(dc); + ret = decoder_has_failed(dc); + decoder_unlock(dc); + + return ret; +} + +static inline const struct song * +decoder_current_song(const struct decoder_control *dc) +{ + switch (dc->state) { case DECODE_STATE_STOP: case DECODE_STATE_ERROR: return NULL; case DECODE_STATE_START: case DECODE_STATE_DECODE: - return dc.current_song; + return dc->song; } assert(false); @@ -115,21 +218,36 @@ decoder_current_song(void) } void -dc_command_wait(struct notify *notify); +dc_command_wait(struct decoder_control *dc); +/** + * Start the decoder. + * + * @param the decoder + * @param song the song to be decoded + * @param pipe the pipe which receives the decoded chunks (owned by + * the caller) + */ void -dc_start(struct notify *notify, struct song *song, struct music_pipe *pipe); +dc_start(struct decoder_control *dc, struct song *song, + struct music_buffer *buffer, struct music_pipe *pipe); void -dc_start_async(struct song *song, struct music_pipe *pipe); +dc_stop(struct decoder_control *dc); + +bool +dc_seek(struct decoder_control *dc, double where); void -dc_stop(struct notify *notify); +dc_quit(struct decoder_control *dc); -bool -dc_seek(struct notify *notify, double where); +void +dc_mixramp_start(struct decoder_control *dc, char *mixramp_start); + +void +dc_mixramp_end(struct decoder_control *dc, char *mixramp_end); void -dc_quit(void); +dc_mixramp_prev_end(struct decoder_control *dc, char *mixramp_prev_end); #endif |