core/playlists/system: Move the unplayed tracks playlist into system.c

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2016-04-26 08:20:27 -04:00 committed by Anna Schumaker
parent 1527ee0e6d
commit 5ab2e63734
6 changed files with 152 additions and 29 deletions

View File

@ -5,6 +5,7 @@
#include <core/collection.h> #include <core/collection.h>
#include <core/history.h> #include <core/history.h>
#include <core/idle.h> #include <core/idle.h>
#include <core/playlist.h>
#include <core/tempq.h> #include <core/tempq.h>
static struct file audio_file = FILE_INIT("cur_track", 0, 0); static struct file audio_file = FILE_INIT("cur_track", 0, 0);
@ -214,8 +215,10 @@ struct track *audio_prev()
struct track *audio_eos() struct track *audio_eos()
{ {
/* Mark current track as played */ /* Mark current track as played */
if (audio_track) if (audio_track) {
track_played(audio_track); track_played(audio_track);
playlist_update(PL_UNPLAYED);
}
/* Check pause count and pick the next track */ /* Check pause count and pick the next track */
if (audio_pause_count >= 0) { if (audio_pause_count >= 0) {

View File

@ -54,8 +54,10 @@ static void __scan_path(struct scan_data *scan, const gchar *name)
__scan_dir_later(scan->sd_lib, path); __scan_dir_later(scan->sd_lib, path);
else { else {
track = track_add(scan->sd_lib, path); track = track_add(scan->sd_lib, path);
if (track) if (track) {
queue_add(&c_queue, track); queue_add(&c_queue, track);
playlist_add(PL_UNPLAYED, track);
}
} }
g_free(path); g_free(path);
@ -108,6 +110,7 @@ static bool __validate_library(void *data)
if (collection_check_library(library) < 0) if (collection_check_library(library) < 0)
return true; return true;
queue_remove_all(&c_queue, track); queue_remove_all(&c_queue, track);
playlist_remove(PL_UNPLAYED, track);
track_remove(track); track_remove(track);
} }
} }

View File

