You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
6.8 KiB
254 lines
6.8 KiB
/* |
|
* 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)); |
|
}
|
|
|