ocarina/gui/queue.c

255 lines
6.8 KiB
C
Raw Normal View History

/*
* Copyright 2016 (c) Anna Schumaker.
*/
#include <core/playlist.h>
#include <core/string.h>
#include <gui/builder.h>
#include <gui/model.h>
#include <gui/queue.h>
#include <gui/view.h>
static struct gui_queue *gq_queue = NULL;
enum gq_filter_how {
GQ_FILTER_DEFAULT,
GQ_FILTER_ALBUM,
GQ_FILTER_ARTIST,
GQ_FILTER_GENRE,
GQ_FILTER_TITLE,
};
static void __queue_set_runtime(struct gui_queue *queue)
{
gchar *len;
if (queue != gq_queue)
return;
len = string_sec2str_long(queue->gq_queue->q_length);
gtk_label_set_text(GTK_LABEL(gui_builder_widget("o_runtime")), len);
g_free(len);
}
static void __queue_toggle_flag(bool active, GtkWidget *widget,
enum queue_flags flag)
{
if (gq_queue == NULL)
return;
/*
* Some GTK themes have trouble with toggle buttons,
* so let's help users by changing image sensitivity.
*/
if (active)
queue_set_flag(gq_queue->gq_queue, flag);
else
queue_unset_flag(gq_queue->gq_queue, flag);
gtk_widget_set_sensitive(widget, active);
}
void __queue_random(GtkToggleButton *button, gpointer data)
{
__queue_toggle_flag(gtk_toggle_button_get_active(button),
gtk_button_get_image(GTK_BUTTON(button)),
Q_RANDOM);
if (gq_queue->gq_playlist) {
playlist_set_random(gq_queue->gq_playlist->pl_type,
gq_queue->gq_playlist->pl_name,
gtk_toggle_button_get_active(button));
}
}
void __queue_repeat(GtkToggleButton *button, gpointer data)
{
__queue_toggle_flag(gtk_toggle_button_get_active(button),
gtk_button_get_image(GTK_BUTTON(button)),
Q_REPEAT);
}
void __queue_disabled(GtkSwitch *enabled, GParamSpec *pspec, gpointer data)
{
__queue_toggle_flag(gtk_switch_get_active(enabled),
gui_builder_widget("o_treeview"),
Q_ENABLED);
}
static gboolean __queue_visible_func(GtkTreeModel *model, GtkTreeIter *iter,
gpointer data)
{
struct track *track;
unsigned int i;
gchar *token;
bool match;
if (!gq_queue || !gq_queue->gq_search)
return TRUE;
track = gui_queue_model_iter_get_track(gq_queue->gq_model, iter);
for (i = 0; gq_queue->gq_search[i]; i++) {
token = gq_queue->gq_search[i];
switch (gq_queue->gq_active) {
case GQ_FILTER_ALBUM:
match = album_match_token(track->tr_album, token);
break;
case GQ_FILTER_ARTIST:
match = artist_match_token(track->tr_artist, token);
break;
case GQ_FILTER_GENRE:
match = genre_match_token(track->tr_genre, token);
break;
case GQ_FILTER_TITLE:
match = track_match_token(track, token);
break;
default: /* GQ_FILTER_DEFAULT */
match = track_match_token(track, token) ||
album_match_token(track->tr_album, token) ||
artist_match_token(track->tr_artist, token) ||
genre_match_token(track->tr_genre, token);
}
if (!match)
return false;
}
return TRUE;
}
void __queue_filter(GtkSearchEntry *entry, gpointer data)
{
const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry));
GtkComboBox *combo = GTK_COMBO_BOX(gui_builder_widget("filter_how"));
if (!gq_queue)
return;
if (gq_queue->gq_search) {
g_strfreev(gq_queue->gq_search);
gq_queue->gq_search = NULL;
}
if (strlen(text) > 0) {
gq_queue->gq_search = g_str_tokenize_and_fold(text, NULL, NULL);
gq_queue->gq_active = gtk_combo_box_get_active(combo);
}
gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(gq_queue->gq_filter));
gui_view_scroll();
}
void __queue_filter_how_changed(int n)
{
__queue_filter(GTK_SEARCH_ENTRY(gui_builder_widget("o_search")), NULL);
}
struct gui_queue *gui_queue_alloc(struct playlist *playlist, struct queue *queue,
const gchar *text, unsigned int flags)
{
struct gui_queue *gq = g_malloc(sizeof(struct gui_queue));
gq->gq_flags = flags;
gq->gq_text = g_strdup(text);
gq->gq_search = NULL;
gq->gq_model = gui_queue_model_new(queue);
gq->gq_filter = gtk_tree_model_filter_new(
GTK_TREE_MODEL(gq->gq_model), NULL);
gq->gq_playlist = playlist;
gq->gq_queue = queue;
gq->gq_search = NULL;
gtk_tree_model_filter_set_visible_func(
GTK_TREE_MODEL_FILTER(gq->gq_filter),
__queue_visible_func,
gui_builder_object("o_search"), NULL);
return gq;
}
void gui_queue_free(struct queue *queue)
{
struct gui_queue *gq = gui_queue(queue);
queue->q_private = NULL;
if (gq_queue == gq)
gui_view_set_model(NULL);
if (gq->gq_search)
g_strfreev(gq->gq_search);
g_object_unref(gq->gq_model);
g_free(gq->gq_text);
g_free(gq);
}
void gui_queue_show(struct gui_queue *queue)
{
GtkTreeView *view = GTK_TREE_VIEW(gui_builder_widget("o_treeview"));
GtkButton *random = GTK_BUTTON(gui_builder_widget("o_random"));
GtkButton *repeat = GTK_BUTTON(gui_builder_widget("o_repeat"));
GtkSwitch *enabled = GTK_SWITCH(gui_builder_widget("o_enable"));
GtkEntry *search = GTK_ENTRY(gui_builder_widget("o_search"));
GtkLabel *runtime = GTK_LABEL(gui_builder_widget("o_runtime"));
bool has_random = false, has_repeat = false, is_enabled = false;;
gchar *text;
gq_queue = queue;
gtk_widget_set_sensitive(GTK_WIDGET(random), gui_queue_can_random(queue));
gtk_widget_set_sensitive(GTK_WIDGET(repeat), gui_queue_can_repeat(queue));
gtk_widget_set_sensitive(GTK_WIDGET(enabled), gui_queue_can_disable(queue));
if (queue) {
has_random = queue_has_flag(queue->gq_queue, Q_RANDOM);
has_repeat = queue_has_flag(queue->gq_queue, Q_REPEAT);
is_enabled = queue_has_flag(queue->gq_queue, Q_ENABLED);
gui_view_set_model(GTK_TREE_MODEL_FILTER(queue->gq_filter));
__queue_set_runtime(queue);
} else
gtk_label_set_text(runtime, "");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(random), has_random);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat), has_repeat);
gtk_switch_set_active(GTK_SWITCH(enabled), is_enabled);
/*
* Some GTK themes have trouble with toggle buttons,
* so let's help users know what the current state is.
*/
gtk_widget_set_sensitive(gtk_button_get_image(random), has_random);
gtk_widget_set_sensitive(gtk_button_get_image(repeat), has_repeat);
gtk_widget_set_sensitive(GTK_WIDGET(view), is_enabled);
gtk_widget_set_sensitive(GTK_WIDGET(search), queue != NULL);
if (queue && queue->gq_search) {
text = g_strjoinv(" ", queue->gq_search);
gtk_entry_set_text(search, text);
g_free(text);
} else
gtk_entry_set_text(search, "");
}
void gui_queue_added(struct queue *queue, unsigned int row)
{
gui_queue_model_add(gui_queue(queue)->gq_model, row);
__queue_set_runtime(gui_queue(queue));
}
void gui_queue_removed(struct queue *queue, unsigned int row)
{
gui_queue_model_remove(gui_queue(queue)->gq_model, row);
__queue_set_runtime(gui_queue(queue));
}
void gui_queue_cleared(struct queue *queue, unsigned int n)
{
gui_queue_model_clear(gui_queue(queue)->gq_model, n);
__queue_set_runtime(gui_queue(queue));
}
void gui_queue_updated(struct queue *queue, unsigned int row)
{
gui_queue_model_update(gui_queue(queue)->gq_model, row);
__queue_set_runtime(gui_queue(queue));
}