db01ed3208
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
324 lines
8.4 KiB
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,
|
|
};
|