diff options
author | Max Kellermann <max@duempel.org> | 2010-06-19 13:17:53 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2010-06-19 13:19:30 +0200 |
commit | 7f803494945895da596cffa23970d84cb9bc5e9f (patch) | |
tree | 0be17af99e2ecfa62778d64af121f0b57b7146df | |
parent | a6ef696132b686153f2119ae84e310c8bd935bde (diff) | |
download | mpd-7f803494945895da596cffa23970d84cb9bc5e9f.tar.gz mpd-7f803494945895da596cffa23970d84cb9bc5e9f.tar.xz mpd-7f803494945895da596cffa23970d84cb9bc5e9f.zip |
player_control: hold mutex in pc_play(), pc_pause()
Race condition fix.
-rw-r--r-- | src/player_control.c | 51 |
1 files 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); } @@ -151,8 +158,21 @@ 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(); } |