ocarina/core/playlists/artist.c
Anna Schumaker b17585237a core/playlist: Add a playlist_played() function
This is used to notify when tracks have been played so dynamic playlists
can be updated, and so the model can display the correct playcount.

The old system playlist tests are mostly unnecessary at this point, so I
remove them as part of this patch.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2017-04-28 09:40:02 -04:00

190 lines
4.3 KiB
C

/*
* Copyright 2016 (c) Anna Schumaker.
*/
#include <core/idle.h>
#include <core/playlists/artist.h>
#include <core/string.h>
static struct queue_ops *artist_ops = NULL;
static struct file artist_file = FILE_INIT("playlist.artist", 0);
static struct playlist_ops pl_artist_ops = {
.pl_can_select = playlist_generic_can_select,
.pl_next = playlist_generic_next,
.pl_set_flag = playlist_generic_set_flag,
.pl_sort = playlist_generic_sort,
};
static struct playlist *__artist_pl_alloc(struct artist *artist)
{
struct playlist *playlist = g_malloc(sizeof(struct playlist));
playlist->pl_name = artist->ar_name;
playlist->pl_type = PL_ARTIST;
playlist->pl_id = artist_index(artist);
playlist->pl_ops = &pl_artist_ops;
playlist_generic_init(playlist, Q_REPEAT, artist_ops);
return playlist;
}
static void __artist_pl_free(struct playlist *playlist)
{
if (playlist) {
queue_deinit(&playlist->pl_queue);
g_free(playlist);
}
}
static bool __artist_pl_add(void *data)
{
struct playlist *playlist = (struct playlist *)data;
struct artist *artist = artist_lookup(playlist->pl_name);
struct db_entry *dbe, *next;
db_for_each(dbe, next, track_db_get()) {
if (TRACK(dbe)->tr_album->al_artist == artist)
queue_add_front(&playlist->pl_queue, TRACK(dbe));
}
queue_resort(&playlist->pl_queue);
return true;
}
static struct playlist *__artist_pl_lookup(const gchar *name)
{
struct artist *artist = artist_lookup(name);
return artist ? artist->ar_playlist : NULL;
}
static bool __artist_pl_load(void *data)
{
struct playlist *playlist;
unsigned int i, n;
gchar *name;
if (!file_open(&artist_file, OPEN_READ))
return true;
file_readf(&artist_file, "%u\n", &n);
for (i = 0; i < n; i++) {
name = file_readl(&artist_file);
playlist = __artist_pl_lookup(name);
g_free(name);
if (!playlist)
continue;
queue_load_flags(&playlist->pl_queue, &artist_file, true);
queue_iter_set(&playlist->pl_queue, &playlist->pl_queue.q_cur,
playlist->pl_queue.q_cur.it_pos);
}
file_close(&artist_file);
return true;
}
static void pl_artist_save(void)
{
struct db_entry *dbe, *next;
struct playlist *playlist;
if (!file_open(&artist_file, OPEN_WRITE))
return;
file_writef(&artist_file, "%u\n", artist_db_get()->db_size);
db_for_each(dbe, next, artist_db_get()) {
playlist = ARTIST(dbe)->ar_playlist;
file_writef(&artist_file, "%s\n", playlist->pl_name);
queue_save_flags(&playlist->pl_queue, &artist_file, true);
}
file_close(&artist_file);
}
static struct playlist *pl_artist_lookup(const gchar *name)
{
return __artist_pl_lookup(name);
}
static struct playlist *pl_artist_get(unsigned int id)
{
struct artist *artist = artist_get(id);
return artist ? artist->ar_playlist : NULL;
}
static void pl_artist_played(struct track *track)
{
struct artist *artist = track->tr_album->al_artist;
struct playlist *playlist = (struct playlist *)artist->ar_playlist;
if (playlist)
queue_updated(&playlist->pl_queue, track);
}
static void pl_artist_update(const gchar *name)
{
}
struct playlist_type pl_artist = {
.pl_save = pl_artist_save,
.pl_lookup = pl_artist_lookup,
.pl_get = pl_artist_get,
.pl_played = pl_artist_played,
.pl_update = pl_artist_update,
};
void pl_artist_init(struct queue_ops *ops)
{
struct db_entry *dbe, *next;
struct playlist *playlist;
artist_ops = ops;
db_for_each(dbe, next, artist_db_get()) {
playlist = __artist_pl_alloc(ARTIST(dbe));
ARTIST(dbe)->ar_playlist = playlist;
idle_schedule(IDLE_SYNC, __artist_pl_add, playlist);
}
idle_schedule(IDLE_SYNC, __artist_pl_load, NULL);
}
void pl_artist_deinit()
{
struct db_entry *dbe, *next;
struct playlist *playlist;
db_for_each(dbe, next, artist_db_get()) {
playlist = ARTIST(dbe)->ar_playlist;
ARTIST(dbe)->ar_playlist = NULL;
__artist_pl_free(playlist);
}
}
void pl_artist_new_track(struct track *track)
{
struct artist *artist = track->tr_album->al_artist;
struct playlist *playlist = (struct playlist *)artist->ar_playlist;
if (!playlist) {
playlist = __artist_pl_alloc(artist);
artist->ar_playlist = playlist;
}
playlist_generic_add_track(playlist, track);
}
void pl_artist_delete_track(struct track *track)
{
struct artist *artist = track->tr_album->al_artist;
struct playlist *playlist = (struct playlist *)artist->ar_playlist;
if (playlist)
playlist_generic_remove_track(playlist, track);
}