comparison 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
comparison
equal deleted inserted replaced
16374:2a19bbc743ed 16375:391a79778f89
25 */ 25 */
26 26
27 #include <glib.h> 27 #include <glib.h>
28 #include "debug.h" 28 #include "debug.h"
29 #include "imgstore.h" 29 #include "imgstore.h"
30 #include "util.h"
30 31
31 static GSList *imgstore = NULL; 32 static GHashTable *imgstore;
32 static int nextid = 0; 33 static int nextid = 0;
33 34
34 /** 35 /**
35 * Stored image 36 * Stored image
36 * 37 *
37 * Represents a single IM image awaiting display and/or transmission. 38 * NOTE: purple_imgstore_add() creates these without zeroing the memory, so
38 * Now that this type is basicly private too, these two structs could 39 * NOTE: make sure to update that function when adding members.
39 * probably be combined.
40 */ 40 */
41 struct _PurpleStoredImage 41 struct _PurpleStoredImage
42 { 42 {
43 char *data; /**< The image data. */ 43 int id;
44 guint8 refcount;
44 size_t size; /**< The image data's size. */ 45 size_t size; /**< The image data's size. */
45 char *filename; /**< The filename (for the UI) */ 46 char *filename; /**< The filename (for the UI) */
47 gpointer data; /**< The image data. */
46 }; 48 };
47 49
48 typedef struct 50 PurpleStoredImage *
51 purple_imgstore_add(gconstpointer data, size_t size, const char *filename)
49 { 52 {
50 int id;
51 int refcount;
52 PurpleStoredImage *img;
53 } PurpleStoredImagePriv;
54
55 /* private functions */
56
57 static PurpleStoredImagePriv *purple_imgstore_get_priv(int id) {
58 GSList *tmp = imgstore;
59 PurpleStoredImagePriv *priv = NULL;
60
61 g_return_val_if_fail(id > 0, NULL);
62
63 while (tmp && !priv) {
64 PurpleStoredImagePriv *tmp_priv = tmp->data;
65
66 if (tmp_priv->id == id)
67 priv = tmp_priv;
68
69 tmp = tmp->next;
70 }
71
72 if (!priv)
73 purple_debug(PURPLE_DEBUG_ERROR, "imgstore", "failed to find image id %d\n", id);
74
75 return priv;
76 }
77
78 static void purple_imgstore_free_priv(PurpleStoredImagePriv *priv) {
79 PurpleStoredImage *img = NULL;
80
81 g_return_if_fail(priv != NULL);
82
83 img = priv->img;
84 if (img) {
85 g_free(img->data);
86 g_free(img->filename);
87 g_free(img);
88 }
89
90 purple_debug(PURPLE_DEBUG_INFO, "imgstore", "freed image id %d\n", priv->id);
91
92 g_free(priv);
93
94 imgstore = g_slist_remove(imgstore, priv);
95 }
96
97 /* public functions */
98
99 int purple_imgstore_add(const void *data, size_t size, const char *filename) {
100 PurpleStoredImagePriv *priv;
101 PurpleStoredImage *img; 53 PurpleStoredImage *img;
102 54
103 g_return_val_if_fail(data != NULL, 0); 55 g_return_val_if_fail(data != NULL, 0);
104 g_return_val_if_fail(size > 0, 0); 56 g_return_val_if_fail(size > 0, 0);
105 57
106 img = g_new0(PurpleStoredImage, 1); 58 img = g_slice_new(PurpleStoredImage);
107 img->data = g_memdup(data, size); 59 img->data = g_memdup(data, size);
108 img->size = size; 60 img->size = size;
109 img->filename = g_strdup(filename); 61 img->filename = g_strdup(filename);
62 img->refcount = 1;
63 img->id = 0;
110 64
111 priv = g_new0(PurpleStoredImagePriv, 1); 65 return img;
112 priv->id = ++nextid;
113 priv->refcount = 1;
114 priv->img = img;
115
116 imgstore = g_slist_append(imgstore, priv);
117 purple_debug(PURPLE_DEBUG_INFO, "imgstore", "added image id %d\n", priv->id);
118
119 return priv->id;
120 } 66 }
121 67
122 PurpleStoredImage *purple_imgstore_get(int id) { 68 int
123 PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); 69 purple_imgstore_add_with_id(gconstpointer data, size_t size, const char *filename)
70 {
71 PurpleStoredImage *img = purple_imgstore_add(data, size, filename);
72 img->id = ++nextid;
124 73
125 g_return_val_if_fail(priv != NULL, NULL); 74 g_hash_table_insert(imgstore, GINT_TO_POINTER(img->id), img);
126 75
127 purple_debug(PURPLE_DEBUG_INFO, "imgstore", "retrieved image id %d\n", priv->id); 76 return img->id;
128
129 return priv->img;
130 } 77 }
131 78
132 gpointer purple_imgstore_get_data(PurpleStoredImage *i) { 79 PurpleStoredImage *purple_imgstore_find_by_id(int id) {
133 return i->data; 80 PurpleStoredImage *img = g_hash_table_lookup(imgstore, GINT_TO_POINTER(id));
81
82 if (img != NULL)
83 purple_debug_misc("imgstore", "retrieved image id %d\n", img->id);
84
85 return img;
134 } 86 }
135 87
136 size_t purple_imgstore_get_size(PurpleStoredImage *i) { 88 gconstpointer purple_imgstore_get_data(PurpleStoredImage *img) {
137 return i->size; 89 return img->data;
138 } 90 }
139 91
140 const char *purple_imgstore_get_filename(PurpleStoredImage *i) { 92 size_t purple_imgstore_get_size(PurpleStoredImage *img)
141 return i->filename; 93 {
94 return img->size;
142 } 95 }
143 96
144 void purple_imgstore_ref(int id) { 97 const char *purple_imgstore_get_filename(PurpleStoredImage *img)
145 PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); 98 {
146 99 return img->filename;
147 g_return_if_fail(priv != NULL);
148
149 (priv->refcount)++;
150
151 purple_debug(PURPLE_DEBUG_INFO, "imgstore", "referenced image id %d (count now %d)\n", priv->id, priv->refcount);
152 } 100 }
153 101
154 void purple_imgstore_unref(int id) { 102 const char *purple_imgstore_get_extension(PurpleStoredImage *img)
155 PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); 103 {
104 return purple_util_get_image_extension(img->data, img->size);
105 }
156 106
157 g_return_if_fail(priv != NULL); 107 void purple_imgstore_ref_by_id(int id)
158 g_return_if_fail(priv->refcount > 0); 108 {
109 PurpleStoredImage *img = purple_imgstore_find_by_id(id);
159 110
160 (priv->refcount)--; 111 g_return_if_fail(img != NULL);
161 112
162 purple_debug(PURPLE_DEBUG_INFO, "imgstore", "unreferenced image id %d (count now %d)\n", priv->id, priv->refcount); 113 purple_imgstore_ref(img);
114 }
163 115
164 if (priv->refcount == 0) 116 void purple_imgstore_unref_by_id(int id)
165 purple_imgstore_free_priv(priv); 117 {
118 PurpleStoredImage *img = purple_imgstore_find_by_id(id);
119
120 g_return_if_fail(img != NULL);
121
122 purple_imgstore_unref(img);
166 } 123 }
124
125 PurpleStoredImage *
126 purple_imgstore_ref(PurpleStoredImage *img)
127 {
128 g_return_val_if_fail(img != NULL, NULL);
129
130 img->refcount++;
131
132 return img;
133 }
134
135 PurpleStoredImage *
136 purple_imgstore_unref(PurpleStoredImage *img)
137 {
138 if (img == NULL)
139 return NULL;
140
141 g_return_val_if_fail(img->refcount > 0, NULL);
142
143 img->refcount--;
144
145 if (img->refcount == 0)
146 {
147 purple_signal_emit(purple_blist_get_handle(),
148 "image-deleting", img);
149
150 if (img->id)
151 g_hash_table_remove(imgstore, GINT_TO_POINTER(img->id));
152 g_slice_free(PurpleStoredImage, img);
153 }
154
155 return img;
156 }
157
158 void *
159 purple_imgstore_get_handle()
160 {
161 static int handle;
162
163 return &handle;
164 }
165
166 void
167 purple_imgstore_init()
168 {
169 void *handle = purple_imgstore_get_handle();
170
171 purple_signal_register(handle, "image-deleting",
172 purple_marshal_VOID__POINTER, NULL,
173 1,
174 purple_value_new(PURPLE_TYPE_SUBTYPE,
175 PURPLE_SUBTYPE_STORED_IMAGE));
176
177 imgstore = g_hash_table_new(g_int_hash, g_int_equal);
178 }
179
180 void
181 purple_imgstore_uninit()
182 {
183 g_hash_table_destroy(imgstore);
184
185 purple_signals_unregister_by_instance(purple_blist_get_handle());
186 }