ocarina/gui/model.c

324 lines
8.4 KiB
C

/*
* Copyright 2016 (c) Anna Schumaker.
*/
#include <core/audio.h>
#include <core/queue.h>
#include <core/string.h>
#include <gui/model.h>
static const GTypeInfo queue_type_info;
static const GInterfaceInfo queue_tree_model;
static GObjectClass *parent_class = NULL;
static gchar *font_current = "bold";
static gchar *font_regular = "";
static GType queue_columns[Q_MODEL_N_COLUMNS] = {
[Q_MODEL_TRACK_NR] = G_TYPE_UINT,
[Q_MODEL_TITLE] = G_TYPE_STRING,
[Q_MODEL_LENGTH] = G_TYPE_STRING,
[Q_MODEL_ARTIST] = G_TYPE_STRING,
[Q_MODEL_ALBUM] = G_TYPE_STRING,
[Q_MODEL_YEAR] = G_TYPE_UINT,
[Q_MODEL_GENRE] = G_TYPE_STRING,
[Q_MODEL_COUNT] = G_TYPE_UINT,
[Q_MODEL_LAST_PLAY] = G_TYPE_STRING,
[Q_MODEL_FILE_PATH] = G_TYPE_STRING,
[Q_MODEL_FONT] = G_TYPE_STRING,
};
static gboolean __queue_model_iter_nth(GuiQueueModel *model,
GtkTreeIter *iter,
gint n)
{
if (n >= queue_size(model->gqm_queue))
return FALSE;
queue_iter_set(model->gqm_queue, &model->gqm_iter, n);
iter->stamp = model->gqm_stamp;
iter->user_data = &model->gqm_iter;
iter->user_data2 = queue_iter_val(&model->gqm_iter);
return TRUE;
}
static GtkTreeModelFlags _queue_model_get_flags(GtkTreeModel *model)
{
return GTK_TREE_MODEL_LIST_ONLY;
}
static gint _queue_model_get_n_columns(GtkTreeModel *model)
{
return Q_MODEL_N_COLUMNS;
}
static GType _queue_model_get_column_type(GtkTreeModel *model, gint index)
{
g_return_val_if_fail(index >= 0 && index < Q_MODEL_N_COLUMNS,
G_TYPE_INVALID);
return queue_columns[index];
}
static gboolean _queue_model_get_iter(GtkTreeModel *model, GtkTreeIter *iter,
GtkTreePath *path)
{
gint *indices, depth;
g_assert(path != NULL);
indices = gtk_tree_path_get_indices_with_depth(path, &depth);
g_assert(depth == 1);
return __queue_model_iter_nth(GUI_QUEUE_MODEL(model), iter, indices[0]);
}
static GtkTreePath *_queue_model_get_path(GtkTreeModel *model, GtkTreeIter *iter)
{
struct queue_iter *q_it;
GtkTreePath *path;
g_return_val_if_fail(iter != NULL, FALSE);
g_return_val_if_fail(iter->user_data, FALSE);
g_return_val_if_fail(iter->user_data2, FALSE);
q_it = iter->user_data;
path = gtk_tree_path_new();
gtk_tree_path_append_index(path, q_it->it_pos);
return path;
}
static void _queue_model_get_value(GtkTreeModel *model, GtkTreeIter *iter,
gint column, GValue *value)
{
struct track *track = iter->user_data2;
gchar *str;
g_return_if_fail(iter != NULL);
g_return_if_fail(iter->user_data2 != NULL);
g_return_if_fail(column < Q_MODEL_N_COLUMNS);
g_value_init(value, queue_columns[column]);
switch (column) {
case Q_MODEL_TRACK_NR:
g_value_set_uint(value, track->tr_track);
break;
case Q_MODEL_TITLE:
g_value_set_static_string(value, track->tr_title);
break;
case Q_MODEL_LENGTH:
g_value_take_string(value, string_sec2str(track->tr_length));
break;
case Q_MODEL_ARTIST:
g_value_set_static_string(value, track->tr_artist->ar_name);
break;
case Q_MODEL_ALBUM:
g_value_set_static_string(value, track->tr_album->al_name);
break;
case Q_MODEL_YEAR:
g_value_set_uint(value, track->tr_album->al_year);
break;
case Q_MODEL_GENRE:
g_value_set_static_string(value, track->tr_genre->ge_name);
break;
case Q_MODEL_COUNT:
g_value_set_uint(value, track->tr_count);
break;
case Q_MODEL_LAST_PLAY:
g_value_take_string(value, track_last_play(track));
break;
case Q_MODEL_FILE_PATH:
str = track_path(track);
g_value_take_string(value, g_markup_escape_text(str, -1));
g_free(str);
break;
case Q_MODEL_FONT:
str = (track == audio_cur_track()) ? font_current : font_regular;
g_value_set_static_string(value, str);
break;
}
}
static gboolean _queue_model_iter_next(GtkTreeModel *model, GtkTreeIter *iter)
{
GuiQueueModel *gqm = GUI_QUEUE_MODEL(model);
g_return_val_if_fail(iter != NULL, FALSE);
g_return_val_if_fail(iter->user_data, FALSE);
g_return_val_if_fail(iter->user_data2, FALSE);
queue_iter_next(&gqm->gqm_iter);
if (gqm->gqm_iter.it_iter == NULL)
return FALSE;
iter->stamp = gqm->gqm_stamp;
iter->user_data = &gqm->gqm_iter;
iter->user_data2 = queue_iter_val(&gqm->gqm_iter);
return TRUE;
}
static gboolean _queue_model_iter_children(GtkTreeModel *model,
GtkTreeIter *iter,
GtkTreeIter *parent)
{
if (parent)
return FALSE;
return __queue_model_iter_nth(GUI_QUEUE_MODEL(model), iter, 0);
}
static gboolean _queue_model_iter_has_child(GtkTreeModel *model,
GtkTreeIter *iter)
{
return FALSE;
}
static gint _queue_model_iter_n_children(GtkTreeModel *model,
GtkTreeIter *iter)
{
if (iter != NULL)
return 0;
return queue_size(GUI_QUEUE_MODEL(model)->gqm_queue);
}
static gboolean _queue_model_iter_nth_child(GtkTreeModel *model,
GtkTreeIter *iter,
GtkTreeIter *parent,
gint n)
{
if (parent)
return FALSE;
return __queue_model_iter_nth(GUI_QUEUE_MODEL(model), iter, n);
}
static gboolean _queue_model_iter_parent(GtkTreeModel *model,
GtkTreeIter *iter,
GtkTreeIter *child)
{
return FALSE;
}
static void _queue_model_init(GuiQueueModel *model)
{
model->gqm_stamp = g_random_int();
}
static void _queue_model_finalize(GObject *object)
{
parent_class->finalize(object);
}
static void _queue_model_class_init(GuiQueueModelClass *class)
{
GObjectClass *object_class;
parent_class = g_type_class_peek_parent(class);
object_class = (GObjectClass *)class;
object_class->finalize = _queue_model_finalize;
}
static void _queue_tree_model_init(GtkTreeModelIface *iface)
{
iface->get_flags = _queue_model_get_flags;
iface->get_n_columns = _queue_model_get_n_columns;
iface->get_column_type = _queue_model_get_column_type;
iface->get_iter = _queue_model_get_iter;
iface->get_path = _queue_model_get_path;
iface->get_value = _queue_model_get_value;
iface->iter_next = _queue_model_iter_next;
iface->iter_children = _queue_model_iter_children;
iface->iter_has_child = _queue_model_iter_has_child;
iface->iter_n_children = _queue_model_iter_n_children;
iface->iter_nth_child = _queue_model_iter_nth_child;
iface->iter_parent = _queue_model_iter_parent;
}
GuiQueueModel *gui_queue_model_new(struct queue *queue)
{
GuiQueueModel *model = g_object_new(GUI_QUEUE_MODEL_TYPE, NULL);
g_assert(model != NULL);
model->gqm_queue = queue;
return model;
}
GType gui_queue_model_get_type()
{
static GType queue_type = 0;
if (queue_type == 0) {
queue_type = g_type_register_static(G_TYPE_OBJECT,
"GuiQueueModel",
&queue_type_info,
(GTypeFlags)0);
g_type_add_interface_static(queue_type,
GTK_TYPE_TREE_MODEL,
&queue_tree_model);
}
return queue_type;
}
void gui_queue_model_add(GuiQueueModel *model, unsigned int row)
{
GtkTreePath *path = gtk_tree_path_new_from_indices(row, -1);
GtkTreeIter iter;
_queue_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
gtk_tree_model_row_inserted(GTK_TREE_MODEL(model), path, &iter);
gtk_tree_path_free(path);
}
void gui_queue_model_remove(GuiQueueModel *model, unsigned int row)
{
GtkTreePath *path = gtk_tree_path_new_from_indices(row, -1);
gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), path);
gtk_tree_path_free(path);
}
void gui_queue_model_clear(GuiQueueModel *model, unsigned int n)
{
unsigned int i;
for (i = 1; i <= n; i++)
gui_queue_model_remove(model, n - i);
}
void gui_queue_model_update(GuiQueueModel *model, unsigned int row)
{
GtkTreePath *path = gtk_tree_path_new_from_indices(row, -1);
GtkTreeIter iter;
_queue_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &iter);
gtk_tree_path_free(path);
}
struct track * gui_queue_model_path_get_track(GuiQueueModel *model,
GtkTreePath *path)
{
GtkTreeIter iter;
_queue_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
return gui_queue_model_iter_get_track(model, &iter);
}
static const GTypeInfo queue_type_info = {
.class_size = sizeof(GuiQueueModelClass),
.base_init = NULL,
.base_finalize = NULL,
.class_init = (GClassInitFunc)_queue_model_class_init,
.class_finalize = NULL,
.class_data = NULL,
.instance_size = sizeof(GuiQueueModel),
.n_preallocs = 0,
.instance_init = (GInstanceInitFunc)_queue_model_init,
};
static const GInterfaceInfo queue_tree_model = {
.interface_init = (GInterfaceInitFunc)_queue_tree_model_init,
.interface_finalize = NULL,
.interface_data = NULL,
};