diff --git a/core/playlist.c b/core/playlist.c index e7fcabcc..f7b5d433 100644 --- a/core/playlist.c +++ b/core/playlist.c @@ -2,18 +2,31 @@ * Copyright 2013 (c) Anna Schumaker. */ #include +#include #include #include -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 enum playlist_t playlist_cur; 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) @@ -28,11 +41,11 @@ static inline bool __playlist_is_dynamic(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; - if (ent) { - set_for_each(&ent->ie_set, &it) + if (set) { + set_for_each(set, &it) 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) { @@ -65,23 +123,35 @@ void playlist_init(struct queue_ops *ops) queue_sort(&playlist_q, COMPARE_TRACK, false); queue_set_flag(&playlist_q, Q_NO_SORT); - index_init(&playlist_db, "playlist.db", true); - db_load_idle(&playlist_db); + playlist_db = g_hash_table_new(g_str_hash, g_str_equal); + idle_schedule(IDLE_SYNC, __playlist_init_idle, NULL); } 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); - db_deinit(&playlist_db); } bool playlist_add(enum playlist_t plist, struct track *track) { - if (!track || !__playlist_is_static(plist) || playlist_has(plist, track)) - return false; + struct set *set; - index_insert(&playlist_db, playlist_names[plist], - track->tr_dbe.dbe_index); + if (!track || __playlist_is_dynamic(plist)) + 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) queue_add(&playlist_q, track); 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) { - if (!track || !playlist_has(plist, track)) - return false; + struct set *set; - index_remove(&playlist_db, playlist_names[plist], - track->tr_dbe.dbe_index); + if (!track || __playlist_is_dynamic(plist)) + 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) queue_remove_all(&playlist_q, track); 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) { - if (!track || __playlist_is_dynamic(plist)) + struct set *set = __playlist_lookup(playlist_names[plist]); + + if (!set || !track) 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)