ocarina/core/playlist.c

237 lines
5.5 KiB
C

/*
* Copyright 2013 (c) Anna Schumaker.
*/
#include <core/playlist.h>
#include <core/settings.h>
#include <core/string.h>
static const gchar *SETTINGS_CUR_TYPE = "core.playlist.cur.type";
static const gchar *SETTINGS_CUR_ID = "core.playlist.cur.id";
static const gchar *SETTINGS_PREV_TYPE = "core.playlist.prev.type";
static const gchar *SETTINGS_PREV_ID = "core.playlist.prev.id";
static struct playlist *current = NULL;
static struct playlist *previous = NULL;
struct playlist_type *playlist_types[] = {
[PL_SYSTEM] = &pl_system,
[PL_ARTIST] = &pl_artist,
[PL_LIBRARY] = &pl_library,
[PL_USER] = &pl_user,
};
static struct playlist *__playlist_saved(const gchar *s_type, const gchar *s_id)
{
unsigned int type, id;
if (!settings_has(s_type) || !settings_has(s_id))
return NULL;
type = settings_get(s_type);
id = settings_get(s_id);
return playlist_types[type]->pl_get(id);
}
void playlist_init(struct playlist_callbacks *cb)
{
playlist_generic_set_callbacks(cb);
pl_system_init();
pl_artist_init();
pl_user_init();
pl_library_init();
current = __playlist_saved(SETTINGS_CUR_TYPE, SETTINGS_CUR_ID);
previous = __playlist_saved(SETTINGS_PREV_TYPE, SETTINGS_PREV_ID);
if (!current)
current = playlist_lookup(PL_SYSTEM, "Collection");
}
void playlist_deinit()
{
pl_system_deinit();
pl_artist_deinit();
pl_user_deinit();
pl_library_deinit();
}
void playlist_save()
{
unsigned int i;
for (i = 0; i < PL_MAX_TYPE; i++)
playlist_types[i]->pl_save();
}
void playlist_played(struct track *track)
{
unsigned int i;
if (track && !TRACK_IS_EXTERNAL(track)) {
for (i = 0; i < PL_MAX_TYPE; i++)
playlist_types[i]->pl_played(track);
}
}
void playlist_selected(struct track *track)
{
unsigned int i;
if (track && !TRACK_IS_EXTERNAL(track)) {
for (i = 0; i < PL_MAX_TYPE; i++)
playlist_types[i]->pl_selected(track);
if (playlist_size(current) == 0)
playlist_select(previous);
}
}
struct playlist *playlist_new(enum playlist_type_t type, const gchar *name)
{
if (type < PL_MAX_TYPE && playlist_types[type]->pl_new)
return playlist_types[type]->pl_new(name);
return NULL;
}
bool playlist_delete(struct playlist *playlist)
{
enum playlist_type_t type;
bool ret;
if (!playlist || !playlist->pl_ops->pl_delete)
return false;
type = playlist->pl_type;
ret = playlist->pl_ops->pl_delete(playlist);
if (ret)
playlist_types[type]->pl_save();
return ret;
}
struct playlist *playlist_lookup(enum playlist_type_t type, const gchar *name)
{
if (type >= PL_MAX_TYPE)
return NULL;
return playlist_types[type]->pl_lookup(name);
}
struct playlist *playlist_get(enum playlist_type_t type, unsigned int id)
{
if (type >= PL_MAX_TYPE)
return NULL;
return playlist_types[type]->pl_get(id);
}
struct playlist *playlist_current(void)
{
return current;
}
bool playlist_select(struct playlist *playlist)
{
if (!playlist || (playlist == current))
return false;
if (!playlist->pl_ops->pl_can_select)
return false;
if (!playlist->pl_ops->pl_can_select(playlist))
return false;
previous = current;
current = playlist;
settings_set(SETTINGS_CUR_TYPE, current->pl_type);
settings_set(SETTINGS_CUR_ID, current->pl_id);
if (previous) {
settings_set(SETTINGS_PREV_TYPE, previous->pl_type);
settings_set(SETTINGS_PREV_ID, previous->pl_id);
}
return true;
}
struct track *playlist_next(void)
{
struct track *track = playlist_generic_next(current);
if (track && current->pl_type < PL_MAX_TYPE)
playlist_types[current->pl_type]->pl_save();
return track;
}
struct track *playlist_prev(void)
{
return playlist_generic_next(playlist_lookup(PL_SYSTEM, "History"));
}
bool playlist_add(struct playlist *playlist, struct track *track)
{
bool ret;
if (!track || !playlist || !playlist->pl_ops->pl_add)
return false;
ret = playlist->pl_ops->pl_add(playlist, track);
if (ret && playlist->pl_type < PL_MAX_TYPE)
playlist_types[playlist->pl_type]->pl_save();
if (playlist == playlist_lookup(PL_SYSTEM, "Queued Tracks"))
playlist_select(playlist);
return ret;
}
bool playlist_remove(struct playlist *playlist, struct track *track)
{
bool ret;
if (!track || !playlist || !playlist->pl_ops->pl_remove)
return false;
ret = playlist->pl_ops->pl_remove(playlist, track);
if (ret && playlist->pl_type < PL_MAX_TYPE)
playlist_types[playlist->pl_type]->pl_save();
return ret;
}
void playlist_set_random(struct playlist *playlist, bool enabled)
{
if (playlist && playlist->pl_ops->pl_set_random) {
playlist->pl_ops->pl_set_random(playlist, enabled);
if (playlist->pl_type < PL_MAX_TYPE)
playlist_types[playlist->pl_type]->pl_save();
}
}
bool playlist_sort(struct playlist *playlist, enum compare_t sort)
{
if (!playlist || !playlist->pl_ops->pl_sort)
return false;
playlist->pl_ops->pl_sort(playlist, sort);
if (playlist->pl_type < PL_MAX_TYPE)
playlist_types[playlist->pl_type]->pl_save();
return g_slist_length(playlist->pl_sort) > 0;
}
bool playlist_rearrange(struct playlist *playlist, unsigned int old_pos,
unsigned int new_pos)
{
bool ret;
if (!playlist || !playlist->pl_ops->pl_rearrange)
return false;
ret = playlist->pl_ops->pl_rearrange(playlist, old_pos, new_pos);
if (ret && playlist->pl_type < PL_MAX_TYPE)
playlist_types[playlist->pl_type]->pl_save();
return ret;
}
void playlist_set_search(struct playlist *playlist, const gchar *text)
{
gchar **tokens = NULL;
if (!playlist)
return;
if (playlist->pl_search)
g_strfreev(playlist->pl_search);
if (strlen(text) > 0)
tokens = g_str_tokenize_and_fold(text, NULL, NULL);
playlist->pl_search = tokens;
}