diff options
-rw-r--r-- | doc/protocol.xml | 21 | ||||
-rw-r--r-- | src/command.c | 24 | ||||
-rw-r--r-- | src/playlist.c | 19 | ||||
-rw-r--r-- | src/playlist.h | 5 | ||||
-rw-r--r-- | src/playlist_control.c | 35 | ||||
-rw-r--r-- | src/playlist_state.c | 10 | ||||
-rw-r--r-- | src/queue.c | 1 | ||||
-rw-r--r-- | src/queue.h | 3 |
8 files changed, 103 insertions, 15 deletions
diff --git a/doc/protocol.xml b/doc/protocol.xml index 3dcfedeb5..0096ed672 100644 --- a/doc/protocol.xml +++ b/doc/protocol.xml @@ -223,6 +223,12 @@ </para> </listitem> <listitem> + <para> + <varname>consume</varname>: + <returnvalue>0 or 1</returnvalue> + </para> + </listitem> + <listitem> <para> <varname>playlist</varname>: <returnvalue>31-bit unsigned integer, the playlist @@ -352,6 +358,21 @@ <section> <title>Playback options</title> + <varlistentry id="command_consume"> + <term> + <cmdsynopsis> + <command>consume</command> + <arg choice="req"><replaceable>STATE</replaceable></arg> + </cmdsynopsis> + </term> + <listitem> + <para> + Sets consume state to <varname>STATE</varname>, + <varname>STATE</varname> should be 0 or 1. + When consume is activated, each song played is removed from playlist. + </para> + </listitem> + </varlistentry> <variablelist> <varlistentry id="command_crossfade"> <term> diff --git a/src/command.c b/src/command.c index 69fbe514f..d4363ff65 100644 --- a/src/command.c +++ b/src/command.c @@ -59,7 +59,8 @@ #define COMMAND_STATUS_VOLUME "volume" #define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_REPEAT "repeat" -#define COMMAND_STATUS_SINGLE "single" +#define COMMAND_STATUS_SINGLE "single" +#define COMMAND_STATUS_CONSUME "consume" #define COMMAND_STATUS_RANDOM "random" #define COMMAND_STATUS_PLAYLIST "playlist" #define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength" @@ -471,6 +472,7 @@ handle_status(struct client *client, COMMAND_STATUS_REPEAT ": %i\n" COMMAND_STATUS_RANDOM ": %i\n" COMMAND_STATUS_SINGLE ": %i\n" + COMMAND_STATUS_CONSUME ": %i\n" COMMAND_STATUS_PLAYLIST ": %li\n" COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n" COMMAND_STATUS_CROSSFADE ": %i\n" @@ -479,6 +481,7 @@ handle_status(struct client *client, getPlaylistRepeatStatus(&g_playlist), getPlaylistRandomStatus(&g_playlist), getPlaylistSingleStatus(&g_playlist), + getPlaylistConsumeStatus(&g_playlist), getPlaylistVersion(&g_playlist), getPlaylistLength(&g_playlist), (int)(getPlayerCrossFade() + 0.5), @@ -1114,6 +1117,24 @@ handle_single(struct client *client, G_GNUC_UNUSED int argc, char *argv[]) } static enum command_return +handle_consume(struct client *client, G_GNUC_UNUSED int argc, char *argv[]) +{ + int status; + + if (!check_int(client, &status, argv[1], need_integer)) + return COMMAND_RETURN_ERROR; + + if (status != 0 && status != 1) { + command_error(client, ACK_ERROR_ARG, + "\"%i\" is not 0 or 1", status); + return COMMAND_RETURN_ERROR; + } + + setPlaylistConsumeStatus(&g_playlist, status); + return COMMAND_RETURN_OK; +} + +static enum command_return handle_random(struct client *client, G_GNUC_UNUSED int argc, char *argv[]) { int status; @@ -1573,6 +1594,7 @@ static const struct command commands[] = { { "clearerror", PERMISSION_CONTROL, 0, 0, handle_clearerror }, { "close", PERMISSION_NONE, -1, -1, handle_close }, { "commands", PERMISSION_NONE, 0, 0, handle_commands }, + { "consume", PERMISSION_CONTROL, 1, 1, handle_consume }, { "count", PERMISSION_READ, 2, -1, handle_count }, { "crossfade", PERMISSION_CONTROL, 1, 1, handle_crossfade }, { "currentsong", PERMISSION_READ, 0, 0, handle_currentsong }, diff --git a/src/playlist.c b/src/playlist.c index 776308db0..79f6022a5 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -100,9 +100,13 @@ static void syncPlaylistWithQueue(struct playlist *playlist) /* queued song has started: copy queued to current, and notify the clients */ + int current = playlist->current; playlist->current = playlist->queued; playlist->queued = -1; + if(playlist->queue.consume) + deleteFromPlaylist(playlist, queue_order_to_position(&playlist->queue, current)); + idle_add(IDLE_PLAYER); } } @@ -267,6 +271,12 @@ getPlaylistSingleStatus(const struct playlist *playlist) return playlist->queue.single; } +bool +getPlaylistConsumeStatus(const struct playlist *playlist) +{ + return playlist->queue.consume; +} + void setPlaylistRepeatStatus(struct playlist *playlist, bool status) { if (status == playlist->queue.repeat) @@ -307,6 +317,15 @@ void setPlaylistSingleStatus(struct playlist *playlist, bool status) idle_add(IDLE_OPTIONS); } +void setPlaylistConsumeStatus(struct playlist *playlist, bool status) +{ + if (status == playlist->queue.consume) + return; + + playlist->queue.consume = status; + idle_add(IDLE_OPTIONS); +} + void setPlaylistRandomStatus(struct playlist *playlist, bool status) { const struct song *queued; diff --git a/src/playlist.h b/src/playlist.h index 17862b335..4237cea98 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -184,6 +184,11 @@ getPlaylistSingleStatus(const struct playlist *playlist); void setPlaylistSingleStatus(struct playlist *playlist, bool status); +bool +getPlaylistConsumeStatus(const struct playlist *playlist); + +void setPlaylistConsumeStatus(struct playlist *playlist, bool status); + int getPlaylistCurrentSong(const struct playlist *playlist); int getPlaylistNextSong(const struct playlist *playlist); diff --git a/src/playlist_control.c b/src/playlist_control.c index 9e31c07ab..4f51345c3 100644 --- a/src/playlist_control.c +++ b/src/playlist_control.c @@ -139,6 +139,7 @@ void nextSongInPlaylist(struct playlist *playlist) { int next_order; + int current; if (!playlist->playing) return; @@ -146,6 +147,7 @@ nextSongInPlaylist(struct playlist *playlist) assert(!queue_is_empty(&playlist->queue)); assert(queue_valid_order(&playlist->queue, playlist->current)); + current = playlist->current; playlist->stop_on_error = false; /* determine the next song from the queue's order list */ @@ -156,24 +158,29 @@ nextSongInPlaylist(struct playlist *playlist) playlist->queue.single = false; /* no song after this one: stop playback */ stopPlaylist(playlist); - return; } + else + { + if (next_order == 0 && playlist->queue.random) { + /* The queue told us that the next song is the first + song. This means we are in repeat mode. Shuffle + the queue order, so this time, the user hears the + songs in a different than before */ + assert(playlist->queue.repeat); + + queue_shuffle_order(&playlist->queue); + + /* note that playlist->current and playlist->queued are + now invalid, but playPlaylistOrderNumber() will + discard them anyway */ + } - if (next_order == 0 && playlist->queue.random) { - /* The queue told us that the next song is the first - song. This means we are in repeat mode. Shuffle - the queue order, so this time, the user hears the - songs in a different than before */ - assert(playlist->queue.repeat); - - queue_shuffle_order(&playlist->queue); - - /* note that playlist->current and playlist->queued are - now invalid, but playPlaylistOrderNumber() will - discard them anyway */ + playPlaylistOrderNumber(playlist, next_order); } - playPlaylistOrderNumber(playlist, next_order); + /* Consume mode removes each played songs. */ + if(playlist->queue.consume) + deleteFromPlaylist(playlist, queue_order_to_position(&playlist->queue, current)); } void previousSongInPlaylist(struct playlist *playlist) diff --git a/src/playlist_state.c b/src/playlist_state.c index f5b1456d7..af0f7982b 100644 --- a/src/playlist_state.c +++ b/src/playlist_state.c @@ -35,6 +35,7 @@ #define PLAYLIST_STATE_FILE_RANDOM "random: " #define PLAYLIST_STATE_FILE_REPEAT "repeat: " #define PLAYLIST_STATE_FILE_SINGLE "single: " +#define PLAYLIST_STATE_FILE_CONSUME "consume: " #define PLAYLIST_STATE_FILE_CURRENT "current: " #define PLAYLIST_STATE_FILE_TIME "time: " #define PLAYLIST_STATE_FILE_CROSSFADE "crossfade: " @@ -74,6 +75,8 @@ playlist_state_save(FILE *fp, const struct playlist *playlist) playlist->queue.repeat); fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_SINGLE, playlist->queue.single); + fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_CONSUME, + playlist->queue.consume); fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_CROSSFADE, (int)(getPlayerCrossFade())); fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_PLAYLIST_BEGIN); @@ -146,6 +149,13 @@ playlist_state_restore(FILE *fp, struct playlist *playlist) setPlaylistSingleStatus(playlist, true); } else setPlaylistSingleStatus(playlist, false); + } else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_CONSUME)) { + if (strcmp + (&(buffer[strlen(PLAYLIST_STATE_FILE_CONSUME)]), + "1") == 0) { + setPlaylistConsumeStatus(playlist, true); + } else + setPlaylistConsumeStatus(playlist, false); } else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_CROSSFADE)) { setPlayerCrossFade(atoi (& diff --git a/src/queue.c b/src/queue.c index 21d4884c6..7cc110bc7 100644 --- a/src/queue.c +++ b/src/queue.c @@ -283,6 +283,7 @@ queue_init(struct queue *queue, unsigned max_length) queue->repeat = false; queue->random = false; queue->single = false; + queue->consume = false; queue->items = g_new(struct queue_item, max_length); queue->order = g_malloc(sizeof(queue->order[0]) * diff --git a/src/queue.h b/src/queue.h index 452084ce8..7dca66406 100644 --- a/src/queue.h +++ b/src/queue.h @@ -84,6 +84,9 @@ struct queue { /** play only current song. */ bool single; + /** remove each played files. */ + bool consume; + /** play back songs in random order? */ bool random; |