ocarina/gui/playlist.c

223 lines
5.8 KiB
C

/*
* Copyright 2016 (c) Anna Schumaker.
*/
#include <core/idle.h>
#include <core/settings.h>
#include <core/string.h>
#include <gui/builder.h>
#include <gui/filter.h>
#include <gui/model.h>
#include <gui/playlist.h>
#include <gui/sidebar.h>
static bool p_filter_enable = true;
static bool p_init_done = false;
static void __playlist_update_sizes(struct queue *);
void __playlist_row_activated(GtkTreeView *treeview, GtkTreePath *path,
GtkTreeViewColumn *col, gpointer data)
{
gui_sidebar_filter_path_select(path);
__playlist_update_sizes(&playlist_cur()->pl_queue);
}
static bool __playlist_queue_set_size(struct queue *queue, GtkTreeIter *iter)
{
struct playlist *playlist = queue->q_private;
bool match = (gui_sidebar_iter_type(iter) == playlist->pl_type);
gchar *name = gui_sidebar_iter_name(iter);
if (match)
match = string_match(name, playlist->pl_name);
if (match)
gui_sidebar_iter_update(iter);
g_free(name);
return match;
}
static void __playlist_update_sizes(struct queue *queue)
{
GtkTreeModelFilter *filter;
GtkTreeIter parent, iter;
if (!gui_sidebar_iter_first(&parent))
return;
do {
if (__playlist_queue_set_size(queue, &parent))
goto out;
if (gtk_tree_model_iter_children(gui_sidebar_model(), &iter, &parent)) {
do {
if (__playlist_queue_set_size(queue, &iter))
goto out;
} while (gui_sidebar_iter_next(&iter));
}
} while (gui_sidebar_iter_next(&parent));
out:
filter = gui_sidebar_filter();
gtk_tree_model_filter_refilter(filter);
}
static void *__playlist_init(struct queue *queue, void *data)
{
struct playlist *playlist = (struct playlist *)data;
if (p_init_done && playlist->pl_type == PL_ARTIST) {
p_filter_enable = false;
gui_playlist_add_artist(playlist);
p_filter_enable = true;
}
if (p_init_done && playlist->pl_type == PL_USER)
gui_playlist_add_user(playlist);
return playlist;
}
static void __playlist_deinit(struct queue *queue)
{
gui_filter_clear_search(queue->q_private);
}
static void __playlist_added(struct queue *queue, unsigned int row)
{
gui_model_add(queue->q_private, row);
__playlist_update_sizes(queue);
}
static void __playlist_removed(struct queue *queue, unsigned int row)
{
gui_model_remove(queue->q_private, row);
__playlist_update_sizes(queue);
}
static void __playlist_cleared(struct queue *queue, unsigned int n)
{
gui_model_clear(queue->q_private, n);
__playlist_update_sizes(queue);
}
static void __playlist_updated(struct queue *queue, unsigned int n)
{
gui_model_update(queue->q_private, n);
}
static bool __playlist_erase(struct queue *queue, struct track *track)
{
struct playlist *playlist = queue->q_private;
enum playlist_type_t type = playlist->pl_type;
const gchar *name = playlist->pl_name;
switch (type) {
case PL_SYSTEM:
if (string_match(name, "Collection"))
name = "Hidden";
else if (!string_match(name, "Favorites") &&
!string_match(name, "Hidden") &&
!string_match(name, "Queued Tracks"))
break;
case PL_USER:
playlist_remove(type, name, track);
default:
break;
};
return false;
}
bool __gui_playlist_init_idle()
{
struct db_entry *dbe, *next;
GtkTreeSelection *selection;
GtkTreeView *treeview;
GtkTreeModel *filter;
GtkTreeIter iter;
filter = GTK_TREE_MODEL(gui_sidebar_filter());
treeview = gui_sidebar_treeview();
selection = gtk_tree_view_get_selection(treeview);
gtk_tree_model_get_iter_first(filter, &iter);
gtk_tree_selection_select_iter(selection, &iter);
p_filter_enable = false;
db_for_each(dbe, next, pl_user_db_get())
gui_playlist_add_user(&USER_PLAYLIST(dbe)->pl_playlist);
gtk_tree_view_expand_all(treeview);
db_for_each(dbe, next, artist_db_get())
gui_playlist_add_artist(ARTIST(dbe)->ar_playlist);
p_filter_enable = true;
p_init_done = true;
return true;
}
void gui_playlist_init()
{
GtkTreeIter parent;
gui_sidebar_iter_first(&parent);
gui_sidebar_iter_add(&parent, playlist_get(PL_SYSTEM, "Queued Tracks"),
"audio-x-generic");
gui_sidebar_iter_add(&parent, playlist_get(PL_SYSTEM, "Collection"),
"media-optical");
gui_sidebar_iter_add(&parent, playlist_get(PL_SYSTEM, "History"),
"document-open-recent");
/* Add "Playlists" header and playlists. */
gui_sidebar_iter_find(&parent, "Playlists", PL_MAX_TYPE);
gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Favorites"),
"emblem-favorite");
gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Hidden"),
"window-close");
/* Add "Dynamic" header. */
gui_sidebar_iter_find(&parent, "Dynamic", PL_MAX_TYPE);
gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Most Played"),
"go-up");
gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Least Played"),
"go-down");
gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Unplayed"),
"audio-x-generic");
idle_schedule(IDLE_SYNC, __gui_playlist_init_idle, NULL);
gui_pl_library_init();
}
const gchar *gui_playlist_cur()
{
if (gui_model_get_playlist())
return gui_model_get_playlist()->pl_name;
return NULL;
}
void gui_playlist_add_artist(struct playlist *playlist)
{
GtkTreeIter parent;
gui_sidebar_iter_first(&parent);
gui_sidebar_iter_find(&parent, "Collection", PL_SYSTEM);
gui_sidebar_iter_sort_child(&parent, playlist, "system-users");
}
void gui_playlist_add_user(struct playlist *playlist)
{
GtkTreeIter parent;
gui_sidebar_iter_first(&parent);
gui_sidebar_iter_find(&parent, "Playlists", PL_MAX_TYPE);
gui_sidebar_iter_sort_child(&parent, playlist, "text-x-generic");
}
struct queue_ops playlist_ops = {
.qop_init = __playlist_init,
.qop_deinit = __playlist_deinit,
.qop_added = __playlist_added,
.qop_erase = __playlist_erase,
.qop_removed = __playlist_removed,
.qop_cleared = __playlist_cleared,
.qop_updated = __playlist_updated,
};