2015-12-10 13:59:21 -05:00
|
|
|
/*
|
2013-12-22 17:24:09 -05:00
|
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
|
|
*/
|
2014-06-05 10:19:22 -04:00
|
|
|
#include <core/playlist.h>
|
2016-08-01 09:41:10 -04:00
|
|
|
#include <core/settings.h>
|
2016-08-16 10:21:22 -04:00
|
|
|
#include <core/string.h>
|
2016-05-13 13:50:59 -04:00
|
|
|
|
2016-08-16 10:21:22 -04:00
|
|
|
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";
|
2013-12-22 17:24:09 -05:00
|
|
|
|
2016-09-12 13:08:24 -04:00
|
|
|
static struct playlist *current = NULL;
|
|
|
|
static struct playlist *previous = NULL;
|
|
|
|
|
2016-05-06 08:05:21 -04:00
|
|
|
struct playlist_type *playlist_types[] = {
|
|
|
|
[PL_SYSTEM] = &pl_system,
|
2016-05-15 10:19:31 -04:00
|
|
|
[PL_ARTIST] = &pl_artist,
|
2016-05-09 07:52:10 -04:00
|
|
|
[PL_LIBRARY] = &pl_library,
|
2016-08-14 10:20:15 -04:00
|
|
|
[PL_USER] = &pl_user,
|
2016-05-06 08:05:21 -04:00
|
|
|
};
|
|
|
|
|
2015-12-10 10:55:53 -05:00
|
|
|
|
2016-09-12 13:08:24 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-09-22 13:37:34 -04:00
|
|
|
void playlist_init(struct playlist_callbacks *cb)
|
2014-05-18 21:09:46 -04:00
|
|
|
{
|
2016-09-17 09:30:11 -04:00
|
|
|
playlist_generic_set_callbacks(cb);
|
2016-09-22 13:37:34 -04:00
|
|
|
pl_system_init();
|
|
|
|
pl_artist_init();
|
|
|
|
pl_user_init();
|
|
|
|
pl_library_init();
|
2016-08-01 09:41:10 -04:00
|
|
|
|
2016-09-12 13:08:24 -04:00
|
|
|
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");
|
2014-05-18 21:09:46 -04:00
|
|
|
}
|
2014-02-02 14:11:38 -05:00
|
|
|
|
2015-12-09 09:20:18 -05:00
|
|
|
void playlist_deinit()
|
|
|
|
{
|
2016-04-24 10:36:15 -04:00
|
|
|
pl_system_deinit();
|
2016-05-15 10:19:31 -04:00
|
|
|
pl_artist_deinit();
|
2016-08-14 10:20:15 -04:00
|
|
|
pl_user_deinit();
|
2016-05-09 07:52:10 -04:00
|
|
|
pl_library_deinit();
|
2015-12-09 09:20:18 -05:00
|
|
|
}
|
|
|
|
|
2016-08-12 16:12:17 -04:00
|
|
|
void playlist_save()
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < PL_MAX_TYPE; i++)
|
|
|
|
playlist_types[i]->pl_save();
|
|
|
|
}
|
|
|
|
|
2016-09-13 10:59:20 -04:00
|
|
|
void playlist_played(struct track *track)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
2016-09-20 09:00:40 -04:00
|
|
|
|
|
|
|
if (track) {
|
|
|
|
for (i = 0; i < PL_MAX_TYPE; i++)
|
|
|
|
playlist_types[i]->pl_played(track);
|
|
|
|
}
|
2016-09-13 10:59:20 -04:00
|
|
|
}
|
|
|
|
|
2016-09-20 10:00:12 -04:00
|
|
|
void playlist_selected(struct track *track)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
if (track) {
|
|
|
|
for (i = 0; i < PL_MAX_TYPE; i++)
|
|
|
|
playlist_types[i]->pl_selected(track);
|
|
|
|
|
|
|
|
if (playlist_size(current) == 0)
|
|
|
|
playlist_select(previous);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-09 08:35:52 -04:00
|
|
|
struct playlist *playlist_new(enum playlist_type_t type, const gchar *name)
|
2016-05-09 10:38:47 -04:00
|
|
|
{
|
2016-09-09 08:35:52 -04:00
|
|
|
if (type < PL_MAX_TYPE && playlist_types[type]->pl_new)
|
|
|
|
return playlist_types[type]->pl_new(name);
|
|
|
|
return NULL;
|
2016-05-09 10:38:47 -04:00
|
|
|
}
|
|
|
|
|
2016-09-09 10:17:37 -04:00
|
|
|
bool playlist_delete(struct playlist *playlist)
|
2016-05-09 10:38:47 -04:00
|
|
|
{
|
2016-09-09 10:17:37 -04:00
|
|
|
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;
|
2016-05-09 10:38:47 -04:00
|
|
|
}
|
|
|
|
|
2016-09-12 13:49:27 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-09-12 10:59:46 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-09-12 16:02:46 -04:00
|
|
|
struct playlist *playlist_current(void)
|
|
|
|
{
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
|
2016-09-12 13:08:24 -04:00
|
|
|
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);
|
2016-09-12 15:42:56 -04:00
|
|
|
settings_set(SETTINGS_CUR_ID, current->pl_id);
|
2016-09-12 13:08:24 -04:00
|
|
|
|
|
|
|
if (previous) {
|
|
|
|
settings_set(SETTINGS_PREV_TYPE, previous->pl_type);
|
2016-09-12 15:42:56 -04:00
|
|
|
settings_set(SETTINGS_PREV_ID, previous->pl_id);
|
2016-09-12 13:08:24 -04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-09-13 08:47:45 -04:00
|
|
|
struct track *playlist_next(void)
|
|
|
|
{
|
2016-09-19 10:27:40 -04:00
|
|
|
struct track *track = playlist_generic_next(current);
|
|
|
|
if (track && current->pl_type < PL_MAX_TYPE)
|
2016-09-13 08:47:45 -04:00
|
|
|
playlist_types[current->pl_type]->pl_save();
|
|
|
|
return track;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct track *playlist_prev(void)
|
|
|
|
{
|
2016-09-19 10:27:40 -04:00
|
|
|
return playlist_generic_next(playlist_lookup(PL_SYSTEM, "History"));
|
2016-09-13 08:47:45 -04:00
|
|
|
}
|
|
|
|
|
2016-09-10 12:08:11 -04:00
|
|
|
bool playlist_add(struct playlist *playlist, struct track *track)
|
2013-12-22 17:53:58 -05:00
|
|
|
{
|
2016-08-16 10:21:22 -04:00
|
|
|
bool ret;
|
|
|
|
|
2016-09-10 12:08:11 -04:00
|
|
|
if (!track || !playlist || !playlist->pl_ops->pl_add)
|
2016-04-22 13:56:42 -04:00
|
|
|
return false;
|
2016-08-16 10:21:22 -04:00
|
|
|
|
2016-09-10 12:08:11 -04:00
|
|
|
ret = playlist->pl_ops->pl_add(playlist, track);
|
2016-09-21 10:44:06 -04:00
|
|
|
if (ret && playlist->pl_type < PL_MAX_TYPE)
|
2016-09-10 12:08:11 -04:00
|
|
|
playlist_types[playlist->pl_type]->pl_save();
|
2016-09-12 13:49:27 -04:00
|
|
|
if (playlist == playlist_lookup(PL_SYSTEM, "Queued Tracks"))
|
2016-09-12 13:08:24 -04:00
|
|
|
playlist_select(playlist);
|
2016-08-16 10:21:22 -04:00
|
|
|
return ret;
|
2013-12-22 17:53:58 -05:00
|
|
|
}
|
|
|
|
|
2016-09-10 13:11:18 -04:00
|
|
|
bool playlist_remove(struct playlist *playlist, struct track *track)
|
2013-12-22 17:53:58 -05:00
|
|
|
{
|
2016-09-10 13:11:18 -04:00
|
|
|
bool ret;
|
|
|
|
|
|
|
|
if (!track || !playlist || !playlist->pl_ops->pl_remove)
|
2016-04-22 13:56:42 -04:00
|
|
|
return false;
|
2016-09-10 13:11:18 -04:00
|
|
|
|
|
|
|
ret = playlist->pl_ops->pl_remove(playlist, track);
|
2016-09-20 14:38:46 -04:00
|
|
|
if (ret && playlist->pl_type < PL_MAX_TYPE)
|
2016-09-10 13:11:18 -04:00
|
|
|
playlist_types[playlist->pl_type]->pl_save();
|
|
|
|
return ret;
|
2013-12-22 17:53:58 -05:00
|
|
|
}
|
2013-12-22 20:53:06 -05:00
|
|
|
|
2016-09-12 08:17:41 -04:00
|
|
|
void playlist_set_random(struct playlist *playlist, bool enabled)
|
2016-05-01 19:55:47 -04:00
|
|
|
{
|
2016-09-19 10:55:29 -04:00
|
|
|
if (playlist && playlist->pl_ops->pl_set_random) {
|
|
|
|
playlist->pl_ops->pl_set_random(playlist, enabled);
|
2016-09-19 10:27:40 -04:00
|
|
|
if (playlist->pl_type < PL_MAX_TYPE)
|
|
|
|
playlist_types[playlist->pl_type]->pl_save();
|
2016-09-12 08:17:41 -04:00
|
|
|
}
|
2016-05-01 19:55:47 -04:00
|
|
|
}
|
|
|
|
|
2016-09-16 15:48:42 -04:00
|
|
|
bool playlist_sort(struct playlist *playlist, enum compare_t sort)
|
2016-05-04 09:55:37 -04:00
|
|
|
{
|
2016-09-12 09:49:35 -04:00
|
|
|
if (!playlist || !playlist->pl_ops->pl_sort)
|
|
|
|
return false;
|
|
|
|
|
2016-09-16 15:48:42 -04:00
|
|
|
playlist->pl_ops->pl_sort(playlist, sort);
|
2016-09-16 16:43:13 -04:00
|
|
|
if (playlist->pl_type < PL_MAX_TYPE)
|
|
|
|
playlist_types[playlist->pl_type]->pl_save();
|
2016-09-21 13:49:42 -04:00
|
|
|
return g_slist_length(playlist->pl_sort) > 0;
|
2016-05-04 09:55:37 -04:00
|
|
|
}
|
2016-09-21 16:49:02 -04:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|