core/playlist: Add a playlist_played() function

This is used to notify when tracks have been played so dynamic playlists
can be updated, and so the model can display the correct playcount.

The old system playlist tests are mostly unnecessary at this point, so I
remove them as part of this patch.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2016-09-13 10:59:20 -04:00
parent 7655b0cae8
commit b17585237a
12 changed files with 97 additions and 214 deletions

View File

@ -242,9 +242,7 @@ struct track *audio_eos()
/* Mark current track as played */
if (audio_track) {
track_played(audio_track);
playlist_update(PL_SYSTEM, "Unplayed");
playlist_update(PL_SYSTEM, "Most Played");
playlist_update(PL_SYSTEM, "Least Played");
playlist_played(audio_track);
}
/* Check pause count and pick the next track */

View File

@ -61,6 +61,13 @@ void playlist_save()
playlist_types[i]->pl_save();
}
void playlist_played(struct track *track)
{
unsigned int i;
for (i = 0; i < PL_MAX_TYPE; i++)
playlist_types[i]->pl_played(track);
}
struct playlist *playlist_new(enum playlist_type_t type, const gchar *name)
{
if (type < PL_MAX_TYPE && playlist_types[type]->pl_new)

View File

@ -114,6 +114,14 @@ static struct playlist *pl_artist_get(unsigned int id)
return artist ? artist->ar_playlist : NULL;
}
static void pl_artist_played(struct track *track)
{
struct artist *artist = track->tr_album->al_artist;
struct playlist *playlist = (struct playlist *)artist->ar_playlist;
if (playlist)
queue_updated(&playlist->pl_queue, track);
}
static void pl_artist_update(const gchar *name)
{
}
@ -123,6 +131,7 @@ struct playlist_type pl_artist = {
.pl_save = pl_artist_save,
.pl_lookup = pl_artist_lookup,
.pl_get = pl_artist_get,
.pl_played = pl_artist_played,
.pl_update = pl_artist_update,
};

View File

@ -245,6 +245,14 @@ static struct playlist *pl_library_new(const gchar *name)
return library->li_playlist;
}
static void pl_library_played(struct track *track)
{
struct library *library = track->tr_library;
struct playlist *playlist = (struct playlist *)library->li_playlist;
if (playlist)
queue_updated(&playlist->pl_queue, track);
}
static void pl_library_update(const gchar *name)
{
struct playlist *playlist = __lib_pl_lookup(name);
@ -258,6 +266,7 @@ struct playlist_type pl_library = {
.pl_lookup = pl_library_lookup,
.pl_get = pl_library_get,
.pl_new = pl_library_new,
.pl_played = pl_library_played,
.pl_update = pl_library_update,
};

View File

@ -489,6 +489,17 @@ static struct playlist *pl_system_get(unsigned int id)
return (id < SYS_PL_NUM_PLAYLISTS) ? &sys_playlists[id]->spl_playlist : NULL;
}
static void pl_system_played(struct track *track)
{
unsigned int i;
for (i = 0; i < SYS_PL_NUM_PLAYLISTS; i++)
queue_updated(&pl_system_get(i)->pl_queue, track);
pl_system_update("Unplayed");
pl_system_update("Most Played");
pl_system_update("Least Played");
}
static void pl_system_update(const gchar *name)
{
struct sys_playlist *sys_pl = __sys_pl_lookup(name);
@ -501,6 +512,7 @@ struct playlist_type pl_system = {
.pl_save = pl_system_save,
.pl_lookup = pl_system_lookup,
.pl_get = pl_system_get,
.pl_played = pl_system_played,
.pl_update = pl_system_update,
};

View File

@ -120,6 +120,17 @@ static struct playlist *pl_user_new(const gchar *name)
return dbe ? &USER_PLAYLIST(dbe)->pl_playlist : NULL;
}
static void pl_user_played(struct track *track)
{
struct db_entry *dbe, *next;
struct playlist *playlist;
db_for_each(dbe, next, &user_db) {
playlist = &USER_PLAYLIST(dbe)->pl_playlist;
queue_updated(&playlist->pl_queue, track);
}
}
static void pl_user_update(const gchar *name)
{
}
@ -130,6 +141,7 @@ struct playlist_type pl_user = {
.pl_lookup = pl_user_lookup,
.pl_get = pl_user_get,
.pl_new = pl_user_new,
.pl_played = pl_user_played,
.pl_update = pl_user_update,
};

View File

@ -24,6 +24,9 @@ void playlist_deinit();
/* Called to force-save all playlists. */
void playlist_save();
/* Called to notify all playlists that a track has been played. */
void playlist_played(struct track *);
/* Called to create a new playlist. */
struct playlist *playlist_new(enum playlist_type_t, const gchar *);

View File

