Mercurial > audlegacy-plugins
changeset 2795:4c9db0b2194f
added strcasestr implementation; improved searching and updating
author | Calin Crisan ccrisan@gmail.com |
---|---|
date | Thu, 10 Jul 2008 01:40:57 +0300 |
parents | f9c6a9cb442e |
children | 2ce16807a088 |
files | src/streambrowser/gui/streambrowser_win.c src/streambrowser/streambrowser.c |
diffstat | 2 files changed, 162 insertions(+), 108 deletions(-) [+] |
line wrap: on
line diff
--- a/src/streambrowser/gui/streambrowser_win.c Wed Jul 09 22:52:56 2008 +0300 +++ b/src/streambrowser/gui/streambrowser_win.c Thu Jul 10 01:40:57 2008 +0300 @@ -1,5 +1,7 @@ +#include <stdlib.h> #include <string.h> +#include <ctype.h> #include <glib.h> #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> @@ -10,14 +12,14 @@ typedef struct { - streamdir_t* streamdir; + streamdir_t* streamdir; GtkWidget* table; GtkWidget* tree_view; } streamdir_gui_t; -void (* update_function) (streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo); +void (* update_function) (streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo); static GtkWidget* gtk_label_new_with_icon(gchar *icon_filename, gchar *label_text); static GtkWidget* gtk_streamdir_tree_view_new(); @@ -29,20 +31,22 @@ static gboolean on_search_entry_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data); static gboolean on_tree_view_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data); -static streamdir_gui_t* find_streamdir_gui_by_name(gchar *name); -static streamdir_gui_t* find_streamdir_gui_by_tree_view(GtkTreeView *tree_view); -static streamdir_gui_t* find_streamdir_gui_by_table(GtkTable *table); -static streamdir_gui_t* find_streamdir_gui_by_streamdir(streamdir_t *streamdir); +static streamdir_gui_t* find_streamdir_gui_by_name(gchar *name); +static streamdir_gui_t* find_streamdir_gui_by_tree_view(GtkTreeView *tree_view); +static streamdir_gui_t* find_streamdir_gui_by_table(GtkTable *table); +static streamdir_gui_t* find_streamdir_gui_by_streamdir(streamdir_t *streamdir); static gboolean tree_view_search_equal_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer data); +static gboolean mystrcasestr(const char *haystack, const char *needle); + static GtkWidget* notebook; static GtkWidget* search_entry; static GtkWidget* add_button; static GtkWidget* streambrowser_window; static GList* streamdir_gui_list; -static GtkCellRenderer* cell_renderer_pixbuf; -static GtkCellRenderer* cell_renderer_text; +static GtkCellRenderer* cell_renderer_pixbuf; +static GtkCellRenderer* cell_renderer_text; void streambrowser_win_init() @@ -238,7 +242,9 @@ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), TRUE); gtk_tree_view_set_search_entry(GTK_TREE_VIEW(tree_view), GTK_ENTRY(search_entry)); gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(tree_view), tree_view_search_equal_func, NULL, NULL); + gtk_tree_view_set_search_column(GTK_TREE_VIEW(tree_view), 1); g_signal_connect(G_OBJECT(tree_view), "key-press-event", G_CALLBACK(on_tree_view_key_pressed), NULL); + g_signal_connect(G_OBJECT(tree_view), "cursor-changed", G_CALLBACK(on_tree_view_cursor_changed), NULL); GtkTreeViewColumn *column = gtk_tree_view_column_new(); gtk_tree_view_column_pack_start(column, cell_renderer_pixbuf, TRUE); @@ -260,8 +266,6 @@ gtk_tree_view_column_set_title(column, _("Now playing")); gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); - g_signal_connect(G_OBJECT(tree_view), "cursor-changed", G_CALLBACK(on_tree_view_cursor_changed), NULL); - return tree_view; } @@ -297,10 +301,11 @@ static gboolean on_tree_view_cursor_changed(GtkTreeView *tree_view, gpointer data) { GtkTreePath *path; - GtkTreeViewColumn *focus_column; + GtkTreeIter iter; + GtkTreeModel *model; /* obtain the current category */ - gtk_tree_view_get_cursor(tree_view, &path, &focus_column); + gtk_tree_view_get_cursor(tree_view, &path, NULL); if (path == NULL) return TRUE; @@ -311,7 +316,10 @@ return TRUE; } - if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(tree_view), path)) { + model = gtk_tree_view_get_model(tree_view); + gtk_tree_model_get_iter(model, &iter, path); + + if (gtk_tree_model_iter_has_child(model, &iter)) { gtk_tree_path_free(path); return TRUE; } @@ -327,9 +335,6 @@ /* issue an update on the current category */ update_function(streamdir_gui->streamdir, category_get_by_index(streamdir_gui->streamdir, category_index), NULL); - /* clear the search box */ - gtk_entry_set_text(GTK_ENTRY(search_entry), ""); - return TRUE; } @@ -365,6 +370,7 @@ category_t *category = category_get_by_index(streamdir_gui->streamdir, category_index); streaminfo_t *streaminfo = streaminfo_get_by_index(category, streaminfo_index); + gtk_entry_set_text(GTK_ENTRY(search_entry), ""); update_function(streamdir, category, streaminfo); return TRUE; @@ -372,40 +378,51 @@ static gboolean on_search_entry_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data) { - if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) + if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) { on_add_button_clicked(GTK_BUTTON(add_button), NULL); + return FALSE; + } + + if (event->keyval == GDK_Escape) { + gtk_entry_set_text(GTK_ENTRY(search_entry), ""); + return FALSE; + } - /* todo: remove this + /* todo : remove this GtkWidget *table = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))); streamdir_gui_t *streamdir_gui = find_streamdir_gui_by_table(GTK_TABLE(table)); if (streamdir_gui == NULL) return FALSE; - GtkWidget *tree_view = streamdir_gui->tree_view; + GtkTreeView *tree_view = GTK_TREE_VIEW(streamdir_gui->tree_view); + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); GtkTreeIter iter; - gboolean is_expanded = FALSE; - GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view))); GtkTreePath *path; - if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) + const gchar *key = gtk_entry_get_text(GTK_ENTRY(search_entry)); + + if (!gtk_tree_model_get_iter_first(model, &iter)) return FALSE; - while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter)) { - path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); - - if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(tree_view), path)) { - is_expanded = TRUE; - break; + while (gtk_tree_model_iter_next(model, &iter)) { + GValue value = {0, }; + + gtk_tree_model_get_value(model, &iter, 1, &value); + const gchar *string = g_value_get_string(&value); + + if (string == NULL || string[0] == '\0' || key == NULL || key[0] == '\0') + return FALSE; + + if (mystrcasestr(string, key)) { gtk_entry_set_text(GTK_ENTRY(search_entry), ""); + + path = gtk_tree_model_get_path(model, &iter); + gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE); + gtk_tree_path_free(path); } - - gtk_tree_path_free(path); - } - if (!is_expanded) - gtk_tree_view_set_search_column(GTK_TREE_VIEW(tree_view), ); - else - gtk_tree_view_set_search_column(GTK_TREE_VIEW(tree_view), 1); + g_value_unset(&value); + } */ - + return FALSE; } @@ -485,11 +502,35 @@ gtk_tree_model_get_value(model, iter, column, &value); const gchar *string = g_value_get_string(&value); - // todo: why do I get "warning: implicit declaration" for strcasestr !? - ret = ((char *) strcasestr(string, key) == NULL); + if (string == NULL || string[0] == '\0' || key == NULL || key[0] == '\0') + ret = TRUE; + + ret = !mystrcasestr(string, key); g_value_unset(&value); return ret; } +static gboolean mystrcasestr(const char *haystack, const char *needle) +{ + int len_h = strlen(haystack) + 1; + int len_n = strlen(needle) + 1; + int i; + + char *upper_h = malloc(len_h); + char *upper_n = malloc(len_n); + + for (i = 0; i < len_h; i++) + upper_h[i] = toupper(haystack[i]); + for (i = 0; i < len_n; i++) + upper_n[i] = toupper(needle[i]); + + char *p = strstr(upper_h, upper_n); + + free(upper_h); + free(upper_n); + + return (gboolean) p; +} +
--- a/src/streambrowser/streambrowser.c Wed Jul 09 22:52:56 2008 +0300 +++ b/src/streambrowser/streambrowser.c Thu Jul 10 01:40:57 2008 +0300 @@ -29,7 +29,7 @@ static void config_save(); static void streamdir_update(streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo); -static gpointer update_thread_core(update_thread_data_t *data); +static gpointer update_thread_core(gpointer user_data); static void streaminfo_add_to_playlist(streaminfo_t *streaminfo); static void on_plugin_services_menu_item_click(); @@ -241,13 +241,16 @@ if (update_thread_count >= MAX_UPDATE_THREADS) { debug("another %d streamdir updates are pending, this request will be dropped\n", update_thread_count); } - else + else { + g_mutex_lock(update_thread_mutex); + + /* do we have a running thread? */ if (update_thread_count > 0) { int i; gboolean exists = FALSE; update_thread_data_t *update_thread_data; - g_mutex_lock(update_thread_mutex); + /* search for another identic update request */ for (i = 0; i < g_queue_get_length(update_thread_data_queue); i++) { update_thread_data = g_queue_peek_nth(update_thread_data_queue, i); if (update_thread_data->streamdir == streamdir && @@ -257,105 +260,115 @@ break; } } - g_mutex_unlock(update_thread_mutex); - + + /* if no other similar request exists, we enqueue it */ if (!exists) { debug("another %d streamdir updates are pending, this request will be queued\n", update_thread_count); - g_mutex_lock(update_thread_mutex); - update_thread_data = g_malloc(sizeof(update_thread_data_t)); update_thread_data->streamdir = streamdir; update_thread_data->category = category; update_thread_data->streaminfo = streaminfo; + g_queue_push_tail(update_thread_data_queue, update_thread_data); - update_thread_count++; - - g_mutex_unlock(update_thread_mutex); } else { debug("this request is already present in the queue, dropping\n"); } } + /* no thread is currently running, we start one */ else { + debug("no other streamdir updates are pending, starting to process this request immediately\n"); + update_thread_data_t *data = g_malloc(sizeof(update_thread_data_t)); data->streamdir = streamdir; data->category = category; data->streaminfo = streaminfo; + + g_queue_push_tail(update_thread_data_queue, data); + update_thread_count++; - g_thread_create((GThreadFunc) update_thread_core, data, FALSE, NULL); + g_thread_create((GThreadFunc) update_thread_core, NULL, FALSE, NULL); } + + g_mutex_unlock(update_thread_mutex); + } } -static gpointer update_thread_core(update_thread_data_t *data) +static gpointer update_thread_core(gpointer user_data) { - g_mutex_lock(update_thread_mutex); - update_thread_count++; - g_mutex_unlock(update_thread_mutex); + debug("entering update thread core\n"); + + /* try to get the last item in the queue */ + g_mutex_lock(update_thread_mutex); + update_thread_data_t *data = NULL; + if (update_thread_count > 0) { + data = g_queue_pop_head(update_thread_data_queue); + } + g_mutex_unlock(update_thread_mutex); - /* update a streaminfo - that is - add this streaminfo to playlist */ - if (data->streaminfo != NULL) { - streaminfo_add_to_playlist(data->streaminfo); - } - /* update a category */ - else if (data->category != NULL) { - /* shoutcast */ - if (strncmp(data->streamdir->name, SHOUTCAST_NAME, strlen(SHOUTCAST_NAME)) == 0) { - gdk_threads_enter(); - streambrowser_win_set_category_state(data->streamdir, data->category, TRUE); - gdk_threads_leave(); - - shoutcast_category_fetch(data->category); + /* repetitively process the queue elements, until queue is empty */ + while (data != NULL && update_thread_count > 0) { + /* update a streaminfo - that is - add this streaminfo to playlist */ + if (data->streaminfo != NULL) { + streaminfo_add_to_playlist(data->streaminfo); + } + /* update a category */ + else if (data->category != NULL) { + /* shoutcast */ + if (strncmp(data->streamdir->name, SHOUTCAST_NAME, strlen(SHOUTCAST_NAME)) == 0) { + gdk_threads_enter(); + streambrowser_win_set_category_state(data->streamdir, data->category, TRUE); + gdk_threads_leave(); + + shoutcast_category_fetch(data->category); - gdk_threads_enter(); - streambrowser_win_set_category(data->streamdir, data->category); - streambrowser_win_set_category_state(data->streamdir, data->category, FALSE); - gdk_threads_leave(); - } - } - /* update a streamdir */ - else if (data->streamdir != NULL) { - /* shoutcast */ - if (strncmp(data->streamdir->name, SHOUTCAST_NAME, strlen(SHOUTCAST_NAME)) == 0) { - streamdir_t *streamdir = shoutcast_streamdir_fetch(); - if (streamdir != NULL) { - gdk_threads_enter(); - streambrowser_win_set_streamdir(streamdir, SHOUTCAST_ICON); - gdk_threads_leave(); - } - } - } - /* update all streamdirs */ - else { - /* shoutcast */ - streamdir_t *shoutcast_streamdir = shoutcast_streamdir_fetch(); - if (shoutcast_streamdir != NULL) { - gdk_threads_enter(); - streambrowser_win_set_streamdir(shoutcast_streamdir, SHOUTCAST_ICON); - gdk_threads_leave(); - } - } + gdk_threads_enter(); + streambrowser_win_set_category(data->streamdir, data->category); + streambrowser_win_set_category_state(data->streamdir, data->category, FALSE); + gdk_threads_leave(); + } + } + /* update a streamdir */ + else if (data->streamdir != NULL) { + /* shoutcast */ + if (strncmp(data->streamdir->name, SHOUTCAST_NAME, strlen(SHOUTCAST_NAME)) == 0) { + streamdir_t *streamdir = shoutcast_streamdir_fetch(); + if (streamdir != NULL) { + gdk_threads_enter(); + streambrowser_win_set_streamdir(streamdir, SHOUTCAST_ICON); + gdk_threads_leave(); + } + } + } + /* update all streamdirs */ + else { + /* shoutcast */ + streamdir_t *shoutcast_streamdir = shoutcast_streamdir_fetch(); + if (shoutcast_streamdir != NULL) { + gdk_threads_enter(); + streambrowser_win_set_streamdir(shoutcast_streamdir, SHOUTCAST_ICON); + gdk_threads_leave(); + } + } - g_free(data); - - /* check to see if there are queued update requests */ + g_free(data); - data = NULL; - g_mutex_lock(update_thread_mutex); - update_thread_count--; + g_mutex_lock(update_thread_mutex); + update_thread_count--; - if (update_thread_count > 0) { - data = g_queue_pop_head(update_thread_data_queue); + /* try to get the last item in the queue */ + if (update_thread_count > 0) + data = g_queue_pop_head(update_thread_data_queue); + else + data = NULL; + g_mutex_unlock(update_thread_mutex); + } - update_thread_count--; - } - g_mutex_unlock(update_thread_mutex); - - if (data != NULL) - update_thread_core(data); + debug("leaving update thread core\n"); return NULL; }