/* * Copyright 2013 (c) Anna Schumaker. */ #include #include #include 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; }