ocarina/gui/playlist.c
Anna Schumaker cfeca9ae4b core/playlist: Add playlist_type enum
I'm going to use this to distinguish between various playlist types that
are about to be added.  Let's update the playlist functions first, and
then add more types in a future patch.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
2016-08-13 08:31:30 -04:00

223 lines
5.9 KiB
C

/*
* Copyright 2016 (c) Anna Schumaker.
*/
#include <core/collection.h>
#include <core/string.h>
#include <gui/builder.h>
#include <gui/playlist.h>
#include <gui/sidebar.h>
enum playlist_sidebar_columns {
P_SB_IMAGE,
P_SB_NAME,
};
static GtkTreeStore *p_store;
static gchar *p_name = NULL;
static void __playlist_set(GtkTreeIter *iter, const gchar *name,
const gchar *image)
{
gtk_tree_store_set(p_store, iter, P_SB_NAME, name,
P_SB_IMAGE, image, -1);
}
static void __playlist_set_size(GtkTreeIter *iter, const gchar *name)
{
GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(p_store), iter);
unsigned int size = playlist_size(PL_SYSTEM, name);
const gchar *fmt = "%s\n%d track%s";
gchar *text;
if (gtk_tree_path_get_depth(path) == 1)
fmt = "<b>%s</b>\n%d track%s";
text = g_strdup_printf(fmt, name, size, (size == 1) ? "" : "s");
gtk_tree_store_set(p_store, iter, P_SB_NAME, text, -1);
gtk_tree_path_free(path);
g_free(text);
}
static void __playlist_add(GtkTreeIter *parent, const gchar *name,
const gchar *image)
{
GtkTreeIter iter;
gtk_tree_store_insert(p_store, &iter, parent, -1);
__playlist_set(&iter, name, image);
__playlist_set_size(&iter, name);
}
static gchar *__playlist_name(GtkTreeIter *iter)
{
GtkTreeModel *model = GTK_TREE_MODEL(p_store);
gchar *text, *parsed, *name, **split;
gtk_tree_model_get(model, iter, P_SB_NAME, &text, -1);
if (!text)
return NULL;
pango_parse_markup(text, -1, 0, NULL, &parsed, NULL, NULL);
split = g_strsplit(parsed, "\n", 2);
name = g_strdup(split[0]);
g_strfreev(split);
g_free(text);
g_free(parsed);
return name;
}
void __playlist_selection_changed(GtkTreeSelection *selection, gpointer data)
{
GtkStack *stack = GTK_STACK(gui_builder_widget("o_stack"));
GtkTreeModel *model = GTK_TREE_MODEL(p_store);
GtkTreeIter iter;
if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
if (p_name)
g_free(p_name);
p_name = __playlist_name(&iter);
gtk_stack_set_visible_child_name(stack, "queues");
gui_sidebar_selected(SB_PLAYLIST,
gui_queue(playlist_get_queue(PL_SYSTEM, p_name)));
}
}
gboolean __playlist_on_select(GtkTreeSelection *selection, GtkTreeModel *model,
GtkTreePath *path, gboolean selected, gpointer data)
{
struct queue *queue = NULL;
GtkTreeIter iter;
gchar *name;
gtk_tree_model_get_iter(model, &iter, path);
name = __playlist_name(&iter);
queue = playlist_get_queue(PL_SYSTEM, name);
g_free(name);
return queue != NULL;
}
static bool __playlist_queue_set_size(struct queue *queue, GtkTreeIter *iter)
{
gchar *name = __playlist_name(iter);
bool match = string_match(name, gui_queue(queue)->gq_text);
if (match)
__playlist_set_size(iter, name);
g_free(name);
return match;
}
static void __playlist_update_sizes(struct queue *queue)
{
GtkTreeModel *model = GTK_TREE_MODEL(p_store);
GtkTreeIter parent, iter;
if (!gtk_tree_model_get_iter_first(model, &parent))
return;
do {
if (__playlist_queue_set_size(queue, &parent))
return;
if (gtk_tree_model_iter_children(model, &iter, &parent)) {
do {
if (__playlist_queue_set_size(queue, &iter))
return;
} while (gtk_tree_model_iter_next(model, &iter));
}
} while (gtk_tree_model_iter_next(model, &parent));
}
static void *__playlist_init(struct queue *queue, void *data)
{
struct playlist *playlist = (struct playlist *)data;
unsigned int flags = 0;
if (string_match(playlist->pl_name, "Collection"))
flags = GQ_CAN_RANDOM;
return gui_queue_alloc(queue, playlist->pl_name, flags);
}
static void __playlist_added(struct queue *queue, unsigned int row)
{
gui_queue_added(queue, row);
__playlist_update_sizes(queue);
}
static void __playlist_removed(struct queue *queue, unsigned int row)
{
gui_queue_removed(queue, row);
__playlist_update_sizes(queue);
}
static bool __playlist_erase(struct queue *queue, struct track *track)
{
if (string_match(gui_playlist_cur(), "Collection"))
playlist_add(PL_SYSTEM, "Hidden", track);
else if (string_match(gui_playlist_cur(), "Favorites") ||
string_match(gui_playlist_cur(), "Hidden"))
playlist_remove(PL_SYSTEM, gui_playlist_cur(), track);
return false;
}
void gui_playlist_init()
{
GtkTreeSelection *selection;
GtkTreeView *treeview;
GtkTreeIter parent;
GtkTreePath *path;
p_store = GTK_TREE_STORE(gui_builder_object("o_playlist_store"));
treeview = GTK_TREE_VIEW(gui_builder_widget("o_playlist_view"));
selection = gtk_tree_view_get_selection(treeview);
gtk_tree_store_insert(p_store, &parent, NULL, -1);
__playlist_set(&parent, "Collection", "media-optical");
__playlist_set_size(&parent, "Collection");
path = gtk_tree_model_get_path(GTK_TREE_MODEL(p_store), &parent);
gtk_tree_selection_select_path(selection, path);
gtk_tree_path_free(path);
gtk_tree_store_insert(p_store, &parent, NULL, -1);
__playlist_set(&parent, "History", "document-open-recent");
__playlist_set_size(&parent, "History");
/* Add "Playlist" header. */
gtk_tree_store_insert(p_store, &parent, NULL, -1);
gtk_tree_store_insert(p_store, &parent, NULL, -1);
__playlist_set(&parent, "<big>Playlists</big>", "emblem-documents");
/* Add playlists. */
__playlist_add(&parent, "Favorites", "emblem-favorite");
__playlist_add(&parent, "Hidden", "window-close");
__playlist_add(&parent, "Most Played", "go-up");
__playlist_add(&parent, "Least Played", "go-down");
__playlist_add(&parent, "Unplayed", "audio-x-generic");
gtk_tree_view_expand_all(treeview);
gtk_tree_selection_set_select_function(
gtk_tree_view_get_selection(treeview),
__playlist_on_select, NULL, NULL);
gtk_tree_store_insert(p_store, &parent, NULL, -1);
}
gchar *gui_playlist_cur()
{
return p_name;
}
struct queue_ops playlist_ops = {
.qop_init = __playlist_init,
.qop_deinit = gui_queue_free,
.qop_added = __playlist_added,
.qop_erase = __playlist_erase,
.qop_removed = __playlist_removed,
.qop_cleared = gui_queue_cleared,
.qop_updated = gui_queue_updated,
};