@ -74,6 +74,9 @@ struct playlist_type {
/* Called to create a new playlist. */
struct playlist *(*pl_new)(const gchar *);
/* Called to notify that a track has been played. */
void (*pl_played)(struct track *);
/* Called to update a playlist. */
void (*pl_update)(const gchar *);
};

View File

@ -43,6 +43,7 @@ void test_artist()
g_assert_cmpuint(settings_get("core.playlist.cur.id"), ==, 0);
g_assert(playlist_current() == playlist);
g_assert_false(playlist_select(playlist));
playlist_played(track_get(0));
g_assert_cmpuint(playlist_next()->tr_track, ==, 1);
g_assert_cmpuint(playlist_size(playlist), ==, 2);

View File

@ -65,6 +65,7 @@ void test_library()
g_assert_false(playlist_remove(playlist, track_get(0)));
g_assert_false(playlist_remove(playlist, track_get(1)));
g_assert_cmpuint(playlist_size(playlist), ==, 48);
playlist_played(track_get(1));
g_assert_false(playlist_get_random(playlist));
playlist_set_random(playlist, true);

View File

@ -8,63 +8,6 @@
#include <tests/test.h>
#define __test_playlist_has(name, track, expected) \
if (expected) \
g_assert_true(playlist_has(playlist_lookup(PL_SYSTEM, name), track)); \
else \
g_assert_false(playlist_has(playlist_lookup(PL_SYSTEM, name), track))
#define __test_playlist_state(name, ex_size, ex_track0, ex_track1) \
g_assert_cmpuint(playlist_size(playlist_lookup(PL_SYSTEM, name)), ==, ex_size); \
__test_playlist_has(name, track_get(0), ex_track0); \
__test_playlist_has(name, track_get(1), ex_track1)
#define __test_playlist_add(name) \
__test_playlist_state(name, 0, false, false); \
g_assert_true( playlist_add(playlist_lookup(PL_SYSTEM, name), track_get(0))); \
g_assert_false(playlist_add(playlist_lookup(PL_SYSTEM, name), track_get(0))); \
g_assert_true( playlist_add(playlist_lookup(PL_SYSTEM, name), track_get(1))); \
g_assert_false(playlist_add(playlist_lookup(PL_SYSTEM, name), track_get(1))); \
__test_playlist_state(name, 2, true, true)
#define __test_playlist_remove(name) \
g_assert_true( playlist_remove(playlist_lookup(PL_SYSTEM, name), track_get(0))); \
g_assert_false(playlist_remove(playlist_lookup(PL_SYSTEM, name), track_get(0))); \
g_assert_true( playlist_remove(playlist_lookup(PL_SYSTEM, name), track_get(1))); \
g_assert_false(playlist_remove(playlist_lookup(PL_SYSTEM, name), track_get(1))); \
__test_playlist_state(name, 0, false, false)
#define __test_playlist_update(name, ex_size, ex_track0, ex_track1) \
playlist_update(PL_SYSTEM, name); \
while (idle_run_task()) {}; \
__test_playlist_state(name, ex_size, ex_track0, ex_track1)
#define __test_playlist_hide_track(name, ex_size, ex_track0, ex_track1) \
g_assert_true(playlist_add(playlist_lookup(PL_SYSTEM, "Hidden"), track_get(0))); \
__test_playlist_state(name, ex_size, ex_track0, ex_track1); \
g_assert_false(playlist_add(playlist_lookup(PL_SYSTEM, name), track_get(0)))
#define __test_playlist_unhide_track(name, ex_size, ex_track0, ex_track1) \
g_assert_true(playlist_remove(playlist_lookup(PL_SYSTEM, "Hidden"), track_get(0))); \
__test_playlist_state(name, ex_size, ex_track0, ex_track1)
#define __test_playlist_clear_hidden(name, ex_size, ex_track0, ex_track1) \
g_assert_false(playlist_delete(playlist_lookup(PL_SYSTEM, "Hidden"))); \
__test_playlist_state("Hidden", 0, false, false); \
__test_playlist_state(name, ex_size, ex_track0, ex_track1);
#define __test_playlist_reinit(name, ex_size, ex_track0, ex_track1) \
do { \
struct playlist *playlist; \
pl_system_deinit(); \
pl_system_init(NULL); \
playlist = playlist_lookup(PL_SYSTEM, name); \
g_assert_nonnull(playlist); \
__test_playlist_state(name, 0, false, false); \
while (idle_run_task()) {}; \
__test_playlist_state(name, ex_size, ex_track0, ex_track1); \
} while (0)
static inline struct playlist *__test_pl_favorites(void)
{ return playlist_lookup(PL_SYSTEM, "Favorites"); }
static inline struct playlist *__test_pl_hidden(void)
@ -110,160 +53,22 @@ static void test_init()
/* Add tracks to the collection. */
track_add(library, "tests/Music/Hyrule Symphony/01 - Title Theme.ogg");
track_add(library, "tests/Music/Hyrule Symphony/02 - Kokiri Forest.ogg");
track_add(library, "tests/Music/Hyrule Symphony/03 - Hyrule Field.ogg");
pl_system_new_track(track_get(0));
pl_system_new_track(track_get(1));
pl_system_new_track(track_get(2));
g_assert_null(playlist_new(PL_SYSTEM, "New Playlist"));
for (i = 0; i < SYS_PL_NUM_PLAYLISTS; i++) {
playlist = playlist_get(PL_SYSTEM, i);
if (i == SYS_PL_COLLECTION || i == SYS_PL_UNPLAYED)
g_assert_cmpuint(playlist_size(playlist), ==, 2);
g_assert_cmpuint(playlist_size(playlist), ==, 3);
else
g_assert_cmpuint(playlist_size(playlist), ==, 0);
}
}
static void test_invalid()
{
playlist_update(PL_SYSTEM, NULL);
}
static void test_favorites()
{
__test_playlist_add("Favorites");
__test_playlist_reinit("Favorites", 2, true, true);
__test_playlist_update("Favorites", 2, true, true);
__test_playlist_remove("Favorites");
}
static void test_hidden()
{
__test_playlist_add("Hidden");
__test_playlist_reinit("Hidden", 2, true, true);
__test_playlist_update("Hidden", 2, true, true);
__test_playlist_remove("Hidden");
}
static void test_queued()
{
__test_playlist_add("Queued Tracks");
__test_playlist_reinit("Queued Tracks", 2, true, true);
__test_playlist_remove("Queued Tracks");
__test_playlist_update("Queued Tracks", 0, false, false);
}
static void test_collection()
{
pl_system_deinit();
pl_system_init(NULL);
__test_playlist_update("Collection", 2, true, true);
__test_playlist_hide_track("Collection", 1, false, true);
__test_playlist_reinit("Collection", 1, false, true);
__test_playlist_update("Collection", 1, false, true);
__test_playlist_unhide_track("Collection", 2, true, true);
__test_playlist_hide_track("Collection", 1, false, true);
__test_playlist_clear_hidden("Collection", 2, true, true);
}
static void test_history()
{
__test_playlist_state("History", 0, false, false);
g_assert_true(playlist_add(__test_pl_history(), track_get(0)));
g_assert_true(playlist_add(__test_pl_history(), track_get(0)));
g_assert_true(playlist_add(__test_pl_history(), track_get(1)));
g_assert_true(playlist_add(__test_pl_history(), track_get(1)));
__test_playlist_state("History", 4, true, true);
g_assert(playlist_prev() == track_get(1));
g_assert(playlist_prev() == track_get(0));
g_assert_cmpuint(playlist_size(__test_pl_history()), ==, 4);
g_assert_true(playlist_add(__test_pl_history(), track_get(1)));
g_assert_cmpuint(playlist_size(__test_pl_history()), ==, 5);
g_assert(playlist_prev() == track_get(1));
__test_playlist_update("History", 5, true, true);
}
static void test_unplayed()
{
pl_system_deinit();
pl_system_init(NULL);
__test_playlist_reinit("Unplayed", 2, true, true);
track_get(1)->tr_count = 1;
__test_playlist_update("Unplayed", 1, true, false);
track_get(0)->tr_count = 1;
track_get(1)->tr_count = 0;
__test_playlist_update("Unplayed", 1, false, true);
track_get(0)->tr_count = 0;
__test_playlist_update("Unplayed", 2, true, true);
__test_playlist_hide_track("Unplayed", 1, false, true);
__test_playlist_reinit("Unplayed", 1, false, true);
__test_playlist_update("Unplayed", 1, false, true);
__test_playlist_unhide_track("Unplayed", 2, true, true);
__test_playlist_hide_track("Unplayed", 1, false, true);
__test_playlist_clear_hidden("Unplayed", 2, true, true);
}
static void test_most_played()
{
/* Set average = (4 / 2) = 2 */
track_played(track_get(0));
track_played(track_get(1));
track_played(track_get(1));
track_played(track_get(1));
pl_system_deinit();
pl_system_init(NULL);
__test_playlist_reinit("Most Played", 1, false, true);
track_get(0)->tr_count = 3;
track_get(1)->tr_count = 1;
__test_playlist_update("Most Played", 1, true, false);
__test_playlist_hide_track("Most Played", 0, false, false);
__test_playlist_reinit("Most Played", 0, false, false);
__test_playlist_update("Most Played", 0, false, false);
__test_playlist_unhide_track("Most Played", 1, true, false);
__test_playlist_hide_track("Most Played", 0, false, false);
__test_playlist_clear_hidden("Most Played", 1, true, false);
}
static void test_least_played()
{
/* Reset playcounts so track 1 is "least played" */
track_get(0)->tr_count = 3;
track_get(1)->tr_count = 1;
pl_system_deinit();
pl_system_init(NULL);
__test_playlist_reinit("Least Played", 1, false, true);
track_get(0)->tr_count = 1;
track_get(1)->tr_count = 3;
__test_playlist_update("Least Played", 1, true, false);
__test_playlist_hide_track("Least Played", 0, false, false);
__test_playlist_reinit("Least Played", 0, false, false);
__test_playlist_update("Least Played", 0, false, false);
__test_playlist_unhide_track("Least Played", 1, true, false);
__test_playlist_hide_track("Least Played", 0, false, false);
__test_playlist_clear_hidden("Least Played", 1, true, false);
track_get(0)->tr_count = 3;
track_get(1)->tr_count = 1;
__test_playlist_update("Least Played", 1, false, true);
__test_playlist_update("Most Played", 1, true, false);
}
static void test_random()
{
struct playlist *playlist;
@ -306,15 +111,45 @@ static void test_sort()
}
}
static void test_played()
{
g_assert_cmpuint(playlist_size(__test_pl_unplayed()), ==, 3);
g_assert_cmpuint(playlist_size(__test_pl_most_played()), ==, 0);
g_assert_cmpuint(playlist_size(__test_pl_least_played()), ==, 0);
track_played(track_get(0));
playlist_played(track_get(0));
while (idle_run_task()) {}
g_assert_cmpuint(playlist_size(__test_pl_unplayed()), ==, 2);
g_assert_cmpuint(playlist_size(__test_pl_most_played()), ==, 0);
g_assert_cmpuint(playlist_size(__test_pl_least_played()), ==, 1);
g_assert_true(playlist_has(__test_pl_least_played(), track_get(0)));
g_assert_true(playlist_has(__test_pl_unplayed(), track_get(1)));
g_assert_true(playlist_has(__test_pl_unplayed(), track_get(2)));
track_played(track_get(0));
track_played(track_get(0));
track_played(track_get(1));
playlist_played(track_get(0));
playlist_played(track_get(1));
while (idle_run_task()) {}
g_assert_cmpuint(playlist_size(__test_pl_unplayed()), ==, 1);
g_assert_cmpuint(playlist_size(__test_pl_most_played()), ==, 1);
g_assert_cmpuint(playlist_size(__test_pl_least_played()), ==, 1);
g_assert_true(playlist_has(__test_pl_most_played(), track_get(0)));
g_assert_true(playlist_has(__test_pl_least_played(), track_get(1)));
g_assert_true(playlist_has(__test_pl_unplayed(), track_get(2)));
}
static void test_add()
{
struct library *library = library_find("tests/Music");
struct playlist *playlist;
unsigned int i;
track_add(library, "tests/Music/Hyrule Symphony/03 - Hyrule Field.ogg");
pl_system_new_track(track_get(2));
g_assert_true( playlist_add(__test_pl_favorites(), track_get(0)));
g_assert_false(playlist_add(__test_pl_favorites(), track_get(0)));
g_assert_true( playlist_add(__test_pl_queued(), track_get(0)));
@ -533,17 +368,9 @@ int main(int argc, char **argv)
g_test_init(&argc, &argv, NULL);
g_test_add_func("/Core/Playlists/System/Init", test_init);
g_test_add_func("/Core/Playlists/System/Invalid", test_invalid);
g_test_add_func("/Core/Playlists/System/Favorites", test_favorites);
g_test_add_func("/Core/Playlists/System/Hidden", test_hidden);
g_test_add_func("/Core/Playlists/System/Queued", test_queued);
g_test_add_func("/Core/Playlists/System/Collection", test_collection);
g_test_add_func("/Core/Playlists/System/History", test_history);
g_test_add_func("/Core/Playlists/System/Unplayed Tracks", test_unplayed);
g_test_add_func("/Core/Playlists/System/Most Played Tracks", test_most_played);
g_test_add_func("/Core/Playlists/System/Least Played Tracks", test_least_played);
g_test_add_func("/Core/Playlists/System/Random", test_random);
g_test_add_func("/Core/Playlists/System/Sort", test_sort);
g_test_add_func("/Core/Playlists/System/Played", test_played);
g_test_add_func("/Core/Playlists/System/Add Tracks", test_add);
g_test_add_func("/Core/Playlists/System/Remove Tracks", test_remove);
g_test_add_func("/Core/Playlists/System/Delete", test_delete);

View File

@ -47,6 +47,7 @@ void test_user()
g_assert(playlist_next() == track_get(0));
g_assert_true(playlist_has(playlist, track_get(0)));
g_assert_cmpuint(playlist_size(playlist), ==, 1);
playlist_played(track_get(0));
playlist_update(PL_USER, "Test Playlist");
pl_user_deinit();