core/playlist: Convert playlist_db to a GHashTable
I want to manage this container on my own, rather than relying on the generic index code. This will eventually make it easier to store a playlist as a queue, instead of a set. Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
parent
c845530812
commit
90fc9bff0a
115
core/playlist.c
115
core/playlist.c
|
@ -2,18 +2,31 @@
|
||||||
* Copyright 2013 (c) Anna Schumaker.
|
* Copyright 2013 (c) Anna Schumaker.
|
||||||
*/
|
*/
|
||||||
#include <core/collection.h>
|
#include <core/collection.h>
|
||||||
|
#include <core/idle.h>
|
||||||
#include <core/string.h>
|
#include <core/string.h>
|
||||||
#include <core/playlist.h>
|
#include <core/playlist.h>
|
||||||
|
|
||||||
static struct database playlist_db;
|
static GHashTable *playlist_db;
|
||||||
|
static struct file playlist_f = FILE_INIT("playlist.db", 0, 0);
|
||||||
static struct queue playlist_q;
|
static struct queue playlist_q;
|
||||||
static enum playlist_t playlist_cur;
|
static enum playlist_t playlist_cur;
|
||||||
static const gchar *playlist_names[2] = { "Favorites", "Banned" };
|
static const gchar *playlist_names[2] = { "Favorites", "Banned" };
|
||||||
|
|
||||||
|
|
||||||
static inline struct index_entry *__playlist_lookup(enum playlist_t plist)
|
static inline struct set *__playlist_lookup(const gchar *name)
|
||||||
{
|
{
|
||||||
return INDEX_ENTRY(db_get(&playlist_db, playlist_names[plist]));
|
return g_hash_table_lookup(playlist_db, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct set *__playlist_alloc(const gchar *name)
|
||||||
|
{
|
||||||
|
struct set *set = __playlist_lookup(name);
|
||||||
|
if (!set) {
|
||||||
|
set = g_malloc(sizeof(struct set));
|
||||||
|
set_init(set);
|
||||||
|
g_hash_table_insert(playlist_db, (gpointer)name, set);
|
||||||
|
}
|
||||||
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool __playlist_is_static(enum playlist_t plist)
|
static inline bool __playlist_is_static(enum playlist_t plist)
|
||||||
|
@ -28,11 +41,11 @@ static inline bool __playlist_is_dynamic(enum playlist_t plist)
|
||||||
|
|
||||||
static void __playlist_fill_static(enum playlist_t plist)
|
static void __playlist_fill_static(enum playlist_t plist)
|
||||||
{
|
{
|
||||||
struct index_entry *ent = __playlist_lookup(plist);
|
struct set *set = __playlist_lookup(playlist_names[plist]);
|
||||||
struct set_iter it;
|
struct set_iter it;
|
||||||
|
|
||||||
if (ent) {
|
if (set) {
|
||||||
set_for_each(&ent->ie_set, &it)
|
set_for_each(set, &it)
|
||||||
queue_add(&playlist_q, track_get(it.it_val));
|
queue_add(&playlist_q, track_get(it.it_val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +69,51 @@ static void __playlist_fill_dynamic(enum playlist_t plist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __playlist_save()
|
||||||
|
{
|
||||||
|
struct set *set;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!file_open(&playlist_f, OPEN_WRITE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
file_writef(&playlist_f, "%u\n", g_hash_table_size(playlist_db));
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
set = __playlist_lookup(playlist_names[i]);
|
||||||
|
if (!set)
|
||||||
|
continue;
|
||||||
|
file_writef(&playlist_f, "1 %s\n", playlist_names[i]);
|
||||||
|
set_write(&playlist_f, set);
|
||||||
|
file_writef(&playlist_f, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
file_close(&playlist_f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __playlist_init_idle()
|
||||||
|
{
|
||||||
|
unsigned int i, n, valid;
|
||||||
|
struct set *set;
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
|
if (!file_open(&playlist_f, OPEN_READ))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
file_readf(&playlist_f, "%u\n", &n);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
file_readf(&playlist_f, "%u ", &valid);
|
||||||
|
if (!valid)
|
||||||
|
continue;
|
||||||
|
name = file_readl(&playlist_f);
|
||||||
|
set = __playlist_alloc(name);
|
||||||
|
set_read(&playlist_f, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_close(&playlist_f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void playlist_init(struct queue_ops *ops)
|
void playlist_init(struct queue_ops *ops)
|
||||||
{
|
{
|
||||||
|
@ -65,23 +123,35 @@ void playlist_init(struct queue_ops *ops)
|
||||||
queue_sort(&playlist_q, COMPARE_TRACK, false);
|
queue_sort(&playlist_q, COMPARE_TRACK, false);
|
||||||
queue_set_flag(&playlist_q, Q_NO_SORT);
|
queue_set_flag(&playlist_q, Q_NO_SORT);
|
||||||
|
|
||||||
index_init(&playlist_db, "playlist.db", true);
|
playlist_db = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
db_load_idle(&playlist_db);
|
idle_schedule(IDLE_SYNC, __playlist_init_idle, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void playlist_deinit()
|
void playlist_deinit()
|
||||||
{
|
{
|
||||||
|
struct set *set;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
set = __playlist_lookup(playlist_names[i]);
|
||||||
|
if (set)
|
||||||
|
set_deinit(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy(playlist_db);
|
||||||
queue_deinit(&playlist_q);
|
queue_deinit(&playlist_q);
|
||||||
db_deinit(&playlist_db);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool playlist_add(enum playlist_t plist, struct track *track)
|
bool playlist_add(enum playlist_t plist, struct track *track)
|
||||||
{
|
{
|
||||||
if (!track || !__playlist_is_static(plist) || playlist_has(plist, track))
|
struct set *set;
|
||||||
return false;
|
|
||||||
|
|
||||||
index_insert(&playlist_db, playlist_names[plist],
|
if (!track || __playlist_is_dynamic(plist))
|
||||||
track->tr_dbe.dbe_index);
|
return false;
|
||||||
|
set = __playlist_alloc(playlist_names[plist]);
|
||||||
|
if (!set_insert(set, track->tr_dbe.dbe_index))
|
||||||
|
return false;
|
||||||
|
__playlist_save();
|
||||||
if (playlist_cur == plist)
|
if (playlist_cur == plist)
|
||||||
queue_add(&playlist_q, track);
|
queue_add(&playlist_q, track);
|
||||||
return true;
|
return true;
|
||||||
|
@ -89,11 +159,16 @@ bool playlist_add(enum playlist_t plist, struct track *track)
|
||||||
|
|
||||||
bool playlist_remove(enum playlist_t plist, struct track *track)
|
bool playlist_remove(enum playlist_t plist, struct track *track)
|
||||||
{
|
{
|
||||||
if (!track || !playlist_has(plist, track))
|
struct set *set;
|
||||||
return false;
|
|
||||||
|
|
||||||
index_remove(&playlist_db, playlist_names[plist],
|
if (!track || __playlist_is_dynamic(plist))
|
||||||
track->tr_dbe.dbe_index);
|
return false;
|
||||||
|
set = __playlist_lookup(playlist_names[plist]);
|
||||||
|
if (!set)
|
||||||
|
return true;
|
||||||
|
if (!set_remove(set, track->tr_dbe.dbe_index))
|
||||||
|
return false;
|
||||||
|
__playlist_save();
|
||||||
if (playlist_cur == plist)
|
if (playlist_cur == plist)
|
||||||
queue_remove_all(&playlist_q, track);
|
queue_remove_all(&playlist_q, track);
|
||||||
return true;
|
return true;
|
||||||
|
@ -101,9 +176,11 @@ bool playlist_remove(enum playlist_t plist, struct track *track)
|
||||||
|
|
||||||
bool playlist_has(enum playlist_t plist, struct track *track)
|
bool playlist_has(enum playlist_t plist, struct track *track)
|
||||||
{
|
{
|
||||||
if (!track || __playlist_is_dynamic(plist))
|
struct set *set = __playlist_lookup(playlist_names[plist]);
|
||||||
|
|
||||||
|
if (!set || !track)
|
||||||
return false;
|
return false;
|
||||||
return index_has(&playlist_db, playlist_names[plist], track->tr_dbe.dbe_index);
|
return set_has(set, track->tr_dbe.dbe_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void playlist_select(enum playlist_t plist)
|
void playlist_select(enum playlist_t plist)
|
||||||
|
|
Loading…
Reference in New Issue