implemented the 'consume' mode
Consume mode removes each song played
This commit is contained in:
parent
7d9380fd91
commit
e81f683a18
@ -222,6 +222,12 @@
|
|||||||
<returnvalue>0 or 1</returnvalue>
|
<returnvalue>0 or 1</returnvalue>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>consume</varname>:
|
||||||
|
<returnvalue>0 or 1</returnvalue>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<varname>playlist</varname>:
|
<varname>playlist</varname>:
|
||||||
@ -352,6 +358,21 @@
|
|||||||
<section>
|
<section>
|
||||||
<title>Playback options</title>
|
<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>
|
<variablelist>
|
||||||
<varlistentry id="command_crossfade">
|
<varlistentry id="command_crossfade">
|
||||||
<term>
|
<term>
|
||||||
|
@ -59,7 +59,8 @@
|
|||||||
#define COMMAND_STATUS_VOLUME "volume"
|
#define COMMAND_STATUS_VOLUME "volume"
|
||||||
#define COMMAND_STATUS_STATE "state"
|
#define COMMAND_STATUS_STATE "state"
|
||||||
#define COMMAND_STATUS_REPEAT "repeat"
|
#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_RANDOM "random"
|
||||||
#define COMMAND_STATUS_PLAYLIST "playlist"
|
#define COMMAND_STATUS_PLAYLIST "playlist"
|
||||||
#define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength"
|
#define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength"
|
||||||
@ -471,6 +472,7 @@ handle_status(struct client *client,
|
|||||||
COMMAND_STATUS_REPEAT ": %i\n"
|
COMMAND_STATUS_REPEAT ": %i\n"
|
||||||
COMMAND_STATUS_RANDOM ": %i\n"
|
COMMAND_STATUS_RANDOM ": %i\n"
|
||||||
COMMAND_STATUS_SINGLE ": %i\n"
|
COMMAND_STATUS_SINGLE ": %i\n"
|
||||||
|
COMMAND_STATUS_CONSUME ": %i\n"
|
||||||
COMMAND_STATUS_PLAYLIST ": %li\n"
|
COMMAND_STATUS_PLAYLIST ": %li\n"
|
||||||
COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n"
|
COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n"
|
||||||
COMMAND_STATUS_CROSSFADE ": %i\n"
|
COMMAND_STATUS_CROSSFADE ": %i\n"
|
||||||
@ -479,6 +481,7 @@ handle_status(struct client *client,
|
|||||||
getPlaylistRepeatStatus(&g_playlist),
|
getPlaylistRepeatStatus(&g_playlist),
|
||||||
getPlaylistRandomStatus(&g_playlist),
|
getPlaylistRandomStatus(&g_playlist),
|
||||||
getPlaylistSingleStatus(&g_playlist),
|
getPlaylistSingleStatus(&g_playlist),
|
||||||
|
getPlaylistConsumeStatus(&g_playlist),
|
||||||
getPlaylistVersion(&g_playlist),
|
getPlaylistVersion(&g_playlist),
|
||||||
getPlaylistLength(&g_playlist),
|
getPlaylistLength(&g_playlist),
|
||||||
(int)(getPlayerCrossFade() + 0.5),
|
(int)(getPlayerCrossFade() + 0.5),
|
||||||
@ -1113,6 +1116,24 @@ handle_single(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
|
|||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static enum command_return
|
||||||
handle_random(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
|
handle_random(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -1573,6 +1594,7 @@ static const struct command commands[] = {
|
|||||||
{ "clearerror", PERMISSION_CONTROL, 0, 0, handle_clearerror },
|
{ "clearerror", PERMISSION_CONTROL, 0, 0, handle_clearerror },
|
||||||
{ "close", PERMISSION_NONE, -1, -1, handle_close },
|
{ "close", PERMISSION_NONE, -1, -1, handle_close },
|
||||||
{ "commands", PERMISSION_NONE, 0, 0, handle_commands },
|
{ "commands", PERMISSION_NONE, 0, 0, handle_commands },
|
||||||
|
{ "consume", PERMISSION_CONTROL, 1, 1, handle_consume },
|
||||||
{ "count", PERMISSION_READ, 2, -1, handle_count },
|
{ "count", PERMISSION_READ, 2, -1, handle_count },
|
||||||
{ "crossfade", PERMISSION_CONTROL, 1, 1, handle_crossfade },
|
{ "crossfade", PERMISSION_CONTROL, 1, 1, handle_crossfade },
|
||||||
{ "currentsong", PERMISSION_READ, 0, 0, handle_currentsong },
|
{ "currentsong", PERMISSION_READ, 0, 0, handle_currentsong },
|
||||||
|
@ -100,9 +100,13 @@ static void syncPlaylistWithQueue(struct playlist *playlist)
|
|||||||
/* queued song has started: copy queued to current,
|
/* queued song has started: copy queued to current,
|
||||||
and notify the clients */
|
and notify the clients */
|
||||||
|
|
||||||
|
int current = playlist->current;
|
||||||
playlist->current = playlist->queued;
|
playlist->current = playlist->queued;
|
||||||
playlist->queued = -1;
|
playlist->queued = -1;
|
||||||
|
|
||||||
|
if(playlist->queue.consume)
|
||||||
|
deleteFromPlaylist(playlist, queue_order_to_position(&playlist->queue, current));
|
||||||
|
|
||||||
idle_add(IDLE_PLAYER);
|
idle_add(IDLE_PLAYER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,6 +271,12 @@ getPlaylistSingleStatus(const struct playlist *playlist)
|
|||||||
return playlist->queue.single;
|
return playlist->queue.single;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
getPlaylistConsumeStatus(const struct playlist *playlist)
|
||||||
|
{
|
||||||
|
return playlist->queue.consume;
|
||||||
|
}
|
||||||
|
|
||||||
void setPlaylistRepeatStatus(struct playlist *playlist, bool status)
|
void setPlaylistRepeatStatus(struct playlist *playlist, bool status)
|
||||||
{
|
{
|
||||||
if (status == playlist->queue.repeat)
|
if (status == playlist->queue.repeat)
|
||||||
@ -307,6 +317,15 @@ void setPlaylistSingleStatus(struct playlist *playlist, bool status)
|
|||||||
idle_add(IDLE_OPTIONS);
|
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)
|
void setPlaylistRandomStatus(struct playlist *playlist, bool status)
|
||||||
{
|
{
|
||||||
const struct song *queued;
|
const struct song *queued;
|
||||||
|
@ -184,6 +184,11 @@ getPlaylistSingleStatus(const struct playlist *playlist);
|
|||||||
|
|
||||||
void setPlaylistSingleStatus(struct playlist *playlist, bool status);
|
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 getPlaylistCurrentSong(const struct playlist *playlist);
|
||||||
|
|
||||||
int getPlaylistNextSong(const struct playlist *playlist);
|
int getPlaylistNextSong(const struct playlist *playlist);
|
||||||
|
@ -139,6 +139,7 @@ void
|
|||||||
nextSongInPlaylist(struct playlist *playlist)
|
nextSongInPlaylist(struct playlist *playlist)
|
||||||
{
|
{
|
||||||
int next_order;
|
int next_order;
|
||||||
|
int current;
|
||||||
|
|
||||||
if (!playlist->playing)
|
if (!playlist->playing)
|
||||||
return;
|
return;
|
||||||
@ -146,6 +147,7 @@ nextSongInPlaylist(struct playlist *playlist)
|
|||||||
assert(!queue_is_empty(&playlist->queue));
|
assert(!queue_is_empty(&playlist->queue));
|
||||||
assert(queue_valid_order(&playlist->queue, playlist->current));
|
assert(queue_valid_order(&playlist->queue, playlist->current));
|
||||||
|
|
||||||
|
current = playlist->current;
|
||||||
playlist->stop_on_error = false;
|
playlist->stop_on_error = false;
|
||||||
|
|
||||||
/* determine the next song from the queue's order list */
|
/* determine the next song from the queue's order list */
|
||||||
@ -156,24 +158,29 @@ nextSongInPlaylist(struct playlist *playlist)
|
|||||||
playlist->queue.single = false;
|
playlist->queue.single = false;
|
||||||
/* no song after this one: stop playback */
|
/* no song after this one: stop playback */
|
||||||
stopPlaylist(playlist);
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
playPlaylistOrderNumber(playlist, next_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next_order == 0 && playlist->queue.random) {
|
/* Consume mode removes each played songs. */
|
||||||
/* The queue told us that the next song is the first
|
if(playlist->queue.consume)
|
||||||
song. This means we are in repeat mode. Shuffle
|
deleteFromPlaylist(playlist, queue_order_to_position(&playlist->queue, current));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void previousSongInPlaylist(struct playlist *playlist)
|
void previousSongInPlaylist(struct playlist *playlist)
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#define PLAYLIST_STATE_FILE_RANDOM "random: "
|
#define PLAYLIST_STATE_FILE_RANDOM "random: "
|
||||||
#define PLAYLIST_STATE_FILE_REPEAT "repeat: "
|
#define PLAYLIST_STATE_FILE_REPEAT "repeat: "
|
||||||
#define PLAYLIST_STATE_FILE_SINGLE "single: "
|
#define PLAYLIST_STATE_FILE_SINGLE "single: "
|
||||||
|
#define PLAYLIST_STATE_FILE_CONSUME "consume: "
|
||||||
#define PLAYLIST_STATE_FILE_CURRENT "current: "
|
#define PLAYLIST_STATE_FILE_CURRENT "current: "
|
||||||
#define PLAYLIST_STATE_FILE_TIME "time: "
|
#define PLAYLIST_STATE_FILE_TIME "time: "
|
||||||
#define PLAYLIST_STATE_FILE_CROSSFADE "crossfade: "
|
#define PLAYLIST_STATE_FILE_CROSSFADE "crossfade: "
|
||||||
@ -74,6 +75,8 @@ playlist_state_save(FILE *fp, const struct playlist *playlist)
|
|||||||
playlist->queue.repeat);
|
playlist->queue.repeat);
|
||||||
fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_SINGLE,
|
fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_SINGLE,
|
||||||
playlist->queue.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,
|
fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_CROSSFADE,
|
||||||
(int)(getPlayerCrossFade()));
|
(int)(getPlayerCrossFade()));
|
||||||
fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_PLAYLIST_BEGIN);
|
fprintf(fp, "%s\n", PLAYLIST_STATE_FILE_PLAYLIST_BEGIN);
|
||||||
@ -146,6 +149,13 @@ playlist_state_restore(FILE *fp, struct playlist *playlist)
|
|||||||
setPlaylistSingleStatus(playlist, true);
|
setPlaylistSingleStatus(playlist, true);
|
||||||
} else
|
} else
|
||||||
setPlaylistSingleStatus(playlist, false);
|
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)) {
|
} else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_CROSSFADE)) {
|
||||||
setPlayerCrossFade(atoi
|
setPlayerCrossFade(atoi
|
||||||
(&
|
(&
|
||||||
|
@ -283,6 +283,7 @@ queue_init(struct queue *queue, unsigned max_length)
|
|||||||
queue->repeat = false;
|
queue->repeat = false;
|
||||||
queue->random = false;
|
queue->random = false;
|
||||||
queue->single = false;
|
queue->single = false;
|
||||||
|
queue->consume = false;
|
||||||
|
|
||||||
queue->items = g_new(struct queue_item, max_length);
|
queue->items = g_new(struct queue_item, max_length);
|
||||||
queue->order = g_malloc(sizeof(queue->order[0]) *
|
queue->order = g_malloc(sizeof(queue->order[0]) *
|
||||||
|
@ -84,6 +84,9 @@ struct queue {
|
|||||||
/** play only current song. */
|
/** play only current song. */
|
||||||
bool single;
|
bool single;
|
||||||
|
|
||||||
|
/** remove each played files. */
|
||||||
|
bool consume;
|
||||||
|
|
||||||
/** play back songs in random order? */
|
/** play back songs in random order? */
|
||||||
bool random;
|
bool random;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user