implements the smartstop feature
The smartstop feature is a way to tell mpd to stop playing after current song. This patche provides: - 'state' command returns 'smartstop' state (1 or 0) - 'smartstop' can activate or not the smartstop state - when song is terminated, mpd stops playing and smartstop is set to 0
This commit is contained in:
parent
929c200c38
commit
e46722b2eb
@ -216,6 +216,12 @@
|
|||||||
<returnvalue>0 or 1</returnvalue>
|
<returnvalue>0 or 1</returnvalue>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>smartstop</varname>:
|
||||||
|
<returnvalue>0 or 1</returnvalue>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<varname>playlist</varname>:
|
<varname>playlist</varname>:
|
||||||
@ -402,6 +408,21 @@
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry id="command_smartstop">
|
||||||
|
<term>
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>smartstop</command>
|
||||||
|
<arg choice="req"><replaceable>STATE</replaceable></arg>
|
||||||
|
</cmdsynopsis>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Sets smartstop state to <varname>STATE</varname>,
|
||||||
|
<varname>STATE</varname> should be 0 or 1.
|
||||||
|
When smartstop is activated, playback is stopped after current song.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry id="command_volume">
|
<varlistentry id="command_volume">
|
||||||
<term>
|
<term>
|
||||||
<cmdsynopsis>
|
<cmdsynopsis>
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#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_SMARTSTOP "smartstop"
|
||||||
#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"
|
||||||
@ -469,6 +470,7 @@ handle_status(struct client *client,
|
|||||||
COMMAND_STATUS_VOLUME ": %i\n"
|
COMMAND_STATUS_VOLUME ": %i\n"
|
||||||
COMMAND_STATUS_REPEAT ": %i\n"
|
COMMAND_STATUS_REPEAT ": %i\n"
|
||||||
COMMAND_STATUS_RANDOM ": %i\n"
|
COMMAND_STATUS_RANDOM ": %i\n"
|
||||||
|
COMMAND_STATUS_SMARTSTOP ": %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"
|
||||||
@ -476,6 +478,7 @@ handle_status(struct client *client,
|
|||||||
volume_level_get(),
|
volume_level_get(),
|
||||||
getPlaylistRepeatStatus(&g_playlist),
|
getPlaylistRepeatStatus(&g_playlist),
|
||||||
getPlaylistRandomStatus(&g_playlist),
|
getPlaylistRandomStatus(&g_playlist),
|
||||||
|
getPlaylistSmartstopStatus(&g_playlist),
|
||||||
getPlaylistVersion(&g_playlist),
|
getPlaylistVersion(&g_playlist),
|
||||||
getPlaylistLength(&g_playlist),
|
getPlaylistLength(&g_playlist),
|
||||||
(int)(getPlayerCrossFade() + 0.5),
|
(int)(getPlayerCrossFade() + 0.5),
|
||||||
@ -1092,6 +1095,24 @@ handle_repeat(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
|
|||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum command_return
|
||||||
|
handle_smartstop(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlaylistSmartstopStatus(&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[])
|
||||||
{
|
{
|
||||||
@ -1602,6 +1623,7 @@ static const struct command commands[] = {
|
|||||||
{ "seekid", PERMISSION_CONTROL, 2, 2, handle_seekid },
|
{ "seekid", PERMISSION_CONTROL, 2, 2, handle_seekid },
|
||||||
{ "setvol", PERMISSION_CONTROL, 1, 1, handle_setvol },
|
{ "setvol", PERMISSION_CONTROL, 1, 1, handle_setvol },
|
||||||
{ "shuffle", PERMISSION_CONTROL, 0, 1, handle_shuffle },
|
{ "shuffle", PERMISSION_CONTROL, 0, 1, handle_shuffle },
|
||||||
|
{ "smartstop", PERMISSION_CONTROL, 1, 1, handle_smartstop },
|
||||||
{ "stats", PERMISSION_READ, 0, 0, handle_stats },
|
{ "stats", PERMISSION_READ, 0, 0, handle_stats },
|
||||||
{ "status", PERMISSION_READ, 0, 0, handle_status },
|
{ "status", PERMISSION_READ, 0, 0, handle_status },
|
||||||
#ifdef ENABLE_SQLITE
|
#ifdef ENABLE_SQLITE
|
||||||
|
@ -261,6 +261,12 @@ getPlaylistRandomStatus(const struct playlist *playlist)
|
|||||||
return playlist->queue.random;
|
return playlist->queue.random;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
getPlaylistSmartstopStatus(const struct playlist *playlist)
|
||||||
|
{
|
||||||
|
return playlist->queue.smartstop;
|
||||||
|
}
|
||||||
|
|
||||||
void setPlaylistRepeatStatus(struct playlist *playlist, bool status)
|
void setPlaylistRepeatStatus(struct playlist *playlist, bool status)
|
||||||
{
|
{
|
||||||
if (status == playlist->queue.repeat)
|
if (status == playlist->queue.repeat)
|
||||||
@ -286,6 +292,18 @@ static void orderPlaylist(struct playlist *playlist)
|
|||||||
queue_restore_order(&playlist->queue);
|
queue_restore_order(&playlist->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPlaylistSmartstopStatus(struct playlist *playlist, bool status)
|
||||||
|
{
|
||||||
|
playlist->queue.smartstop = status;
|
||||||
|
|
||||||
|
/* if the last song is currently being played, the "next song"
|
||||||
|
might change when repeat mode is toggled */
|
||||||
|
playlist_update_queued_song(playlist,
|
||||||
|
playlist_get_queued_song(playlist));
|
||||||
|
|
||||||
|
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;
|
||||||
@ -341,6 +359,8 @@ int getPlaylistNextSong(const struct playlist *playlist)
|
|||||||
{
|
{
|
||||||
if (playlist->current >= 0)
|
if (playlist->current >= 0)
|
||||||
{
|
{
|
||||||
|
if (playlist->queue.smartstop == 1)
|
||||||
|
return -1;
|
||||||
if (playlist->current + 1 < (int)queue_length(&playlist->queue))
|
if (playlist->current + 1 < (int)queue_length(&playlist->queue))
|
||||||
return queue_order_to_position(&playlist->queue,
|
return queue_order_to_position(&playlist->queue,
|
||||||
playlist->current + 1);
|
playlist->current + 1);
|
||||||
|
@ -179,6 +179,11 @@ getPlaylistRandomStatus(const struct playlist *playlist);
|
|||||||
|
|
||||||
void setPlaylistRandomStatus(struct playlist *playlist, bool status);
|
void setPlaylistRandomStatus(struct playlist *playlist, bool status);
|
||||||
|
|
||||||
|
bool
|
||||||
|
getPlaylistSmartstopStatus(const struct playlist *playlist);
|
||||||
|
|
||||||
|
void setPlaylistSmartstopStatus(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);
|
||||||
|
@ -152,6 +152,8 @@ nextSongInPlaylist(struct playlist *playlist)
|
|||||||
|
|
||||||
next_order = queue_next_order(&playlist->queue, playlist->current);
|
next_order = queue_next_order(&playlist->queue, playlist->current);
|
||||||
if (next_order < 0) {
|
if (next_order < 0) {
|
||||||
|
/* cancel smartstop */
|
||||||
|
playlist->queue.smartstop = false;
|
||||||
/* no song after this one: stop playback */
|
/* no song after this one: stop playback */
|
||||||
stopPlaylist(playlist);
|
stopPlaylist(playlist);
|
||||||
return;
|
return;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#define PLAYLIST_STATE_FILE_STATE "state: "
|
#define PLAYLIST_STATE_FILE_STATE "state: "
|
||||||
#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_SMARTSTOP "smartstop: "
|
||||||
#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: "
|
||||||
@ -71,6 +72,8 @@ playlist_state_save(FILE *fp, const struct playlist *playlist)
|
|||||||
playlist->queue.random);
|
playlist->queue.random);
|
||||||
fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_REPEAT,
|
fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_REPEAT,
|
||||||
playlist->queue.repeat);
|
playlist->queue.repeat);
|
||||||
|
fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_SMARTSTOP,
|
||||||
|
playlist->queue.smartstop);
|
||||||
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);
|
||||||
@ -129,14 +132,20 @@ playlist_state_restore(FILE *fp, struct playlist *playlist)
|
|||||||
} else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_TIME)) {
|
} else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_TIME)) {
|
||||||
seek_time =
|
seek_time =
|
||||||
atoi(&(buffer[strlen(PLAYLIST_STATE_FILE_TIME)]));
|
atoi(&(buffer[strlen(PLAYLIST_STATE_FILE_TIME)]));
|
||||||
} else
|
} else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_REPEAT)) {
|
||||||
if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_REPEAT)) {
|
|
||||||
if (strcmp
|
if (strcmp
|
||||||
(&(buffer[strlen(PLAYLIST_STATE_FILE_REPEAT)]),
|
(&(buffer[strlen(PLAYLIST_STATE_FILE_REPEAT)]),
|
||||||
"1") == 0) {
|
"1") == 0) {
|
||||||
setPlaylistRepeatStatus(playlist, true);
|
setPlaylistRepeatStatus(playlist, true);
|
||||||
} else
|
} else
|
||||||
setPlaylistRepeatStatus(playlist, false);
|
setPlaylistRepeatStatus(playlist, false);
|
||||||
|
} else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_SMARTSTOP)) {
|
||||||
|
if (strcmp
|
||||||
|
(&(buffer[strlen(PLAYLIST_STATE_FILE_SMARTSTOP)]),
|
||||||
|
"1") == 0) {
|
||||||
|
setPlaylistSmartstopStatus(playlist, true);
|
||||||
|
} else
|
||||||
|
setPlaylistSmartstopStatus(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
|
||||||
(&
|
(&
|
||||||
|
@ -40,6 +40,8 @@ queue_next_order(const struct queue *queue, unsigned order)
|
|||||||
{
|
{
|
||||||
assert(order < queue->length);
|
assert(order < queue->length);
|
||||||
|
|
||||||
|
if (queue->smartstop)
|
||||||
|
return -1;
|
||||||
if (order + 1 < queue->length)
|
if (order + 1 < queue->length)
|
||||||
return order + 1;
|
return order + 1;
|
||||||
else if (queue->repeat)
|
else if (queue->repeat)
|
||||||
@ -275,6 +277,7 @@ queue_init(struct queue *queue, unsigned max_length)
|
|||||||
queue->version = 1;
|
queue->version = 1;
|
||||||
queue->repeat = false;
|
queue->repeat = false;
|
||||||
queue->random = false;
|
queue->random = false;
|
||||||
|
queue->smartstop = 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]) *
|
||||||
|
@ -81,6 +81,9 @@ struct queue {
|
|||||||
reached? */
|
reached? */
|
||||||
bool repeat;
|
bool repeat;
|
||||||
|
|
||||||
|
/** stop playing after that song. */
|
||||||
|
bool smartstop;
|
||||||
|
|
||||||
/** play back songs in random order? */
|
/** play back songs in random order? */
|
||||||
bool random;
|
bool random;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user