diff options
Diffstat (limited to 'src/decoder_control.h')
-rw-r--r-- | src/decoder_control.h | 169 |
1 files changed, 136 insertions, 33 deletions
diff --git a/src/decoder_control.h b/src/decoder_control.h index 6a04a1617..38c4f0d83 100644 --- a/src/decoder_control.h +++ b/src/decoder_control.h @@ -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,139 @@ 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; }; -extern struct decoder_control dc; +void +dc_init(struct decoder_control *dc); + +void +dc_deinit(struct decoder_control *dc); + +/** + * Locks the #decoder_control object. + */ +static inline void +decoder_lock(struct decoder_control *dc) +{ + g_mutex_lock(dc->mutex); +} + +/** + * Unlocks the #decoder_control object. + */ +static inline void +decoder_unlock(struct decoder_control *dc) +{ + g_mutex_unlock(dc->mutex); +} + +/** + * 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) +{ + g_cond_wait(dc->cond, dc->mutex); +} + +/** + * 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) +{ + 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; +} + +static inline bool +decoder_is_starting(const struct decoder_control *dc) +{ + return dc->state == DECODE_STATE_START; +} -void dc_init(void); +static inline bool +decoder_has_failed(const struct decoder_control *dc) +{ + assert(dc->command == DECODE_COMMAND_NONE); -void dc_deinit(void); + return dc->state == DECODE_STATE_ERROR; +} -static inline bool decoder_is_idle(void) +static inline bool +decoder_lock_is_idle(struct decoder_control *dc) { - return (dc.state == DECODE_STATE_STOP || - dc.state == DECODE_STATE_ERROR) && - dc.command != DECODE_COMMAND_START; + bool ret; + + decoder_lock(dc); + ret = decoder_is_idle(dc); + decoder_unlock(dc); + + return ret; } -static inline bool decoder_is_starting(void) +static inline bool +decoder_lock_is_starting(struct decoder_control *dc) { - return dc.command == DECODE_COMMAND_START || - dc.state == DECODE_STATE_START; + bool ret; + + decoder_lock(dc); + ret = decoder_is_starting(dc); + decoder_unlock(dc); + + return ret; } -static inline bool decoder_has_failed(void) +static inline bool +decoder_lock_has_failed(struct decoder_control *dc) { - assert(dc.command == DECODE_COMMAND_NONE); + bool ret; + + decoder_lock(dc); + ret = decoder_has_failed(dc); + decoder_unlock(dc); - return dc.state == DECODE_STATE_ERROR; + return ret; } -static inline struct song * -decoder_current_song(void) +static inline const struct song * +decoder_current_song(const struct decoder_control *dc) { - switch (dc.state) { + 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 +212,27 @@ decoder_current_song(void) } void -dc_command_wait(struct notify *notify); - -void -dc_start(struct notify *notify, struct song *song); +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_async(struct song *song); +dc_start(struct decoder_control *dc, struct song *song, + struct music_buffer *buffer, struct music_pipe *pipe); void -dc_stop(struct notify *notify); +dc_stop(struct decoder_control *dc); bool -dc_seek(struct notify *notify, double where); +dc_seek(struct decoder_control *dc, double where); void -dc_quit(void); +dc_quit(struct decoder_control *dc); #endif |