aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2010-06-19 13:17:53 +0200
committerMax Kellermann <max@duempel.org>2010-06-19 13:19:30 +0200
commit7f803494945895da596cffa23970d84cb9bc5e9f (patch)
tree0be17af99e2ecfa62778d64af121f0b57b7146df /src
parenta6ef696132b686153f2119ae84e310c8bd935bde (diff)
downloadmpd-7f803494945895da596cffa23970d84cb9bc5e9f.tar.gz
mpd-7f803494945895da596cffa23970d84cb9bc5e9f.tar.xz
mpd-7f803494945895da596cffa23970d84cb9bc5e9f.zip
player_control: hold mutex in pc_play(), pc_pause()
Race condition fix.
Diffstat (limited to 'src')
-rw-r--r--src/player_control.c51
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();
}