diff --git a/contrib/mympd.conf.dist b/contrib/mympd.conf.dist index 4188933..5d20904 100644 --- a/contrib/mympd.conf.dist +++ b/contrib/mympd.conf.dist @@ -37,4 +37,16 @@ stickers = true taglist = Artist,Album,AlbumArtist,Title,Track,Genre,Date,Composer,Performer #Enable smart playlists -smartplaylists = true +smartpls = true + +#Newest songs = newest song minus one week +smartpls_newest = 604800 + +#Add max songs to myMPDsmart-newestSongs +smartpls_maxnewest = 200 + +#Add max songs to myMPDsmart-bestRated +smartpls_maxlike = 200 + +#Add max songs to myMPDsmart-mostPlayed +smartpls_maxplaycount = 200 diff --git a/src/mpd_client.c b/src/mpd_client.c index f4e88bf..a66d8f6 100644 --- a/src/mpd_client.c +++ b/src/mpd_client.c @@ -636,9 +636,9 @@ void mympd_mpd_features() { printf("MPD don't support stickers, disabling myMPD feature\n"); config.stickers = false; } - if (config.stickers == false && config.smartplaylists == true) { + if (config.stickers == false && config.smartpls == true) { printf("Stickers are disabled, disabling smartplaylists\n"); - config.smartplaylists = false; + config.smartpls = false; } printf("MPD supported tags: "); @@ -1883,12 +1883,38 @@ void mympd_disconnect() { } int mympd_smartpls_update_all() { - if (!config.smartplaylists) + if (!config.smartpls) return 0; if (mympd_smartpls_update("like", "myMPDsmart-bestRated") != 0) return 1; if (mympd_smartpls_update("playCount", "myMPDsmart-mostPlayed") != 0) return 1; + if (mympd_smartpls_update_newest("myMPDsmart-newestSongs") != 0) + return 1; + return 0; +} + +int mympd_smartpls_clear(char *playlist) { + struct mpd_playlist *pl; + const char *plpath; + bool exists = false; + if (!mpd_send_list_playlists(mpd.conn)) { + LOG_ERROR_AND_RECOVER("mpd_send_list_playlists"); + return 1; + } + while((pl = mpd_recv_playlist(mpd.conn)) != NULL) { + plpath = mpd_playlist_get_path(pl); + if (strcmp(playlist, plpath) == 0) + exists = true; + mpd_playlist_free(pl); + } + + if (exists) { + if (!mpd_run_rm(mpd.conn, playlist)) { + LOG_ERROR_AND_RECOVER("mpd_run_rm"); + return 1; + } + } return 0; } @@ -1902,18 +1928,15 @@ int mympd_smartpls_update(char *sticker, char *playlist) { long value_max = 0; size_t len = 0; ssize_t read; - unsigned i = 0; - struct mpd_playlist *pl; - const char *plpath; - bool exists = false; - + long i = 0; + FILE *fp = fopen("/var/lib/mympd/tmp/playlist.tmp", "w"); if (fp == NULL) { printf("Error opening /var/lib/mympd/tmp/playlist.tmp"); return 1; } if (!mpd_send_sticker_find(mpd.conn, "song", "", sticker)) { - LOG_ERROR_AND_RECOVER("mpd_run_rm"); + LOG_ERROR_AND_RECOVER("mpd_send_sticker_find"); return 1; } while ((pair = mpd_recv_pair(mpd.conn)) != NULL) { @@ -1934,23 +1957,8 @@ int mympd_smartpls_update(char *sticker, char *playlist) { mpd_response_finish(mpd.conn); fclose(fp); - if (!mpd_send_list_playlists(mpd.conn)) { - LOG_ERROR_AND_RECOVER("mpd_run_rm"); - return 1; - } - while((pl = mpd_recv_playlist(mpd.conn)) != NULL) { - plpath = mpd_playlist_get_path(pl); - if (strcmp(playlist, plpath) == 0) - exists = true; - mpd_playlist_free(pl); - } - - if (exists) - if (!mpd_run_rm(mpd.conn, playlist)) { - LOG_ERROR_AND_RECOVER("mpd_run_rm"); - return 1; - } - + mympd_smartpls_clear(playlist); + if (value_max > 2) value_max = value_max / 2; fp = fopen("/var/lib/mympd/tmp/playlist.tmp", "r"); @@ -1966,6 +1974,75 @@ int mympd_smartpls_update(char *sticker, char *playlist) { if (value <= value_max) continue; } + if (!mpd_run_playlist_add(mpd.conn, playlist, name)) { + LOG_ERROR_AND_RECOVER("mpd_run_playlist_add"); + fclose(fp); + free(uri); + return 1; + } + i++; + if (strcmp(sticker, "playCount") == 0) { + if (i >= config.smartpls_maxplaycount) + break; + } + else if (strcmp(sticker, "like") == 0) { + if (i >= config.smartpls_maxlike) + break; + } + } + fclose(fp); + free(uri); + unlink("/var/lib/mympd/tmp/playlist.tmp"); + printf("Updated %s with %ld songs, minValue: %ld\n", playlist, i, value_max); + return 0; +} + +int mympd_smartpls_update_newest(char *playlist) { + struct mpd_song *song; + char *uri; + char *p_value; + char *name; + char *crap; + time_t value; + time_t value_max = 0; + size_t len = 0; + ssize_t read; + long i = 0; + + FILE *fp = fopen("/var/lib/mympd/tmp/playlist.tmp", "w"); + if (fp == NULL) { + printf("Error opening /var/lib/mympd/tmp/playlist.tmp"); + return 1; + } + if (!mpd_send_list_all_meta(mpd.conn, "/")) { + LOG_ERROR_AND_RECOVER("mpd_send_list_all_meta"); + return 1; + } + while ((song = mpd_recv_song(mpd.conn)) != NULL) { + value = mpd_song_get_last_modified(song); + if (value > value_max) + value_max = value; + fprintf(fp, "%s::%ld\n", mpd_song_get_uri(song), value); + mpd_song_free(song); + } + mpd_response_finish(mpd.conn); + fclose(fp); + + mympd_smartpls_clear(playlist); + + value_max -= config.smartpls_newest; //one week + + fp = fopen("/var/lib/mympd/tmp/playlist.tmp", "r"); + if (fp == NULL) { + printf("Error opening /var/lib/mympd/tmp/playlist.tmp"); + return 1; + } + while ((read = getline(&uri, &len, fp)) != -1) { + name = strtok(uri, "::"); + p_value = strtok(NULL, "::"); + value = strtol(p_value, &crap, 10); + if (value >= value_max) + continue; if (!mpd_run_playlist_add(mpd.conn, playlist, name)) { LOG_ERROR_AND_RECOVER("mpd_run_rm"); fclose(fp); @@ -1973,10 +2050,12 @@ int mympd_smartpls_update(char *sticker, char *playlist) { return 1; } i++; + if (i >= config.smartpls_maxnewest) + break; } fclose(fp); free(uri); unlink("/var/lib/mympd/tmp/playlist.tmp"); - printf("Updated %s with %u songs, minValue: %ld\n", playlist, i, value_max); + printf("Updated %s with %ld songs, minValue: %ld\n", playlist, i, value_max); return 0; } diff --git a/src/mpd_client.h b/src/mpd_client.h index d184b61..a1eeb7c 100644 --- a/src/mpd_client.h +++ b/src/mpd_client.h @@ -162,7 +162,11 @@ typedef struct { bool stickers; bool mixramp; const char* taglist; - bool smartplaylists; + bool smartpls; + long smartpls_newest; + long smartpls_maxnewest; + long smartpls_maxlike; + long smartpls_maxplaycount; } t_config; t_config config; @@ -199,7 +203,9 @@ void mympd_last_played_song_id(int song_id); void mympd_get_sticker(const char *uri, t_sticker *sticker); void mympd_jukebox(); int mympd_smartpls_update_all(); +int mympd_smartpls_clear(char *playlist); int mympd_smartpls_update(char *sticker, char *playlist); +int mympd_smartpls_update_newest(char *playlist); int mympd_get_updatedb_state(char *buffer); int mympd_put_state(char *buffer, int *current_song_id, int *next_song_id, int *last_song_id, unsigned *queue_version, unsigned *queue_length); int mympd_put_outputs(char *buffer); diff --git a/src/mympd.c b/src/mympd.c index 105cce5..4fd7e12 100644 --- a/src/mympd.c +++ b/src/mympd.c @@ -162,11 +162,19 @@ static int inihandler(void* user, const char* section, const char* name, const c p_config->stickers = true; else p_config->stickers = false; - else if (MATCH("smartplaylists")) + else if (MATCH("smartpls")) if (strcmp(value, "true") == 0) - p_config->smartplaylists = true; + p_config->smartpls = true; else - p_config->smartplaylists = false; + p_config->smartpls = false; + else if (MATCH("smartpls_newest")) + p_config->smartpls_newest = strtol(value, &crap, 10); + else if (MATCH("smartpls_maxnewest")) + p_config->smartpls_maxnewest = strtol(value, &crap, 10); + else if (MATCH("smartpls_maxlike")) + p_config->smartpls_maxlike = strtol(value, &crap, 10); + else if (MATCH("smartpls_maxplaycount")) + p_config->smartpls_maxplaycount = strtol(value, &crap, 10); else if (MATCH("mixramp")) if (strcmp(value, "true") == 0) p_config->mixramp = true; @@ -203,7 +211,9 @@ int main(int argc, char **argv) { config.stickers = true; config.mixramp = true; config.taglist = "Artist,Album,AlbumArtist,Title,Track,Genre,Date,Composer,Performer"; - config.smartplaylists = true; + config.smartpls = true; + config.smartpls_newest = 604800; + config.smartpls_maxnewest = 200; mpd.timeout = 3000; mpd.last_update_sticker_song_id = -1;