b3592e40c0
"Banning" a track is a bit harsh. Let's talking about hiding tracks instead, so that it sounds friendlier. Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
140 lines
3.4 KiB
C
140 lines
3.4 KiB
C
/*
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
*/
|
|
#include <core/collection.h>
|
|
#include <core/string.h>
|
|
#include <core/playlist.h>
|
|
|
|
static struct database playlist_db;
|
|
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)
|
|
{
|
|
return INDEX_ENTRY(db_get(&playlist_db, playlist_names[plist]));
|
|
}
|
|
|
|
static inline bool __playlist_is_static(enum playlist_t plist)
|
|
{
|
|
return (plist == PL_FAVORITED) || (plist == PL_HIDDEN);
|
|
}
|
|
|
|
static inline bool __playlist_is_dynamic(enum playlist_t plist)
|
|
{
|
|
return !__playlist_is_static(plist);
|
|
}
|
|
|
|
static unsigned int __playlist_find_average()
|
|
{
|
|
struct db_entry *track, *next;
|
|
unsigned int total = 0;
|
|
|
|
if (track_db_get()->db_size == 0)
|
|
return 0;
|
|
|
|
db_for_each(track, next, track_db_get())
|
|
total += TRACK(track)->tr_count;
|
|
return total / track_db_get()->db_size;
|
|
}
|
|
|
|
static void __playlist_fill_static(enum playlist_t plist)
|
|
{
|
|
struct index_entry *ent = __playlist_lookup(plist);
|
|
struct set_iter it;
|
|
|
|
if (ent) {
|
|
set_for_each(&ent->ie_set, &it)
|
|
queue_add(&playlist_q, track_get(it.it_val));
|
|
}
|
|
}
|
|
|
|
static void __playlist_fill_dynamic(enum playlist_t plist)
|
|
{
|
|
unsigned int count = 0, average = 0;
|
|
struct db_entry *track, *next;
|
|
|
|
if (plist == PL_MOST_PLAYED || plist == PL_LEAST_PLAYED)
|
|
average = __playlist_find_average();
|
|
|
|
db_for_each(track, next, track_db_get()) {
|
|
count = TRACK(track)->tr_count;
|
|
if (plist == PL_UNPLAYED && count == 0)
|
|
queue_add(&playlist_q, TRACK(track));
|
|
else if (plist == PL_MOST_PLAYED && count > average)
|
|
queue_add(&playlist_q, TRACK(track));
|
|
else if (plist == PL_LEAST_PLAYED && count < average && count > 0)
|
|
queue_add(&playlist_q, TRACK(track));
|
|
}
|
|
}
|
|
|
|
|
|
void playlist_init(struct queue_ops *ops)
|
|
{
|
|
queue_init(&playlist_q, Q_ENABLED | Q_REPEAT, ops);
|
|
queue_sort(&playlist_q, COMPARE_ARTIST, true);
|
|
queue_sort(&playlist_q, COMPARE_YEAR, false);
|
|
queue_sort(&playlist_q, COMPARE_TRACK, false);
|
|
queue_set_flag(&playlist_q, Q_NO_SORT);
|
|
|
|
index_init(&playlist_db, "playlist.db", true);
|
|
db_load(&playlist_db);
|
|
}
|
|
|
|
void playlist_deinit()
|
|
{
|
|
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;
|
|
|
|
index_insert(&playlist_db, playlist_names[plist],
|
|
track->tr_dbe.dbe_index);
|
|
if (playlist_cur == plist)
|
|
queue_add(&playlist_q, track);
|
|
return true;
|
|
}
|
|
|
|
bool playlist_remove(enum playlist_t plist, struct track *track)
|
|
{
|
|
if (!track || !playlist_has(plist, track))
|
|
return false;
|
|
|
|
index_remove(&playlist_db, playlist_names[plist],
|
|
track->tr_dbe.dbe_index);
|
|
if (playlist_cur == plist)
|
|
queue_remove_all(&playlist_q, track);
|
|
return true;
|
|
}
|
|
|
|
bool playlist_has(enum playlist_t plist, struct track *track)
|
|
{
|
|
if (!track || __playlist_is_dynamic(plist))
|
|
return false;
|
|
return index_has(&playlist_db, playlist_names[plist], track->tr_dbe.dbe_index);
|
|
}
|
|
|
|
void playlist_select(enum playlist_t plist)
|
|
{
|
|
queue_clear(&playlist_q);
|
|
queue_set_flag(&playlist_q, Q_ADD_FRONT);
|
|
if (__playlist_is_static(plist))
|
|
__playlist_fill_static(plist);
|
|
else
|
|
__playlist_fill_dynamic(plist);
|
|
queue_unset_flag(&playlist_q, Q_ADD_FRONT);
|
|
|
|
playlist_cur = plist;
|
|
queue_resort(&playlist_q);
|
|
}
|
|
|
|
struct queue *playlist_get_queue()
|
|
{
|
|
return &playlist_q;
|
|
}
|