From 7f803494945895da596cffa23970d84cb9bc5e9f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 19 Jun 2010 13:17:53 +0200 Subject: player_control: hold mutex in pc_play(), pc_pause() Race condition fix. --- src/player_control.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/src/player_control.c b/src/player_control.c index 30a530a6a..a190bbd8b 100644 --- a/src/player_control.c +++ b/src/player_control.c @@ -34,6 +34,9 @@ struct player_control pc; +static void +pc_enqueue_song_locked(struct song *song); + void pc_init(unsigned buffer_chunks, unsigned int buffered_before_play) { pc.buffer_chunks = buffer_chunks; @@ -103,15 +106,19 @@ pc_play(struct song *song) { assert(song != NULL); + player_lock(); + if (pc.state != PLAYER_STATE_STOP) - player_command(PLAYER_COMMAND_STOP); + player_command_locked(PLAYER_COMMAND_STOP); assert(pc.next_song == NULL); - pc_enqueue_song(song); + pc_enqueue_song_locked(song); assert(pc.next_song == NULL); + player_unlock(); + idle_add(IDLE_PLAYER); } @@ -150,9 +157,22 @@ pc_kill(void) void pc_pause(void) +{ + player_lock(); + + if (pc.state != PLAYER_STATE_STOP) { + player_command_locked(PLAYER_COMMAND_PAUSE); + idle_add(IDLE_PLAYER); + } + + player_unlock(); +} + +static void +pc_pause_locked(void) { if (pc.state != PLAYER_STATE_STOP) { - player_command(PLAYER_COMMAND_PAUSE); + player_command_locked(PLAYER_COMMAND_PAUSE); idle_add(IDLE_PLAYER); } } @@ -160,20 +180,24 @@ pc_pause(void) void pc_set_pause(bool pause_flag) { + player_lock(); + switch (pc.state) { case PLAYER_STATE_STOP: break; case PLAYER_STATE_PLAY: if (pause_flag) - pc_pause(); + pc_pause_locked(); break; case PLAYER_STATE_PAUSE: if (!pause_flag) - pc_pause(); + pc_pause_locked(); break; } + + player_unlock(); } void @@ -203,8 +227,10 @@ pc_get_state(void) void pc_clear_error(void) { + player_lock(); pc.error = PLAYER_ERROR_NOERROR; pc.errored_song = NULL; + player_unlock(); } enum player_error @@ -258,16 +284,23 @@ pc_get_error_message(void) return NULL; } -void -pc_enqueue_song(struct song *song) +static void +pc_enqueue_song_locked(struct song *song) { assert(song != NULL); - - player_lock(); assert(pc.next_song == NULL); pc.next_song = song; player_command_locked(PLAYER_COMMAND_QUEUE); +} + +void +pc_enqueue_song(struct song *song) +{ + assert(song != NULL); + + player_lock(); + pc_enqueue_song_locked(song); player_unlock(); } -- cgit v1.2.3