Mercurial > pidgin
diff libpurple/imgstore.c @ 16375:391a79778f89
Rework the buddy icon subsystem to use the imgstore subsystem, and modify the
imgstore subsystem to not require IDs for everything.
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Tue, 24 Apr 2007 03:57:07 +0000 |
parents | 32c366eeeb99 |
children | dd47fa8ba3e4 |
line wrap: on
line diff
--- a/libpurple/imgstore.c Tue Apr 24 03:56:16 2007 +0000 +++ b/libpurple/imgstore.c Tue Apr 24 03:57:07 2007 +0000 @@ -27,140 +27,160 @@ #include <glib.h> #include "debug.h" #include "imgstore.h" +#include "util.h" -static GSList *imgstore = NULL; +static GHashTable *imgstore; static int nextid = 0; /** * Stored image * - * Represents a single IM image awaiting display and/or transmission. - * Now that this type is basicly private too, these two structs could - * probably be combined. + * NOTE: purple_imgstore_add() creates these without zeroing the memory, so + * NOTE: make sure to update that function when adding members. */ struct _PurpleStoredImage { - char *data; /**< The image data. */ + int id; + guint8 refcount; size_t size; /**< The image data's size. */ char *filename; /**< The filename (for the UI) */ + gpointer data; /**< The image data. */ }; -typedef struct +PurpleStoredImage * +purple_imgstore_add(gconstpointer data, size_t size, const char *filename) { - int id; - int refcount; - PurpleStoredImage *img; -} PurpleStoredImagePriv; - -/* private functions */ - -static PurpleStoredImagePriv *purple_imgstore_get_priv(int id) { - GSList *tmp = imgstore; - PurpleStoredImagePriv *priv = NULL; - - g_return_val_if_fail(id > 0, NULL); - - while (tmp && !priv) { - PurpleStoredImagePriv *tmp_priv = tmp->data; - - if (tmp_priv->id == id) - priv = tmp_priv; - - tmp = tmp->next; - } - - if (!priv) - purple_debug(PURPLE_DEBUG_ERROR, "imgstore", "failed to find image id %d\n", id); - - return priv; -} - -static void purple_imgstore_free_priv(PurpleStoredImagePriv *priv) { - PurpleStoredImage *img = NULL; - - g_return_if_fail(priv != NULL); - - img = priv->img; - if (img) { - g_free(img->data); - g_free(img->filename); - g_free(img); - } - - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "freed image id %d\n", priv->id); - - g_free(priv); - - imgstore = g_slist_remove(imgstore, priv); -} - -/* public functions */ - -int purple_imgstore_add(const void *data, size_t size, const char *filename) { - PurpleStoredImagePriv *priv; PurpleStoredImage *img; g_return_val_if_fail(data != NULL, 0); g_return_val_if_fail(size > 0, 0); - img = g_new0(PurpleStoredImage, 1); + img = g_slice_new(PurpleStoredImage); img->data = g_memdup(data, size); img->size = size; img->filename = g_strdup(filename); + img->refcount = 1; + img->id = 0; - priv = g_new0(PurpleStoredImagePriv, 1); - priv->id = ++nextid; - priv->refcount = 1; - priv->img = img; + return img; +} + +int +purple_imgstore_add_with_id(gconstpointer data, size_t size, const char *filename) +{ + PurpleStoredImage *img = purple_imgstore_add(data, size, filename); + img->id = ++nextid; + + g_hash_table_insert(imgstore, GINT_TO_POINTER(img->id), img); - imgstore = g_slist_append(imgstore, priv); - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "added image id %d\n", priv->id); + return img->id; +} + +PurpleStoredImage *purple_imgstore_find_by_id(int id) { + PurpleStoredImage *img = g_hash_table_lookup(imgstore, GINT_TO_POINTER(id)); - return priv->id; + if (img != NULL) + purple_debug_misc("imgstore", "retrieved image id %d\n", img->id); + + return img; +} + +gconstpointer purple_imgstore_get_data(PurpleStoredImage *img) { + return img->data; } -PurpleStoredImage *purple_imgstore_get(int id) { - PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); +size_t purple_imgstore_get_size(PurpleStoredImage *img) +{ + return img->size; +} - g_return_val_if_fail(priv != NULL, NULL); +const char *purple_imgstore_get_filename(PurpleStoredImage *img) +{ + return img->filename; +} - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "retrieved image id %d\n", priv->id); - - return priv->img; +const char *purple_imgstore_get_extension(PurpleStoredImage *img) +{ + return purple_util_get_image_extension(img->data, img->size); } -gpointer purple_imgstore_get_data(PurpleStoredImage *i) { - return i->data; +void purple_imgstore_ref_by_id(int id) +{ + PurpleStoredImage *img = purple_imgstore_find_by_id(id); + + g_return_if_fail(img != NULL); + + purple_imgstore_ref(img); +} + +void purple_imgstore_unref_by_id(int id) +{ + PurpleStoredImage *img = purple_imgstore_find_by_id(id); + + g_return_if_fail(img != NULL); + + purple_imgstore_unref(img); } -size_t purple_imgstore_get_size(PurpleStoredImage *i) { - return i->size; -} +PurpleStoredImage * +purple_imgstore_ref(PurpleStoredImage *img) +{ + g_return_val_if_fail(img != NULL, NULL); -const char *purple_imgstore_get_filename(PurpleStoredImage *i) { - return i->filename; + img->refcount++; + + return img; } -void purple_imgstore_ref(int id) { - PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); +PurpleStoredImage * +purple_imgstore_unref(PurpleStoredImage *img) +{ + if (img == NULL) + return NULL; + + g_return_val_if_fail(img->refcount > 0, NULL); + + img->refcount--; - g_return_if_fail(priv != NULL); + if (img->refcount == 0) + { + purple_signal_emit(purple_blist_get_handle(), + "image-deleting", img); - (priv->refcount)++; + if (img->id) + g_hash_table_remove(imgstore, GINT_TO_POINTER(img->id)); + g_slice_free(PurpleStoredImage, img); + } - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "referenced image id %d (count now %d)\n", priv->id, priv->refcount); + return img; } -void purple_imgstore_unref(int id) { - PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); +void * +purple_imgstore_get_handle() +{ + static int handle; - g_return_if_fail(priv != NULL); - g_return_if_fail(priv->refcount > 0); + return &handle; +} + +void +purple_imgstore_init() +{ + void *handle = purple_imgstore_get_handle(); - (priv->refcount)--; - - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "unreferenced image id %d (count now %d)\n", priv->id, priv->refcount); + purple_signal_register(handle, "image-deleting", + purple_marshal_VOID__POINTER, NULL, + 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_STORED_IMAGE)); - if (priv->refcount == 0) - purple_imgstore_free_priv(priv); + imgstore = g_hash_table_new(g_int_hash, g_int_equal); } + +void +purple_imgstore_uninit() +{ + g_hash_table_destroy(imgstore); + + purple_signals_unregister_by_instance(purple_blist_get_handle()); +}