core/playlists/system: Move system playlists into a new file
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
parent
e3d4143565
commit
a465577c86
|
@ -4,6 +4,7 @@ Import("env")
|
|||
res = Glob("*.c")
|
||||
res += SConscript("tags/Sconscript")
|
||||
res += SConscript("containers/Sconscript")
|
||||
res += SConscript("playlists/Sconscript")
|
||||
|
||||
env.UsePackage("gstreamer-1.0")
|
||||
env.UsePackage("libmusicbrainz5");
|
||||
|
|
131
core/playlist.c
131
core/playlist.c
|
@ -1,35 +1,14 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <core/collection.h>
|
||||
#include <core/idle.h>
|
||||
#include <core/string.h>
|
||||
#include <core/playlist.h>
|
||||
#include <core/playlists/system.h>
|
||||
|
||||
static GHashTable *playlist_db = NULL;
|
||||
static struct file playlist_f = FILE_INIT("playlist.db", 0, 0);
|
||||
static struct queue playlist_q;
|
||||
static enum playlist_t playlist_cur;
|
||||
static const gchar *playlist_names[2] = { "Favorites", "Banned" };
|
||||
static struct queue_ops *playlist_ops = NULL;
|
||||
|
||||
|
||||
static inline struct queue *__playlist_lookup(const gchar *name)
|
||||
{
|
||||
return g_hash_table_lookup(playlist_db, name);
|
||||
}
|
||||
|
||||
static inline struct queue *__playlist_alloc(const gchar *name)
|
||||
{
|
||||
struct queue *queue = __playlist_lookup(name);
|
||||
if (!queue) {
|
||||
queue = g_malloc(sizeof(struct queue));
|
||||
queue_init(queue, Q_ENABLED | Q_REPEAT, playlist_ops);
|
||||
g_hash_table_insert(playlist_db, (gpointer)name, queue);
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
static inline bool __playlist_is_static(enum playlist_t plist)
|
||||
{
|
||||
return (plist == PL_FAVORITED) || (plist == PL_HIDDEN);
|
||||
|
@ -59,109 +38,6 @@ static void __playlist_fill_dynamic(enum playlist_t plist)
|
|||
}
|
||||
}
|
||||
|
||||
static void __pl_system_load_queue()
|
||||
{
|
||||
struct queue *queue;
|
||||
unsigned int valid;
|
||||
gchar *name;
|
||||
|
||||
file_readf(&playlist_f, "%u ", &valid);
|
||||
if (!valid)
|
||||
return;
|
||||
|
||||
name = file_readl(&playlist_f);
|
||||
queue = __playlist_alloc(name);
|
||||
queue_load_tracks(queue, &playlist_f);
|
||||
}
|
||||
|
||||
static void __pl_system_save_queue(gpointer key, gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
struct queue *queue = (struct queue *)value;
|
||||
|
||||
file_writef(&playlist_f, "1 %s\n", (gchar *)key);
|
||||
queue_save_tracks(queue, &playlist_f);
|
||||
file_writef(&playlist_f, "\n");
|
||||
}
|
||||
|
||||
static void __pl_system_save()
|
||||
{
|
||||
if (!file_open(&playlist_f, OPEN_WRITE))
|
||||
return;
|
||||
|
||||
file_writef(&playlist_f, "%u\n", g_hash_table_size(playlist_db));
|
||||
g_hash_table_foreach(playlist_db, __pl_system_save_queue, NULL);
|
||||
file_close(&playlist_f);
|
||||
}
|
||||
|
||||
static bool __pl_system_init_idle()
|
||||
{
|
||||
unsigned int i, n;
|
||||
|
||||
if (!file_open(&playlist_f, OPEN_READ))
|
||||
return true;
|
||||
|
||||
file_readf(&playlist_f, "%u\n", &n);
|
||||
for (i = 0; i < n; i++)
|
||||
__pl_system_load_queue();
|
||||
|
||||
file_close(&playlist_f);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void __pl_system_init()
|
||||
{
|
||||
playlist_db = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
idle_schedule(IDLE_SYNC, __pl_system_init_idle, NULL);
|
||||
}
|
||||
|
||||
static int __pl_system_deinit_queue(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
struct queue *queue = (struct queue *)value;
|
||||
queue_deinit(queue);
|
||||
g_free(queue);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void __pl_system_deinit()
|
||||
{
|
||||
g_hash_table_foreach_remove(playlist_db, __pl_system_deinit_queue, NULL);
|
||||
g_hash_table_destroy(playlist_db);
|
||||
}
|
||||
|
||||
static bool __pl_system_add(const gchar *name, struct track *track)
|
||||
{
|
||||
struct queue *queue = __playlist_alloc(name);
|
||||
if (queue_has(queue, track))
|
||||
return false;
|
||||
queue_add(queue, track);
|
||||
__pl_system_save();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __pl_system_remove(const gchar *name, struct track *track)
|
||||
{
|
||||
struct queue *queue = __playlist_lookup(name);
|
||||
if (!queue)
|
||||
return false;
|
||||
if (!queue_remove_all(queue, track))
|
||||
return false;
|
||||
__pl_system_save();
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct queue *__pl_system_get_queue(const gchar *name)
|
||||
{
|
||||
return __playlist_lookup(name);
|
||||
}
|
||||
|
||||
|
||||
struct playlist_type pl_system = {
|
||||
.pl_get_queue = __pl_system_get_queue,
|
||||
.pl_add_track = __pl_system_add,
|
||||
.pl_remove_track = __pl_system_remove,
|
||||
};
|
||||
|
||||
|
||||
void playlist_init(struct queue_ops *ops)
|
||||
{
|
||||
|
@ -171,14 +47,13 @@ void playlist_init(struct queue_ops *ops)
|
|||
queue_sort(&playlist_q, COMPARE_TRACK, false);
|
||||
queue_set_flag(&playlist_q, Q_NO_SORT);
|
||||
|
||||
playlist_ops = ops;
|
||||
__pl_system_init();
|
||||
pl_system_init(ops);
|
||||
}
|
||||
|
||||
void playlist_deinit()
|
||||
{
|
||||
__pl_system_deinit();
|
||||
queue_deinit(&playlist_q);
|
||||
pl_system_deinit();
|
||||
}
|
||||
|
||||
bool playlist_add(enum playlist_t plist, struct track *track)
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
res = Glob("*.c")
|
||||
Return("res")
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright 2016 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <core/idle.h>
|
||||
#include <core/playlists/system.h>
|
||||
#include <core/string.h>
|
||||
|
||||
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 void __sys_pl_save()
|
||||
{
|
||||
if (!file_open(&sys_file, OPEN_WRITE))
|
||||
return;
|
||||
|
||||
file_writef(&sys_file, "%u\n 1 %s\n", 2, "Favorites");
|
||||
queue_save_tracks(&sys_playlists[SYS_PL_FAVORITES], &sys_file);
|
||||
file_writef(&sys_file, "\n1 %s\n", "Banned");
|
||||
queue_save_tracks(&sys_playlists[SYS_PL_HIDDEN], &sys_file);
|
||||
file_writef(&sys_file, "\n");
|
||||
|
||||
file_close(&sys_file);
|
||||
}
|
||||
|
||||
static bool __sys_pl_load()
|
||||
{
|
||||
struct queue *queue;
|
||||
unsigned int i, n;
|
||||
gchar *name;
|
||||
|
||||
if (!file_open(&sys_file, OPEN_READ))
|
||||
return true;
|
||||
|
||||
file_readf(&sys_file, "%u\n", &n);
|
||||
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);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
file_close(&sys_file);
|
||||
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;
|
||||
}
|
||||
|
||||
static bool pl_system_add_track(const gchar *name, struct track *track)
|
||||
{
|
||||
struct queue *queue = pl_system_get_queue(name);
|
||||
if (!queue)
|
||||
return false;
|
||||
if (queue_has(queue, track))
|
||||
return false;
|
||||
queue_add(queue, track);
|
||||
__sys_pl_save();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pl_system_remove_track(const gchar *name, struct track *track)
|
||||
{
|
||||
struct queue *queue = pl_system_get_queue(name);
|
||||
if (!queue)
|
||||
return false;
|
||||
if (!queue_remove_all(queue, track))
|
||||
return false;
|
||||
__sys_pl_save();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct playlist_type pl_system = {
|
||||
.pl_get_queue = pl_system_get_queue,
|
||||
.pl_add_track = pl_system_add_track,
|
||||
.pl_remove_track = pl_system_remove_track,
|
||||
};
|
||||
|
||||
|
||||
void pl_system_init(struct queue_ops *ops)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < SYS_PL_NUM_PLAYLISTS; i++) {
|
||||
queue_init(&sys_playlists[i], Q_ENABLED | Q_REPEAT, 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);
|
||||
}
|
||||
|
||||
idle_schedule(IDLE_SYNC, __sys_pl_load, NULL);
|
||||
}
|
||||
|
||||
void pl_system_deinit()
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < SYS_PL_NUM_PLAYLISTS; i++)
|
||||
queue_deinit(&sys_playlists[i]);
|
||||
}
|
|
@ -20,18 +20,6 @@ enum playlist_t {
|
|||
};
|
||||
|
||||
|
||||
struct playlist_type {
|
||||
/* Called to get the queue for the playlist. */
|
||||
struct queue *(*pl_get_queue)(const gchar *);
|
||||
|
||||
/* Called to add a track to the playlist. */
|
||||
bool (*pl_add_track)(const gchar *, struct track *);
|
||||
|
||||
/* Called to remove a track from the playlist. */
|
||||
bool (*pl_remove_track)(const gchar *, struct track *);
|
||||
};
|
||||
|
||||
|
||||
/* Called to initialize the playlist manager. */
|
||||
void playlist_init(struct queue_ops *);
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2016 (c) Anna Schumaker.
|
||||
*/
|
||||
#ifndef OCARINA_CORE_PLAYLISTS_SYSTEM_H
|
||||
#define OCARINA_CORE_PLAYLISTS_SYSTEM_H
|
||||
#include <core/playlists/type.h>
|
||||
|
||||
|
||||
enum sys_playlist_t {
|
||||
SYS_PL_FAVORITES, /* Songs that the user likes. */
|
||||
SYS_PL_HIDDEN, /* Songs that the user has hidden. */
|
||||
SYS_PL_NUM_PLAYLISTS, /* Number of system playlists. */
|
||||
};
|
||||
|
||||
|
||||
/* System playlist type. */
|
||||
extern struct playlist_type pl_system;
|
||||
|
||||
|
||||
/* Called to initialize system playlists. */
|
||||
void pl_system_init(struct queue_ops *);
|
||||
|
||||
/* Called to deinitialize system playlists. */
|
||||
void pl_system_deinit();
|
||||
|
||||
#endif /* OCARINA_CORE_PLAYLISTS_SYSTEM_H */
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2016 (c) Anna Schumaker.
|
||||
*/
|
||||
#ifndef OCARINA_CORE_PLAYLISTS_TYPE_H
|
||||
#define OCARINA_CORE_PLAYLISTS_TYPE_H
|
||||
#include <core/queue.h>
|
||||
#include <core/tags/track.h>
|
||||
#include <glib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
struct playlist_type {
|
||||
/* Called to get the queue for the playlist. */
|
||||
struct queue *(*pl_get_queue)(const gchar *);
|
||||
|
||||
/* Called to add a track to the playlist. */
|
||||
bool (*pl_add_track)(const gchar *, struct track *);
|
||||
|
||||
/* Called to remove a track from the playlist. */
|
||||
bool (*pl_remove_track)(const gchar *, struct track *);
|
||||
};
|
||||
|
||||
|
||||
#endif /* OCARINA_CORE_PLAYLISTS_TYPE_H */
|
|
@ -13,6 +13,7 @@ tags/genre
|
|||
tags/library
|
||||
tags/track
|
||||
queue
|
||||
playlists/system
|
||||
playlist
|
||||
collection
|
||||
history
|
||||
|
|
|
@ -35,6 +35,8 @@ res += [ CoreTest("filter") ]
|
|||
|
||||
res += SConscript("tags/Sconscript")
|
||||
res += [ CoreTest("queue") ]
|
||||
|
||||
res += SConscript("playlists/Sconscript")
|
||||
res += [ CoreTest("playlist") ]
|
||||
res += [ CoreTest("collection") ]
|
||||
res += [ CoreTest("history") ]
|
||||
|
|
|
@ -18,8 +18,8 @@ static void test_init()
|
|||
playlist_init(NULL);
|
||||
while (idle_run_task()) {};
|
||||
|
||||
test_equal((void *)playlist_get_queue(PL_FAVORITED), NULL);
|
||||
test_equal((void *)playlist_get_queue(PL_HIDDEN), NULL);
|
||||
test_not_equal((void *)playlist_get_queue(PL_FAVORITED), NULL);
|
||||
test_not_equal((void *)playlist_get_queue(PL_HIDDEN), NULL);
|
||||
test_not_equal((void *)playlist_get_queue(PL_UNPLAYED), NULL);
|
||||
test_not_equal((void *)playlist_get_queue(PL_MOST_PLAYED), NULL);
|
||||
test_not_equal((void *)playlist_get_queue(PL_LEAST_PLAYED), NULL);
|
||||
|
@ -68,7 +68,6 @@ static void test_add()
|
|||
test_equal(playlist_add(PL_FAVORITED, track), (bool)true);
|
||||
test_equal(playlist_has(PL_FAVORITED, track), (bool)true);
|
||||
q = playlist_get_queue(PL_FAVORITED);
|
||||
test_not_equal((void *)q, NULL);
|
||||
test_equal(queue_size(q), 1);
|
||||
test_equal(playlist_add(PL_FAVORITED, track), (bool)false);
|
||||
test_equal(queue_size(q), 1);
|
||||
|
@ -78,12 +77,10 @@ static void test_add()
|
|||
track = track_get(2);
|
||||
playlist_select(PL_HIDDEN);
|
||||
q = playlist_get_queue(PL_HIDDEN);
|
||||
test_equal((void *)q, NULL);
|
||||
test_equal(playlist_has(PL_HIDDEN, track), (bool)false);
|
||||
test_equal(playlist_add(PL_HIDDEN, track), (bool)true);
|
||||
test_equal(playlist_has(PL_HIDDEN, track), (bool)true);
|
||||
q = playlist_get_queue(PL_HIDDEN);
|
||||
test_not_equal((void *)q, NULL);
|
||||
test_equal(queue_size(q), 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#!/env/bin/python
|
||||
Import("env", "CoreTest", "testing_group")
|
||||
|
||||
res = []
|
||||
|
||||
def PlaylistTest(name):
|
||||
run = CoreTest("playlists/%s" % name)
|
||||
Alias("tests/core/playlists", run)
|
||||
if len(res) > 0 and testing_group([ "tests/core/playlists" ]):
|
||||
Depends(run, res[1])
|
||||
return run
|
||||
|
||||
res += [ PlaylistTest("system") ]
|
||||
|
||||
Return("res")
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright 2016 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <core/filter.h>
|
||||
#include <core/idle.h>
|
||||
#include <core/playlists/system.h>
|
||||
#include <core/tags/tags.h>
|
||||
#include <tests/test.h>
|
||||
|
||||
#define __test_playlist_state(queue, ex_size, ex_track0, ex_track1) \
|
||||
test_equal(queue_size(queue), ex_size); \
|
||||
test_equal(queue_has(queue, track_get(0)), (bool)ex_track0); \
|
||||
test_equal(queue_has(queue, track_get(1)), (bool)ex_track1)
|
||||
|
||||
#define __test_playlist_add(name, queue) \
|
||||
__test_playlist_state(queue, 0, false, false); \
|
||||
test_equal(pl_system.pl_add_track(name, track_get(0)), (bool)true); \
|
||||
test_equal(pl_system.pl_add_track(name, track_get(0)), (bool)false); \
|
||||
test_equal(pl_system.pl_add_track(name, track_get(1)), (bool)true); \
|
||||
test_equal(pl_system.pl_add_track(name, track_get(1)), (bool)false); \
|
||||
__test_playlist_state(queue, 2, true, true)
|
||||
|
||||
#define __test_playlist_remove(name, queue) \
|
||||
test_equal(pl_system.pl_remove_track(name, track_get(0)), (bool)true); \
|
||||
test_equal(pl_system.pl_remove_track(name, track_get(0)), (bool)false); \
|
||||
test_equal(pl_system.pl_remove_track(name, track_get(1)), (bool)true); \
|
||||
test_equal(pl_system.pl_remove_track(name, track_get(1)), (bool)false); \
|
||||
__test_playlist_state(queue, 0, false, false)
|
||||
|
||||
#define __test_playlist_reinit(queue, ex_size, ex_track0, ex_track1) \
|
||||
pl_system_deinit(); \
|
||||
pl_system_init(NULL); \
|
||||
__test_playlist_state(queue, 0, false, false); \
|
||||
while (idle_run_task()) {}; \
|
||||
__test_playlist_state(queue, ex_size, ex_track0, ex_track1)
|
||||
|
||||
|
||||
static void test_init()
|
||||
{
|
||||
struct library *library;
|
||||
|
||||
idle_init();
|
||||
filter_init();
|
||||
tags_init();
|
||||
pl_system_init(NULL);
|
||||
while (idle_run_task()) {};
|
||||
|
||||
/* Add tracks to the collection. */
|
||||
library = library_find("tests/Music");
|
||||
track_add(library, "tests/Music/Hyrule Symphony/01 - Title Theme.ogg");
|
||||
track_add(library, "tests/Music/Hyrule Symphony/02 - Kokiri Forest.ogg");
|
||||
}
|
||||
|
||||
static void test_invalid()
|
||||
{
|
||||
test_init();
|
||||
|
||||
test_equal((void *)pl_system.pl_get_queue(NULL), NULL);
|
||||
test_equal((void *)pl_system.pl_get_queue("Invalid"), NULL);
|
||||
|
||||
test_equal(pl_system.pl_add_track(NULL, track_get(0)), (bool)false);
|
||||
test_equal(pl_system.pl_remove_track(NULL, track_get(0)), (bool)false);
|
||||
}
|
||||
|
||||
static void test_favorites()
|
||||
{
|
||||
struct queue *queue = pl_system.pl_get_queue("Favorites");
|
||||
|
||||
test_not_equal((void *)queue, NULL);
|
||||
|
||||
__test_playlist_add("Favorites", queue);
|
||||
__test_playlist_reinit(queue, 2, true, true);
|
||||
__test_playlist_remove("Favorites", queue);
|
||||
}
|
||||
|
||||
static void test_hidden()
|
||||
{
|
||||
struct queue *queue = pl_system.pl_get_queue("Hidden");
|
||||
|
||||
test_not_equal((void *)queue, NULL);
|
||||
test_equal((void *)pl_system.pl_get_queue("Banned"), (void *)queue);
|
||||
|
||||
__test_playlist_add("Hidden", queue);
|
||||
__test_playlist_reinit(queue, 2, true, true);
|
||||
__test_playlist_remove("Hidden", queue);
|
||||
|
||||
pl_system_deinit();
|
||||
}
|
||||
|
||||
DECLARE_UNIT_TESTS(
|
||||
UNIT_TEST("Invalid Playlist", test_invalid),
|
||||
UNIT_TEST("Favorites Playlist", test_favorites),
|
||||
UNIT_TEST("Hidden Playlist", test_hidden),
|
||||
);
|
Loading…
Reference in New Issue