From 5ab2e6373493553cf7efad00d73b6174fb5839d3 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Tue, 26 Apr 2016 08:20:27 -0400 Subject: [PATCH] core/playlists/system: Move the unplayed tracks playlist into system.c Signed-off-by: Anna Schumaker --- core/audio.c | 5 +- core/collection.c | 5 +- core/playlists/system.c | 118 +++++++++++++++++++++++++------- include/core/playlists/system.h | 1 + tests/core/playlist.c | 10 ++- tests/core/playlists/system.c | 42 ++++++++++++ 6 files changed, 152 insertions(+), 29 deletions(-) diff --git a/core/audio.c b/core/audio.c index 10ed311b..38571ea9 100644 --- a/core/audio.c +++ b/core/audio.c @@ -5,6 +5,7 @@ #include #include #include +#include #include static struct file audio_file = FILE_INIT("cur_track", 0, 0); @@ -214,8 +215,10 @@ struct track *audio_prev() struct track *audio_eos() { /* Mark current track as played */ - if (audio_track) + if (audio_track) { track_played(audio_track); + playlist_update(PL_UNPLAYED); + } /* Check pause count and pick the next track */ if (audio_pause_count >= 0) { diff --git a/core/collection.c b/core/collection.c index 89578fe8..9443c432 100644 --- a/core/collection.c +++ b/core/collection.c @@ -54,8 +54,10 @@ static void __scan_path(struct scan_data *scan, const gchar *name) __scan_dir_later(scan->sd_lib, path); else { track = track_add(scan->sd_lib, path); - if (track) + if (track) { queue_add(&c_queue, track); + playlist_add(PL_UNPLAYED, track); + } } g_free(path); @@ -108,6 +110,7 @@ static bool __validate_library(void *data) if (collection_check_library(library) < 0) return true; queue_remove_all(&c_queue, track); + playlist_remove(PL_UNPLAYED, track); track_remove(track); } } diff --git a/core/playlists/system.c b/core/playlists/system.c index c327b328..3e1f521c 100644 --- a/core/playlists/system.c +++ b/core/playlists/system.c @@ -7,8 +7,18 @@ static struct file sys_file = FILE_INIT("playlist.db", 0, 0); static struct queue sys_playlists[SYS_PL_NUM_PLAYLISTS]; -static struct queue *pl_system_get_queue(const gchar *); +static bool __sys_pl_remove(enum sys_playlist_t, struct track *); +static enum sys_playlist_t __sys_pl_convert(const gchar *name) +{ + if (string_match(name, "Favorites")) + return SYS_PL_FAVORITES; + else if (string_match(name, "Hidden") || string_match(name, "Banned")) + return SYS_PL_HIDDEN; + else if (string_match(name, "Unplayed")) + return SYS_PL_UNPLAYED; + return SYS_PL_NUM_PLAYLISTS; +} static void __sys_pl_save() { @@ -26,7 +36,7 @@ static void __sys_pl_save() static bool __sys_pl_load() { - struct queue *queue; + enum sys_playlist_t plist; unsigned int i, n; gchar *name; @@ -37,8 +47,8 @@ static bool __sys_pl_load() for (i = 0; i < n; i++) { file_readf(&sys_file, "%*u %m[^\n]\n", &name); - queue = pl_system_get_queue(name); - queue_load_tracks(queue, &sys_file); + plist = __sys_pl_convert(name); + queue_load_tracks(&sys_playlists[plist], &sys_file); g_free(name); } @@ -46,42 +56,99 @@ static bool __sys_pl_load() return true; } +static bool __sys_pl_can_add(enum sys_playlist_t plist, struct track *track) +{ + if (track->tr_count == 0) + return plist == SYS_PL_UNPLAYED; + return false; +} + +static bool __sys_pl_add(enum sys_playlist_t plist, struct track *track) +{ + if (plist != SYS_PL_FAVORITES && plist != SYS_PL_HIDDEN) { + if (!__sys_pl_can_add(plist, track)) + return false; + if (queue_has(&sys_playlists[SYS_PL_HIDDEN], track)) + return false; + } + + if (queue_has(&sys_playlists[plist], track)) + return false; + queue_add(&sys_playlists[plist], track); + + switch (plist) { + case SYS_PL_HIDDEN: + __sys_pl_remove(SYS_PL_UNPLAYED, track); + case SYS_PL_FAVORITES: + __sys_pl_save(); + default: + break; + } + return true; +} + +static bool __sys_pl_remove(enum sys_playlist_t plist, struct track *track) +{ + if (!queue_remove_all(&sys_playlists[plist], track)) + return false; + + switch (plist) { + case SYS_PL_HIDDEN: + __sys_pl_add(SYS_PL_UNPLAYED, track); + case SYS_PL_FAVORITES: + __sys_pl_save(); + default: + break; + } + return true; +} + +static bool __sys_pl_update(enum sys_playlist_t plist) +{ + struct db_entry *dbe, *next; + + db_for_each(dbe, next, track_db_get()) { + if (TRACK(dbe)->tr_count == 0) + __sys_pl_add(SYS_PL_UNPLAYED, TRACK(dbe)); + else + __sys_pl_remove(SYS_PL_UNPLAYED, TRACK(dbe)); + } + + queue_unset_flag(&sys_playlists[plist], Q_ADD_FRONT); + return true; +} + static struct queue *pl_system_get_queue(const gchar *name) { - if (string_match(name, "Favorites")) - return &sys_playlists[SYS_PL_FAVORITES]; - else if (string_match(name, "Hidden") || string_match(name, "Banned")) - return &sys_playlists[SYS_PL_HIDDEN]; - return NULL; + enum sys_playlist_t plist = __sys_pl_convert(name); + if (plist == SYS_PL_NUM_PLAYLISTS) + return NULL; + return &sys_playlists[plist]; } static bool pl_system_add_track(const gchar *name, struct track *track) { - struct queue *queue = pl_system_get_queue(name); - if (!queue) + enum sys_playlist_t plist = __sys_pl_convert(name); + if (plist == SYS_PL_NUM_PLAYLISTS) return false; - if (queue_has(queue, track)) - return false; - queue_add(queue, track); - __sys_pl_save(); - return true; + return __sys_pl_add(plist, track); } static bool pl_system_remove_track(const gchar *name, struct track *track) { - struct queue *queue = pl_system_get_queue(name); - if (!queue) + enum sys_playlist_t plist = __sys_pl_convert(name); + if (plist == SYS_PL_NUM_PLAYLISTS) return false; - if (!queue_remove_all(queue, track)) - return false; - __sys_pl_save(); - return true; + return __sys_pl_remove(plist, track); } static void pl_system_update(const gchar *name) { - return; + enum sys_playlist_t plist = __sys_pl_convert(name); + if (plist != SYS_PL_FAVORITES && plist != SYS_PL_HIDDEN) + idle_schedule(IDLE_SYNC, IDLE_FUNC(__sys_pl_update), + GUINT_TO_POINTER(plist)); } @@ -102,9 +169,12 @@ void pl_system_init(struct queue_ops *ops) queue_sort(&sys_playlists[i], COMPARE_ARTIST, true); queue_sort(&sys_playlists[i], COMPARE_YEAR, false); queue_sort(&sys_playlists[i], COMPARE_TRACK, false); + if (i >= SYS_PL_UNPLAYED) + queue_set_flag(&sys_playlists[i], Q_ADD_FRONT); } - idle_schedule(IDLE_SYNC, __sys_pl_load, NULL); + idle_schedule(IDLE_SYNC, __sys_pl_load, NULL); + pl_system_update("Unplayed"); } void pl_system_deinit() diff --git a/include/core/playlists/system.h b/include/core/playlists/system.h index 844a79cf..620d45a7 100644 --- a/include/core/playlists/system.h +++ b/include/core/playlists/system.h @@ -9,6 +9,7 @@ enum sys_playlist_t { SYS_PL_FAVORITES, /* Songs that the user likes. */ SYS_PL_HIDDEN, /* Songs that the user has hidden. */ + SYS_PL_UNPLAYED, /* Songs that have not been played yet. */ SYS_PL_NUM_PLAYLISTS, /* Number of system playlists. */ }; diff --git a/tests/core/playlist.c b/tests/core/playlist.c index ba87fb76..ddd836bd 100644 --- a/tests/core/playlist.c +++ b/tests/core/playlist.c @@ -115,10 +115,10 @@ static void test_remove() static void test_dynamic() { - struct queue *q = playlist_get_queue(PL_UNPLAYED); struct db_entry *dbe, *next; unsigned int i, average = 0; struct track *track; + struct queue *q; /* Set play count to (track_number - 1) (average = 6) */ db_for_each(dbe, next, track_db_get()) { @@ -127,16 +127,19 @@ static void test_dynamic() average += TRACK(dbe)->tr_count; } average /= track_db_get()->db_size; + playlist_update(PL_UNPLAYED); /* Only one unplayed track (tr_track == 1) */ - playlist_select(PL_UNPLAYED); + q = playlist_get_queue(PL_UNPLAYED); test_equal(playlist_add(PL_UNPLAYED, track_get(1)), (bool)false); - test_equal(playlist_remove(PL_UNPLAYED, queue_at(q, 0)), (bool)false); + test_equal(playlist_remove(PL_UNPLAYED, queue_at(q, 0)), (bool)true); + test_equal(playlist_add(PL_UNPLAYED, track_get(0)), (bool)true); test_equal(queue_size(q), 1); test_equal(queue_at(q, 0)->tr_track, 1); test_equal(queue_at(q, 0)->tr_count, 0); /* Six tracks have tr_count <= average && tr_count > 0 */ + q = playlist_get_queue(PL_LEAST_PLAYED); playlist_select(PL_LEAST_PLAYED); test_equal(playlist_add(PL_LEAST_PLAYED, track_get(0)), (bool)false); test_equal(queue_size(q), 6); @@ -149,6 +152,7 @@ static void test_dynamic() } test_loop_passed(); /* Six tracks have tr_count > average */ + q = playlist_get_queue(PL_MOST_PLAYED); playlist_select(PL_MOST_PLAYED); test_equal(playlist_add(PL_MOST_PLAYED, track_get(0)), (bool)false); test_equal(queue_size(q), 6); diff --git a/tests/core/playlists/system.c b/tests/core/playlists/system.c index d19781d3..19450d68 100644 --- a/tests/core/playlists/system.c +++ b/tests/core/playlists/system.c @@ -32,6 +32,14 @@ while (idle_run_task()) {}; \ __test_playlist_state(queue, ex_size, ex_track0, ex_track1) +#define __test_playlist_hide_track(name, queue, ex_size, ex_track0, ex_track1) \ + test_equal(pl_system.pl_add_track("Hidden", track_get(0)), (bool)true); \ + __test_playlist_state(queue, ex_size, ex_track0, ex_track1); \ + test_equal(pl_system.pl_add_track(name, track_get(0)), (bool)false) + +#define __test_playlist_unhide_track(name, queue, ex_size, ex_track0, ex_track1) \ + test_equal(pl_system.pl_remove_track("Hidden", track_get(0)), (bool)true); \ + __test_playlist_state(queue, ex_size, ex_track0, ex_track1) #define __test_playlist_reinit(queue, ex_size, ex_track0, ex_track1) \ pl_system_deinit(); \ @@ -73,6 +81,7 @@ static void test_favorites() struct queue *queue = pl_system.pl_get_queue("Favorites"); test_not_equal((void *)queue, NULL); + test_equal(queue_has_flag(queue, Q_ADD_FRONT), (bool)false); __test_playlist_add("Favorites", queue); __test_playlist_reinit(queue, 2, true, true); @@ -86,11 +95,43 @@ static void test_hidden() test_not_equal((void *)queue, NULL); test_equal((void *)pl_system.pl_get_queue("Banned"), (void *)queue); + test_equal(queue_has_flag(queue, Q_ADD_FRONT), (bool)false); __test_playlist_add("Hidden", queue); __test_playlist_reinit(queue, 2, true, true); __test_playlist_update("Hidden", queue, 2, true, true); __test_playlist_remove("Hidden", queue); +} + +static void test_unplayed() +{ + struct queue *queue = pl_system.pl_get_queue("Unplayed"); + + pl_system_deinit(); + pl_system_init(NULL); + + test_not_equal((void *)queue, NULL); + test_equal(queue_has_flag(queue, Q_ADD_FRONT), (bool)true); + + __test_playlist_reinit(queue, 2, true, true); + __test_playlist_remove("Unplayed", queue); + + track_get(1)->tr_count = 1; + test_equal(pl_system.pl_add_track("Unplayed", track_get(0)), (bool)true); + test_equal(pl_system.pl_add_track("Unplayed", track_get(0)), (bool)false); + test_equal(queue_size(queue), 1); + + track_get(0)->tr_count = 1; + track_get(1)->tr_count = 0; + __test_playlist_update("Unplayed", queue, 1, false, true); + + track_get(0)->tr_count = 0; + __test_playlist_update("Unplayed", queue, 2, true, true); + + __test_playlist_hide_track("Unplayed", queue, 1, false, true); + __test_playlist_reinit(queue, 1, false, true); + __test_playlist_update("Unplayed", queue, 1, false, true); + __test_playlist_unhide_track("Unplayed", queue, 2, true, true); pl_system_deinit(); } @@ -99,4 +140,5 @@ DECLARE_UNIT_TESTS( UNIT_TEST("Invalid Playlist", test_invalid), UNIT_TEST("Favorites Playlist", test_favorites), UNIT_TEST("Hidden Playlist", test_hidden), + UNIT_TEST("Unplayed Tracks Playlist", test_unplayed), );