player_control: hold mutex in pc_play(), pc_pause()

Race condition fix.
This commit is contained in:
Max Kellermann 2010-06-19 13:17:53 +02:00
parent a6ef696132
commit 7f80349494

View File

@ -34,6 +34,9 @@
struct player_control pc; struct player_control pc;
static void
pc_enqueue_song_locked(struct song *song);
void pc_init(unsigned buffer_chunks, unsigned int buffered_before_play) void pc_init(unsigned buffer_chunks, unsigned int buffered_before_play)
{ {
pc.buffer_chunks = buffer_chunks; pc.buffer_chunks = buffer_chunks;
@ -103,15 +106,19 @@ pc_play(struct song *song)
{ {
assert(song != NULL); assert(song != NULL);
player_lock();
if (pc.state != PLAYER_STATE_STOP) if (pc.state != PLAYER_STATE_STOP)
player_command(PLAYER_COMMAND_STOP); player_command_locked(PLAYER_COMMAND_STOP);
assert(pc.next_song == NULL); assert(pc.next_song == NULL);
pc_enqueue_song(song); pc_enqueue_song_locked(song);
assert(pc.next_song == NULL); assert(pc.next_song == NULL);
player_unlock();
idle_add(IDLE_PLAYER); idle_add(IDLE_PLAYER);
} }
@ -151,8 +158,21 @@ pc_kill(void)
void void
pc_pause(void) pc_pause(void)
{ {
player_lock();
if (pc.state != PLAYER_STATE_STOP) { if (pc.state != PLAYER_STATE_STOP) {
player_command(PLAYER_COMMAND_PAUSE); 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_locked(PLAYER_COMMAND_PAUSE);
idle_add(IDLE_PLAYER); idle_add(IDLE_PLAYER);
} }
} }
@ -160,20 +180,24 @@ pc_pause(void)
void void
pc_set_pause(bool pause_flag) pc_set_pause(bool pause_flag)
{ {
player_lock();
switch (pc.state) { switch (pc.state) {
case PLAYER_STATE_STOP: case PLAYER_STATE_STOP:
break; break;
case PLAYER_STATE_PLAY: case PLAYER_STATE_PLAY:
if (pause_flag) if (pause_flag)
pc_pause(); pc_pause_locked();
break; break;
case PLAYER_STATE_PAUSE: case PLAYER_STATE_PAUSE:
if (!pause_flag) if (!pause_flag)
pc_pause(); pc_pause_locked();
break; break;
} }
player_unlock();
} }
void void
@ -203,8 +227,10 @@ pc_get_state(void)
void void
pc_clear_error(void) pc_clear_error(void)
{ {
player_lock();
pc.error = PLAYER_ERROR_NOERROR; pc.error = PLAYER_ERROR_NOERROR;
pc.errored_song = NULL; pc.errored_song = NULL;
player_unlock();
} }
enum player_error enum player_error
@ -258,16 +284,23 @@ pc_get_error_message(void)
return NULL; return NULL;
} }
static void
pc_enqueue_song_locked(struct song *song)
{
assert(song != NULL);
assert(pc.next_song == NULL);
pc.next_song = song;
player_command_locked(PLAYER_COMMAND_QUEUE);
}
void void
pc_enqueue_song(struct song *song) pc_enqueue_song(struct song *song)
{ {
assert(song != NULL); assert(song != NULL);
player_lock(); player_lock();
assert(pc.next_song == NULL); pc_enqueue_song_locked(song);
pc.next_song = song;
player_command_locked(PLAYER_COMMAND_QUEUE);
player_unlock(); player_unlock();
} }