@ -7,8 +7,18 @@
static struct file sys_file = FILE_INIT("playlist.db", 0, 0); static struct file sys_file = FILE_INIT("playlist.db", 0, 0);
static struct queue sys_playlists[SYS_PL_NUM_PLAYLISTS]; 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() static void __sys_pl_save()
{ {
@ -26,7 +36,7 @@ static void __sys_pl_save()
static bool __sys_pl_load() static bool __sys_pl_load()
{ {
struct queue *queue; enum sys_playlist_t plist;
unsigned int i, n; unsigned int i, n;
gchar *name; gchar *name;
@ -37,8 +47,8 @@ static bool __sys_pl_load()
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
file_readf(&sys_file, "%*u %m[^\n]\n", &name); file_readf(&sys_file, "%*u %m[^\n]\n", &name);
queue = pl_system_get_queue(name); plist = __sys_pl_convert(name);
queue_load_tracks(queue, &sys_file); queue_load_tracks(&sys_playlists[plist], &sys_file);
g_free(name); g_free(name);
} }
@ -46,42 +56,99 @@ static bool __sys_pl_load()
return true; 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) static struct queue *pl_system_get_queue(const gchar *name)
{ {
if (string_match(name, "Favorites")) enum sys_playlist_t plist = __sys_pl_convert(name);
return &sys_playlists[SYS_PL_FAVORITES]; if (plist == SYS_PL_NUM_PLAYLISTS)
else if (string_match(name, "Hidden") || string_match(name, "Banned")) return NULL;
return &sys_playlists[SYS_PL_HIDDEN]; return &sys_playlists[plist];
return NULL;
} }
static bool pl_system_add_track(const gchar *name, struct track *track) static bool pl_system_add_track(const gchar *name, struct track *track)
{ {
struct queue *queue = pl_system_get_queue(name); enum sys_playlist_t plist = __sys_pl_convert(name);
if (!queue) if (plist == SYS_PL_NUM_PLAYLISTS)
return false; return false;
if (queue_has(queue, track)) return __sys_pl_add(plist, track);
return false;
queue_add(queue, track);
__sys_pl_save();
return true;
} }
static bool pl_system_remove_track(const gchar *name, struct track *track) static bool pl_system_remove_track(const gchar *name, struct track *track)
{ {
struct queue *queue = pl_system_get_queue(name); enum sys_playlist_t plist = __sys_pl_convert(name);
if (!queue) if (plist == SYS_PL_NUM_PLAYLISTS)
return false; return false;
if (!queue_remove_all(queue, track)) return __sys_pl_remove(plist, track);
return false;
__sys_pl_save();
return true;
} }
static void pl_system_update(const gchar *name) 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_ARTIST, true);
queue_sort(&sys_playlists[i], COMPARE_YEAR, false); queue_sort(&sys_playlists[i], COMPARE_YEAR, false);
queue_sort(&sys_playlists[i], COMPARE_TRACK, 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() void pl_system_deinit()

View File

@ -9,6 +9,7 @@
enum sys_playlist_t { enum sys_playlist_t {
SYS_PL_FAVORITES, /* Songs that the user likes. */ SYS_PL_FAVORITES, /* Songs that the user likes. */
SYS_PL_HIDDEN, /* Songs that the user has hidden. */ 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. */ SYS_PL_NUM_PLAYLISTS, /* Number of system playlists. */
}; };

View File

@ -115,10 +115,10 @@ static void test_remove()
static void test_dynamic() static void test_dynamic()
{ {
struct queue *q = playlist_get_queue(PL_UNPLAYED);
struct db_entry *dbe, *next; struct db_entry *dbe, *next;
unsigned int i, average = 0; unsigned int i, average = 0;
struct track *track; struct track *track;
struct queue *q;
/* Set play count to (track_number - 1) (average = 6) */ /* Set play count to (track_number - 1) (average = 6) */
db_for_each(dbe, next, track_db_get()) { db_for_each(dbe, next, track_db_get()) {
@ -127,16 +127,19 @@ static void test_dynamic()
average += TRACK(dbe)->tr_count; average += TRACK(dbe)->tr_count;
} }
average /= track_db_get()->db_size; average /= track_db_get()->db_size;
playlist_update(PL_UNPLAYED);
/* Only one unplayed track (tr_track == 1) */ /* 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_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_size(q), 1);
test_equal(queue_at(q, 0)->tr_track, 1); test_equal(queue_at(q, 0)->tr_track, 1);
test_equal(queue_at(q, 0)->tr_count, 0); test_equal(queue_at(q, 0)->tr_count, 0);
/* Six tracks have tr_count <= average && tr_count > 0 */ /* Six tracks have tr_count <= average && tr_count > 0 */
q = playlist_get_queue(PL_LEAST_PLAYED);
playlist_select(PL_LEAST_PLAYED); playlist_select(PL_LEAST_PLAYED);
test_equal(playlist_add(PL_LEAST_PLAYED, track_get(0)), (bool)false); test_equal(playlist_add(PL_LEAST_PLAYED, track_get(0)), (bool)false);
test_equal(queue_size(q), 6); test_equal(queue_size(q), 6);
@ -149,6 +152,7 @@ static void test_dynamic()
} test_loop_passed(); } test_loop_passed();
/* Six tracks have tr_count > average */ /* Six tracks have tr_count > average */
q = playlist_get_queue(PL_MOST_PLAYED);
playlist_select(PL_MOST_PLAYED); playlist_select(PL_MOST_PLAYED);
test_equal(playlist_add(PL_MOST_PLAYED, track_get(0)), (bool)false); test_equal(playlist_add(PL_MOST_PLAYED, track_get(0)), (bool)false);
test_equal(queue_size(q), 6); test_equal(queue_size(q), 6);

View File

@ -32,6 +32,14 @@
while (idle_run_task()) {}; \ while (idle_run_task()) {}; \
__test_playlist_state(queue, ex_size, ex_track0, ex_track1) __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) \ #define __test_playlist_reinit(queue, ex_size, ex_track0, ex_track1) \
pl_system_deinit(); \ pl_system_deinit(); \
@ -73,6 +81,7 @@ static void test_favorites()
struct queue *queue = pl_system.pl_get_queue("Favorites"); struct queue *queue = pl_system.pl_get_queue("Favorites");
test_not_equal((void *)queue, NULL); test_not_equal((void *)queue, NULL);
test_equal(queue_has_flag(queue, Q_ADD_FRONT), (bool)false);
__test_playlist_add("Favorites", queue); __test_playlist_add("Favorites", queue);
__test_playlist_reinit(queue, 2, true, true); __test_playlist_reinit(queue, 2, true, true);
@ -86,11 +95,43 @@ static void test_hidden()
test_not_equal((void *)queue, NULL); test_not_equal((void *)queue, NULL);
test_equal((void *)pl_system.pl_get_queue("Banned"), (void *)queue); 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_add("Hidden", queue);
__test_playlist_reinit(queue, 2, true, true); __test_playlist_reinit(queue, 2, true, true);
__test_playlist_update("Hidden", queue, 2, true, true); __test_playlist_update("Hidden", queue, 2, true, true);
__test_playlist_remove("Hidden", queue); __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(); pl_system_deinit();
} }
@ -99,4 +140,5 @@ DECLARE_UNIT_TESTS(
UNIT_TEST("Invalid Playlist", test_invalid), UNIT_TEST("Invalid Playlist", test_invalid),
UNIT_TEST("Favorites Playlist", test_favorites), UNIT_TEST("Favorites Playlist", test_favorites),
UNIT_TEST("Hidden Playlist", test_hidden), UNIT_TEST("Hidden Playlist", test_hidden),
UNIT_TEST("Unplayed Tracks Playlist", test_unplayed),
); );