summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2010-01-20 18:54:23 +0100
committerGravatar Martin Szulecki2010-01-20 18:54:23 +0100
commit87e4212b14fb26edeb7509c16c03ea53db970c5e (patch)
tree70717c4160b0fd18f4886d9881a6341bd246e80b
parent40b776a2638b7e9d422724bd76c0b6a0622bc734 (diff)
downloadsbmanager-87e4212b14fb26edeb7509c16c03ea53db970c5e.tar.gz
sbmanager-87e4212b14fb26edeb7509c16c03ea53db970c5e.tar.bz2
Load icons using threads and prevent blocking the clutter main loop
This fixes the unresponsive GUI and any other effects from "freezing" that are planned to run while the loading takes place.
-rw-r--r--src/sbmanager.c151
1 files changed, 99 insertions, 52 deletions
diff --git a/src/sbmanager.c b/src/sbmanager.c
index 6221f3f..39ce556 100644
--- a/src/sbmanager.c
+++ b/src/sbmanager.c
@@ -103,6 +103,7 @@ GList *sbpages = NULL;
guint num_dock_items = 0;
char *match_uuid = NULL;
+sbservices_client_t sbc = NULL;
int current_page = 0;
struct timeval last_page_switch;
@@ -158,6 +159,17 @@ static char *sbitem_get_display_name(SBItem *item)
return strval;
}
+
+static char *sbitem_get_display_identifier(SBItem *item)
+{
+ char *strval = NULL;
+ plist_t node = plist_dict_get_item(item->node, "displayIdentifier");
+ if (node && plist_get_node_type(node) == PLIST_STRING) {
+ plist_get_string_val(node, &strval);
+ }
+ return strval;
+}
+
static void sbitem_free(SBItem *a, gpointer data)
{
if (a) {
@@ -904,7 +916,7 @@ static void gui_show_icons()
debug_printf("%s: showing dock icons\n", __func__);
for (i = 0; i < g_list_length(dockitems); i++) {
SBItem *item = (SBItem*)g_list_nth_data(dockitems, i);
- if (item && item->texture && item->node) {
+ if (item && item->texture && !CLUTTER_ACTOR_IS_VISIBLE(item->texture) && item->node) {
item->is_dock_item = TRUE;
ClutterActor *grp = clutter_group_new();
ClutterActor *actor = item->texture;
@@ -934,7 +946,7 @@ static void gui_show_icons()
debug_printf("%s: showing page icons for page %d\n", __func__, j);
for (i = 0; i < g_list_length(cpage); i++) {
SBItem *item = (SBItem*)g_list_nth_data(cpage, i);
- if (item && item->texture && item->node) {
+ if (item && item->texture && !CLUTTER_ACTOR_IS_VISIBLE(item->texture) && item->node) {
item->is_dock_item = FALSE;
ClutterActor *grp = clutter_group_new();
ClutterActor *actor = item->texture;
@@ -958,53 +970,81 @@ static void gui_show_icons()
clutter_stage_ensure_redraw(CLUTTER_STAGE(stage));
}
-static SBItem *gui_load_icon(sbservices_client_t sbc, plist_t icon_info)
+static char *sbitem_get_icon_filename(SBItem *item)
+{
+ char *value = sbitem_get_display_identifier(item);
+ if (!value)
+ return NULL;
+
+ return g_strdup_printf("/tmp/%s.png", value);
+}
+
+static gboolean sbitem_texture_new(gpointer data)
+{
+ SBItem *item = (SBItem *)data;
+ char *icon_filename = sbitem_get_icon_filename(item);
+ GError *err = NULL;
+
+ /* create and load texture */
+ ClutterActor *actor = clutter_texture_new();
+ clutter_texture_set_load_async(CLUTTER_TEXTURE(actor), TRUE);
+ clutter_texture_set_from_file(CLUTTER_TEXTURE(actor), icon_filename, &err);
+
+ /* create item */
+ item->texture = actor;
+
+ char *txtval = sbitem_get_display_name(item);
+ if (txtval) {
+ item->label = clutter_text_new_with_text(ITEM_FONT, txtval);
+ }
+ if (err) {
+ fprintf(stderr, "ERROR: %s\n", err->message);
+ g_error_free(err);
+ }
+
+ /* FIXME: Optimize! Do not traverse whole iconlist, just this icon */
+ gui_show_icons();
+
+ return FALSE;
+}
+
+static gpointer sbitem_thread_load_texture(gpointer data)
+{
+ SBItem *item = (SBItem *)data;
+ char *icon_filename = sbitem_get_icon_filename(item);
+ char *display_identifier = sbitem_get_display_identifier(item);
+ GError *err = NULL;
+
+ debug_printf("%s: loading icon texture for '%s'\n", __func__, display_identifier);
+
+ if (device_sbs_save_icon(sbc, display_identifier, icon_filename, &err)) {
+ /* load texture in the clutter main loop */
+ clutter_threads_add_idle((GSourceFunc)sbitem_texture_new, item);
+ } else {
+ fprintf(stderr, "ERROR: %s\n", err->message);
+ g_error_free(err);
+ }
+ g_free(icon_filename);
+
+ return NULL;
+}
+
+static SBItem *sbitem_new(plist_t icon_info)
{
SBItem *di = NULL;
- plist_t valuenode = NULL;
+
if (plist_get_node_type(icon_info) != PLIST_DICT) {
return di;
}
- valuenode = plist_dict_get_item(icon_info, "displayIdentifier");
- if (valuenode && (plist_get_node_type(valuenode) == PLIST_STRING)) {
- char *value = NULL;
- char *icon_filename = NULL;
- GError *error = NULL;
- plist_get_string_val(valuenode, &value);
- debug_printf("%s: retrieving icon for '%s'\n", __func__, value);
- icon_filename = g_strdup_printf("/tmp/%s.png", value);
- if (device_sbs_save_icon(sbc, value, icon_filename, &error)) {
- GError *err = NULL;
-
- /* create and load texture */
- ClutterActor *actor = clutter_texture_new();
- clutter_texture_set_load_async(CLUTTER_TEXTURE(actor), TRUE);
- clutter_texture_set_from_file(CLUTTER_TEXTURE(actor), icon_filename, &err);
-
- /* create item */
- if (actor) {
- di = g_new0(SBItem, 1);
- di->node = plist_copy(icon_info);
- di->texture = actor;
-
- char *txtval = sbitem_get_display_name(di);
- if (txtval)
- di->label = clutter_text_new_with_text(ITEM_FONT, txtval);
- }
- if (err) {
- fprintf(stderr, "ERROR: %s\n", err->message);
- g_error_free(err);
- }
- } else {
- fprintf(stderr, "ERROR: could not get icon for '%s'\n", value);
- }
- g_free(icon_filename);
- free(value);
- }
+
+ di = g_new0(SBItem, 1);
+ di->node = plist_copy(icon_info);
+ di->texture = NULL;
+
return di;
}
-static guint gui_load_icon_row(sbservices_client_t sbc, plist_t items, GList **row)
+static guint gui_load_icon_row(plist_t items, GList **row)
{
int i;
int count;
@@ -1013,15 +1053,19 @@ static guint gui_load_icon_row(sbservices_client_t sbc, plist_t items, GList **r
count = plist_array_get_size(items);
for (i = 0; i < count; i++) {
plist_t icon_info = plist_array_get_item(items, i);
- item = gui_load_icon(sbc, icon_info);
- if (item != NULL)
+ item = sbitem_new(icon_info);
+ if (item != NULL) {
+ /* load texture of icon in a new thread */
+ g_thread_create(sbitem_thread_load_texture, item, FALSE, NULL);
+
*row = g_list_append(*row, item);
+ }
}
return count;
}
-static void gui_set_iconstate(sbservices_client_t sbc, plist_t iconstate)
+static void gui_set_iconstate(plist_t iconstate)
{
int total;
@@ -1046,7 +1090,7 @@ static void gui_set_iconstate(sbservices_client_t sbc, plist_t iconstate)
/* load dock icons */
debug_printf("%s: processing dock\n", __func__);
- num_dock_items = gui_load_icon_row(sbc, dock, &dockitems);
+ num_dock_items = gui_load_icon_row(dock, &dockitems);
if (total > 1) {
/* get all page icons */
@@ -1069,7 +1113,7 @@ static void gui_set_iconstate(sbservices_client_t sbc, plist_t iconstate)
fprintf(stderr, "ERROR: error getting page row icon array!\n");
return;
}
- gui_load_icon_row(sbc, nrow, &page);
+ gui_load_icon_row(nrow, &page);
}
if (page) {
@@ -1084,20 +1128,19 @@ static void gui_set_iconstate(sbservices_client_t sbc, plist_t iconstate)
static gboolean gui_pages_init_cb(gpointer data)
{
SBManagerApp *app = (SBManagerApp *)data;
- sbservices_client_t sbc = NULL;
GError *error = NULL;
plist_t iconstate = NULL;
/* connect to sbservices */
- sbc = device_sbs_new(app->uuid, &error);
+ if (!sbc)
+ sbc = device_sbs_new(app->uuid, &error);
+
if (sbc) {
/* Load icon data */
if (device_sbs_get_iconstate(sbc, &iconstate, &error)) {
- gui_set_iconstate(sbc, iconstate);
- gui_show_icons();
+ gui_set_iconstate(iconstate);
plist_free(iconstate);
}
- device_sbs_free(sbc);
}
return FALSE;
}
@@ -1116,7 +1159,8 @@ static gboolean set_icon_state_cb(gpointer user_data)
plist_t iconstate = gui_get_iconstate();
if (iconstate) {
GError *error = NULL;
- sbservices_client_t sbc = device_sbs_new(app->uuid, &error);
+ if (!sbc)
+ sbc = device_sbs_new(app->uuid, &error);
if (sbc) {
device_sbs_set_iconstate(sbc, iconstate, &error);
device_sbs_free(sbc);
@@ -1166,6 +1210,9 @@ static gboolean info_button_clicked_cb(GtkButton *button, gpointer user_data)
static void quit_program_cb(GtkWidget *widget, gpointer user_data)
{
/* cleanup */
+ if (sbc)
+ device_sbs_free(sbc);
+
iphone_event_unsubscribe();
gtk_main_quit();
}