aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-10-12 00:07:54 +0200
committerMax Kellermann <max@duempel.org>2008-10-12 00:07:54 +0200
commit35a939e3e766975776ecaf99e0e46f8a3a68faf2 (patch)
treebde09a92e04ff41ac4502d86b2d2eaa504258d44
parent35a16b99238a7daea97bedd244861f5b82e0b0cf (diff)
downloadmpd-35a939e3e766975776ecaf99e0e46f8a3a68faf2.tar.gz
mpd-35a939e3e766975776ecaf99e0e46f8a3a68faf2.tar.xz
mpd-35a939e3e766975776ecaf99e0e46f8a3a68faf2.zip
player: added commands QUEUE and CANCEL
QUEUE adds a new song to the player's queue. CANCEL clears the queue. These two commands replace the old and complex queueState and queueLockState code.
-rw-r--r--src/player_control.c46
-rw-r--r--src/player_control.h57
-rw-r--r--src/player_thread.c77
-rw-r--r--src/playlist.c49
4 files changed, 74 insertions, 155 deletions
diff --git a/src/player_control.c b/src/player_control.c
index 8ba215ae1..e7935f80f 100644
--- a/src/player_control.c
+++ b/src/player_control.c
@@ -33,8 +33,6 @@ void pc_init(unsigned int buffered_before_play)
pc.command = PLAYER_COMMAND_NONE;
pc.error = PLAYER_ERROR_NOERROR;
pc.state = PLAYER_STATE_STOP;
- pc.queueState = PLAYER_QUEUE_BLANK;
- pc.queueLockState = PLAYER_QUEUE_UNLOCKED;
pc.crossFade = 0;
pc.softwareVolume = 1000;
}
@@ -57,26 +55,22 @@ void
playerPlay(struct song *song)
{
assert(song != NULL);
- assert(pc.queueLockState == PLAYER_QUEUE_UNLOCKED);
if (pc.state != PLAYER_STATE_STOP)
player_command(PLAYER_COMMAND_STOP);
- pc.queueState = PLAYER_QUEUE_BLANK;
-
pc.next_song = song;
player_command(PLAYER_COMMAND_PLAY);
}
-void playerWait(void)
+void pc_cancel(void)
{
- player_command(PLAYER_COMMAND_CLOSE_AUDIO);
-
- assert(pc.queueLockState == PLAYER_QUEUE_UNLOCKED);
+ player_command(PLAYER_COMMAND_CANCEL);
+}
+void playerWait(void)
+{
player_command(PLAYER_COMMAND_CLOSE_AUDIO);
-
- pc.queueState = PLAYER_QUEUE_BLANK;
}
void playerKill(void)
@@ -172,36 +166,10 @@ void
queueSong(struct song *song)
{
assert(song != NULL);
- assert(pc.queueState == PLAYER_QUEUE_BLANK);
+ assert(pc.next_song == NULL);
pc.next_song = song;
- pc.queueState = PLAYER_QUEUE_FULL;
-}
-
-enum player_queue_state getPlayerQueueState(void)
-{
- return pc.queueState;
-}
-
-void setQueueState(enum player_queue_state queueState)
-{
- pc.queueState = queueState;
- notify_signal(&pc.notify);
-}
-
-void playerQueueLock(void)
-{
- assert(pc.queueLockState == PLAYER_QUEUE_UNLOCKED);
- player_command(PLAYER_COMMAND_LOCK_QUEUE);
- assert(pc.queueLockState == PLAYER_QUEUE_LOCKED);
-}
-
-void playerQueueUnlock(void)
-{
- if (pc.queueLockState == PLAYER_QUEUE_LOCKED)
- player_command(PLAYER_COMMAND_UNLOCK_QUEUE);
-
- assert(pc.queueLockState == PLAYER_QUEUE_UNLOCKED);
+ player_command(PLAYER_COMMAND_QUEUE);
}
int
diff --git a/src/player_control.h b/src/player_control.h
index 179a9c2ab..bd557ce57 100644
--- a/src/player_control.h
+++ b/src/player_control.h
@@ -38,8 +38,16 @@ enum player_command {
PLAYER_COMMAND_PAUSE,
PLAYER_COMMAND_SEEK,
PLAYER_COMMAND_CLOSE_AUDIO,
- PLAYER_COMMAND_LOCK_QUEUE,
- PLAYER_COMMAND_UNLOCK_QUEUE
+
+ /** player_control.next_song has been updated */
+ PLAYER_COMMAND_QUEUE,
+
+ /**
+ * cancel pre-decoding player_control.next_song; if the player
+ * has already started playing this song, it will completely
+ * stop
+ */
+ PLAYER_COMMAND_CANCEL,
};
#define PLAYER_ERROR_NOERROR 0
@@ -49,36 +57,6 @@ enum player_command {
#define PLAYER_ERROR_UNKTYPE 4
#define PLAYER_ERROR_FILENOTFOUND 5
-/* 0->1->2->3->5 regular playback
- * ->4->0 don't play queued song
- */
-enum player_queue_state {
- /** there is no queued song */
- PLAYER_QUEUE_BLANK = 0,
-
- /** there is a queued song */
- PLAYER_QUEUE_FULL = 1,
-
- /** the player thread has forwarded the queued song to the
- decoder; it waits for PLAY or STOP */
- PLAYER_QUEUE_DECODE = 2,
-
- /** tells the player thread to start playing the queued song;
- this is a response to DECODE */
- PLAYER_QUEUE_PLAY = 3,
-
- /** tells the player thread to stop before playing the queued
- song; this is a response to DECODE */
- PLAYER_QUEUE_STOP = 4,
-
- /** the player thread has begun playing the queued song, and
- thus its queue is empty */
- PLAYER_QUEUE_EMPTY = 5
-};
-
-#define PLAYER_QUEUE_UNLOCKED 0
-#define PLAYER_QUEUE_LOCKED 1
-
struct player_control {
unsigned int buffered_before_play;
@@ -92,8 +70,6 @@ struct player_control {
volatile float elapsedTime;
struct song *volatile next_song;
struct song *errored_song;
- volatile enum player_queue_state queueState;
- volatile int8_t queueLockState;
volatile double seekWhere;
volatile float crossFade;
volatile uint16_t softwareVolume;
@@ -109,6 +85,11 @@ void pc_deinit(void);
void
playerPlay(struct song *song);
+/**
+ * see PLAYER_COMMAND_CANCEL
+ */
+void pc_cancel(void);
+
void playerSetPause(int pause_flag);
void playerPause(void);
@@ -134,14 +115,6 @@ void playerWait(void);
void
queueSong(struct song *song);
-enum player_queue_state getPlayerQueueState(void);
-
-void setQueueState(enum player_queue_state queueState);
-
-void playerQueueLock(void);
-
-void playerQueueUnlock(void);
-
int
playerSeek(struct song *song, float seek_time);
diff --git a/src/player_thread.c b/src/player_thread.c
index f6cecb5a2..10b9a8769 100644
--- a/src/player_thread.c
+++ b/src/player_thread.c
@@ -52,6 +52,11 @@ struct player {
bool paused;
/**
+ * is there a new song in pc.next_song?
+ */
+ bool queued;
+
+ /**
* is cross fading enabled?
*/
enum xfade_state xfade;
@@ -94,6 +99,9 @@ static int waitOnDecode(struct player *player)
? pc.next_song->tag->time : 0;
pc.bitRate = 0;
audio_format_clear(&pc.audio_format);
+
+ pc.next_song = NULL;
+ player->queued = false;
player->decoder_starting = true;
return 0;
@@ -137,13 +145,9 @@ static void processDecodeInput(struct player *player)
case PLAYER_COMMAND_CLOSE_AUDIO:
break;
- case PLAYER_COMMAND_LOCK_QUEUE:
- pc.queueLockState = PLAYER_QUEUE_LOCKED;
- player_command_finished();
- break;
-
- case PLAYER_COMMAND_UNLOCK_QUEUE:
- pc.queueLockState = PLAYER_QUEUE_UNLOCKED;
+ case PLAYER_COMMAND_QUEUE:
+ assert(pc.next_song != NULL);
+ player->queued = true;
player_command_finished();
break;
@@ -177,6 +181,27 @@ static void processDecodeInput(struct player *player)
player->buffered_before_play = 0;
}
break;
+
+ case PLAYER_COMMAND_CANCEL:
+ if (pc.next_song == NULL) {
+ /* the cancel request arrived too later, we're
+ already playing the queued song... stop
+ everything now */
+ pc.command = PLAYER_COMMAND_STOP;
+ return;
+ }
+
+ if (player->next_song_chunk != -1) {
+ /* the decoder is already decoding the song -
+ stop it and reset the position */
+ dc_stop(&pc.notify);
+ player->next_song_chunk = -1;
+ }
+
+ pc.next_song = NULL;
+ player->queued = false;
+ player_command_finished();
+ break;
}
}
@@ -203,6 +228,7 @@ static void do_play(void)
.buffered_before_play = pc.buffered_before_play,
.decoder_starting = false,
.paused = false,
+ .queued = false,
.xfade = XFADE_UNKNOWN,
.next_song_chunk = -1,
};
@@ -286,15 +312,22 @@ static void do_play(void)
}
}
- if (decoder_is_idle() &&
- pc.queueState == PLAYER_QUEUE_FULL &&
- pc.queueLockState == PLAYER_QUEUE_UNLOCKED) {
+ if (decoder_is_idle() && !player.queued &&
+ pc.next_song != NULL) {
+ /* the decoder has finished the current song;
+ request the next song from the playlist */
+ pc.next_song = NULL;
+ wakeup_main_task();
+ }
+
+ if (decoder_is_idle() && player.queued) {
/* the decoder has finished the current song;
make it decode the next song */
+ assert(pc.next_song != NULL);
+
+ player.queued = false;
player.next_song_chunk = ob.end;
dc_start_async(pc.next_song);
- pc.queueState = PLAYER_QUEUE_DECODE;
- wakeup_main_task();
}
if (player.next_song_chunk >= 0 &&
player.xfade == XFADE_UNKNOWN &&
@@ -386,20 +419,10 @@ static void do_play(void)
player.xfade = XFADE_UNKNOWN;
- /* wait for a signal from the playlist */
- if (pc.queueState == PLAYER_QUEUE_DECODE ||
- pc.queueLockState == PLAYER_QUEUE_LOCKED) {
- notify_wait(&pc.notify);
- continue;
- }
- if (pc.queueState != PLAYER_QUEUE_PLAY)
- break;
-
player.next_song_chunk = -1;
if (waitOnDecode(&player) < 0)
return;
- pc.queueState = PLAYER_QUEUE_EMPTY;
wakeup_main_task();
} else if (decoder_is_idle()) {
break;
@@ -418,6 +441,7 @@ static void * player_task(mpd_unused void *arg)
while (1) {
switch (pc.command) {
case PLAYER_COMMAND_PLAY:
+ case PLAYER_COMMAND_QUEUE:
do_play();
break;
@@ -438,13 +462,8 @@ static void * player_task(mpd_unused void *arg)
pthread_exit(NULL);
break;
- case PLAYER_COMMAND_LOCK_QUEUE:
- pc.queueLockState = PLAYER_QUEUE_LOCKED;
- player_command_finished();
- break;
-
- case PLAYER_COMMAND_UNLOCK_QUEUE:
- pc.queueLockState = PLAYER_QUEUE_UNLOCKED;
+ case PLAYER_COMMAND_CANCEL:
+ pc.next_song = NULL;
player_command_finished();
break;
diff --git a/src/playlist.c b/src/playlist.c
index 74b2d60d2..840c9c6b5 100644
--- a/src/playlist.c
+++ b/src/playlist.c
@@ -499,28 +499,9 @@ static void queueNextSongInPlaylist(void)
static void syncPlaylistWithQueue(void)
{
- switch (getPlayerQueueState()) {
- case PLAYER_QUEUE_EMPTY:
- setQueueState(PLAYER_QUEUE_BLANK);
- if (playlist.queued >= 0) {
- DEBUG("playlist: now playing queued song\n");
- playlist.current = playlist.queued;
- }
+ if (pc.next_song == NULL && playlist.queued != -1) {
+ playlist.current = playlist.queued;
playlist.queued = -1;
- break;
-
- case PLAYER_QUEUE_DECODE:
- if (playlist.queued != -1)
- setQueueState(PLAYER_QUEUE_PLAY);
- else
- setQueueState(PLAYER_QUEUE_STOP);
- break;
-
- case PLAYER_QUEUE_FULL:
- case PLAYER_QUEUE_PLAY:
- case PLAYER_QUEUE_STOP:
- case PLAYER_QUEUE_BLANK:
- break;
}
}
@@ -528,31 +509,9 @@ static void clearPlayerQueue(void)
{
assert(playlist.queued >= 0);
- if (getPlayerQueueState() == PLAYER_QUEUE_PLAY ||
- getPlayerQueueState() == PLAYER_QUEUE_FULL) {
- playerQueueLock();
- syncPlaylistWithQueue();
- }
-
playlist.queued = -1;
- switch (getPlayerQueueState()) {
- case PLAYER_QUEUE_BLANK:
- case PLAYER_QUEUE_DECODE:
- case PLAYER_QUEUE_STOP:
- case PLAYER_QUEUE_EMPTY:
- break;
-
- case PLAYER_QUEUE_FULL:
- DEBUG("playlist: dequeue song\n");
- setQueueState(PLAYER_QUEUE_BLANK);
- break;
- case PLAYER_QUEUE_PLAY:
- DEBUG("playlist: stop decoding queued song\n");
- setQueueState(PLAYER_QUEUE_STOP);
- break;
- }
- playerQueueUnlock();
+ pc_cancel();
}
enum playlist_result addToPlaylist(const char *url, int *added_id)
@@ -907,7 +866,7 @@ void syncPlayerAndPlaylist(void)
playPlaylistIfPlayerStopped();
else {
syncPlaylistWithQueue();
- if (getPlayerQueueState() == PLAYER_QUEUE_BLANK)
+ if (pc.next_song == NULL)
queueNextSongInPlaylist();
}