From e46722b2ebe05fce63bc7b86100c159b5cadd297 Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Fri, 27 Mar 2009 14:42:55 +0100 Subject: 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 --- doc/protocol.xml | 21 +++++++++++++++++++++ src/command.c | 22 ++++++++++++++++++++++ src/playlist.c | 20 ++++++++++++++++++++ src/playlist.h | 5 +++++ src/playlist_control.c | 2 ++ src/playlist_state.c | 13 +++++++++++-- src/queue.c | 3 +++ src/queue.h | 3 +++ 8 files changed, 87 insertions(+), 2 deletions(-) diff --git a/doc/protocol.xml b/doc/protocol.xml index 8f5b4b9e8..fc833f7bf 100644 --- a/doc/protocol.xml +++ b/doc/protocol.xml @@ -216,6 +216,12 @@ 0 or 1 + + + smartstop: + 0 or 1 + + playlist: @@ -402,6 +408,21 @@ + + + + smartstop + STATE + + + + + Sets smartstop state to STATE, + STATE should be 0 or 1. + When smartstop is activated, playback is stopped after current song. + + + diff --git a/src/command.c b/src/command.c index 1b8c45f26..82b088587 100644 --- a/src/command.c +++ b/src/command.c @@ -59,6 +59,7 @@ #define COMMAND_STATUS_VOLUME "volume" #define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_REPEAT "repeat" +#define COMMAND_STATUS_SMARTSTOP "smartstop" #define COMMAND_STATUS_RANDOM "random" #define COMMAND_STATUS_PLAYLIST "playlist" #define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength" @@ -469,6 +470,7 @@ handle_status(struct client *client, COMMAND_STATUS_VOLUME ": %i\n" COMMAND_STATUS_REPEAT ": %i\n" COMMAND_STATUS_RANDOM ": %i\n" + COMMAND_STATUS_SMARTSTOP ": %i\n" COMMAND_STATUS_PLAYLIST ": %li\n" COMMAND_STATUS_PLAYLIST_LENGTH ": %i\n" COMMAND_STATUS_CROSSFADE ": %i\n" @@ -476,6 +478,7 @@ handle_status(struct client *client, volume_level_get(), getPlaylistRepeatStatus(&g_playlist), getPlaylistRandomStatus(&g_playlist), + getPlaylistSmartstopStatus(&g_playlist), getPlaylistVersion(&g_playlist), getPlaylistLength(&g_playlist), (int)(getPlayerCrossFade() + 0.5), @@ -1092,6 +1095,24 @@ handle_repeat(struct client *client, G_GNUC_UNUSED int argc, char *argv[]) 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 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 }, { "setvol", PERMISSION_CONTROL, 1, 1, handle_setvol }, { "shuffle", PERMISSION_CONTROL, 0, 1, handle_shuffle }, + { "smartstop", PERMISSION_CONTROL, 1, 1, handle_smartstop }, { "stats", PERMISSION_READ, 0, 0, handle_stats }, { "status", PERMISSION_READ, 0, 0, handle_status }, #ifdef ENABLE_SQLITE diff --git a/src/playlist.c b/src/playlist.c index 59923efc7..0ec46492a 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -261,6 +261,12 @@ getPlaylistRandomStatus(const struct playlist *playlist) return playlist->queue.random; } +bool +getPlaylistSmartstopStatus(const struct playlist *playlist) +{ + return playlist->queue.smartstop; +} + void setPlaylistRepeatStatus(struct playlist *playlist, bool status) { if (status == playlist->queue.repeat) @@ -286,6 +292,18 @@ static void orderPlaylist(struct playlist *playlist) 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) { const struct song *queued; @@ -341,6 +359,8 @@ int getPlaylistNextSong(const struct playlist *playlist) { if (playlist->current >= 0) { + if (playlist->queue.smartstop == 1) + return -1; if (playlist->current + 1 < (int)queue_length(&playlist->queue)) return queue_order_to_position(&playlist->queue, playlist->current + 1); diff --git a/src/playlist.h b/src/playlist.h index 41befe455..4e11ec421 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -179,6 +179,11 @@ getPlaylistRandomStatus(const struct playlist *playlist); 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 getPlaylistNextSong(const struct playlist *playlist); diff --git a/src/playlist_control.c b/src/playlist_control.c index 666bdc2ba..90aab5f29 100644 --- a/src/playlist_control.c +++ b/src/playlist_control.c @@ -152,6 +152,8 @@ nextSongInPlaylist(struct playlist *playlist) next_order = queue_next_order(&playlist->queue, playlist->current); if (next_order < 0) { + /* cancel smartstop */ + playlist->queue.smartstop = false; /* no song after this one: stop playback */ stopPlaylist(playlist); return; diff --git a/src/playlist_state.c b/src/playlist_state.c index b6636fa54..6d1756eed 100644 --- a/src/playlist_state.c +++ b/src/playlist_state.c @@ -34,6 +34,7 @@ #define PLAYLIST_STATE_FILE_STATE "state: " #define PLAYLIST_STATE_FILE_RANDOM "random: " #define PLAYLIST_STATE_FILE_REPEAT "repeat: " +#define PLAYLIST_STATE_FILE_SMARTSTOP "smartstop: " #define PLAYLIST_STATE_FILE_CURRENT "current: " #define PLAYLIST_STATE_FILE_TIME "time: " #define PLAYLIST_STATE_FILE_CROSSFADE "crossfade: " @@ -71,6 +72,8 @@ playlist_state_save(FILE *fp, const struct playlist *playlist) playlist->queue.random); fprintf(fp, "%s%i\n", PLAYLIST_STATE_FILE_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, (int)(getPlayerCrossFade())); 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)) { seek_time = atoi(&(buffer[strlen(PLAYLIST_STATE_FILE_TIME)])); - } else - if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_REPEAT)) { + } else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_REPEAT)) { if (strcmp (&(buffer[strlen(PLAYLIST_STATE_FILE_REPEAT)]), "1") == 0) { setPlaylistRepeatStatus(playlist, true); } else 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)) { setPlayerCrossFade(atoi (& diff --git a/src/queue.c b/src/queue.c index b9486cfe5..28da0e5a3 100644 --- a/src/queue.c +++ b/src/queue.c @@ -40,6 +40,8 @@ queue_next_order(const struct queue *queue, unsigned order) { assert(order < queue->length); + if (queue->smartstop) + return -1; if (order + 1 < queue->length) return order + 1; else if (queue->repeat) @@ -275,6 +277,7 @@ queue_init(struct queue *queue, unsigned max_length) queue->version = 1; queue->repeat = false; queue->random = false; + queue->smartstop = 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 7f46c2e19..63b71d199 100644 --- a/src/queue.h +++ b/src/queue.h @@ -81,6 +81,9 @@ struct queue { reached? */ bool repeat; + /** stop playing after that song. */ + bool smartstop; + /** play back songs in random order? */ bool random; -- cgit v1.2.3