Remove sqlite3 build dep.
[gmpc.git] / src / Tools / pixbuf-cache.c
blob6cc2a6e321d06523dba4cb294af7f9e913bca8b4
1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <strings.h>
24 #include <glib.h>
25 #include <gdk/gdk.h>
26 #include "pixbuf-cache.h"
28 #define LOG_DOMAIN "PixbufCache"
30 /* The hash table looking up the entries */
31 static GHashTable *pb_cache = NULL;
32 guint32 total_size = 0;
33 #define MAX_SIZE 500
35 /* The structure holding the cache entry */
36 typedef struct
38 const gchar *key;
39 GdkPixbuf *pb;
40 time_t last_used;
41 gboolean in_use;
42 } DCE;
43 static guint timeout = 0;
46 const int sizes[] = {
47 32, // Small
48 48, // Default
49 80, // Large
50 250, // Browser
51 500 // Tooltip
54 int pixbuf_cache_get_closest_size(int size)
56 int i = 0;
57 for(;i<NUM_COVER_SIZES;i++)
59 if(size <= sizes[i]) return sizes[i];
61 return sizes[NUM_COVER_SIZES-1];
66 /* Creates a new cache entry */
67 static DCE *create_cache_entry(void)
69 DCE *e = g_slice_new(DCE);
70 total_size+=sizeof(DCE);
71 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"pixbuf-cache size: %u\n", total_size);
73 e->last_used = time(NULL);
74 return e;
77 static gboolean pixbuf_cache_timeout_passed(void)
79 GHashTableIter iter;
80 gchar *key;
81 DCE *e;
82 GList *liter, *list = NULL;
83 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Pixbuf cache timeout passed\n");
84 g_hash_table_iter_init(&iter, pb_cache);
85 while (g_hash_table_iter_next(&iter, (gpointer) & key, (gpointer) & e))
87 /* do something with key and value */
88 if (e->in_use == FALSE)
90 list = g_list_prepend(list, (gpointer) e->key);
93 for (liter = g_list_first(list); liter; liter = g_list_next(liter))
95 g_hash_table_remove(pb_cache, (gchar *) liter->data);
97 g_list_free(list);
98 timeout = 0;
99 return FALSE;
102 /* Called when the pixbuf looses it last entry */
103 static void pixbuf_cache_entry_toggle_ref(const gchar * key, GdkPixbuf * pb, gboolean is_last_ref)
105 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Toggle Reference called: %i:%s", is_last_ref, key);
106 if (is_last_ref)
108 DCE *e = g_hash_table_lookup(pb_cache, key);
109 if (e)
110 e->in_use = FALSE;
111 if (timeout > 0)
112 g_source_remove(timeout);
113 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "set 10 seconds timeout\n");
114 timeout = g_timeout_add_seconds(10, (GSourceFunc) pixbuf_cache_timeout_passed, NULL);
118 /* Destroy cache entry */
119 static void destroy_cache_entry(DCE * entry)
121 g_return_if_fail(entry != NULL);
122 g_object_remove_toggle_ref(G_OBJECT(entry->pb), (GToggleNotify) pixbuf_cache_entry_toggle_ref,
123 (gpointer) entry->key);
124 g_slice_free(DCE, entry);
125 total_size-=sizeof(DCE);
126 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%i: Destroy cache entry: %p size: %u", g_hash_table_size(pb_cache) - 1, entry,total_size);
129 void pixbuf_cache_create(void)
131 g_assert(pb_cache == NULL);
133 pb_cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) destroy_cache_entry);
135 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Create pixbuf cache");
139 void pixbuf_cache_destroy(void)
141 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Destroy pixbuf cache");
142 if (timeout > 0)
143 g_source_remove(timeout);
144 timeout = 0;
145 g_hash_table_destroy(pb_cache);
146 pb_cache = NULL;
147 g_log(LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"remaining size: %u\n", total_size);
150 void pixbuf_cache_clear(void)
152 pixbuf_cache_destroy();
153 pixbuf_cache_create();
156 void pixbuf_cache_add_icon(int size, const gchar * url, GdkPixbuf * pb)
158 int *mdd= (int *)url;
159 gchar *key;
160 g_assert(pb_cache != NULL);
161 if(size > MAX_SIZE) return;
163 key = g_strdup_printf("%i:%X%X%X%X", size,
164 mdd[0],
165 mdd[1],
166 mdd[2],
167 mdd[3]
170 if (g_hash_table_lookup(pb_cache, key) == NULL)
172 DCE *e = create_cache_entry();
173 e->key = key;
174 e->pb = pb;
175 e->in_use = TRUE;
176 g_object_add_toggle_ref(G_OBJECT(pb), (GToggleNotify) pixbuf_cache_entry_toggle_ref, (gpointer) key);
177 g_hash_table_insert(pb_cache, key, e);
179 else g_free(key);
182 GdkPixbuf *pixbuf_cache_lookup_icon(int size, const gchar * url)
184 int *mdd= (int *)url;
185 gchar *key = g_strdup_printf("%i:%X%X%X%X", size,
186 mdd[0],
187 mdd[1],
188 mdd[2],
189 mdd[3]
191 DCE *retv = NULL;
192 retv = g_hash_table_lookup(pb_cache, key);
193 g_free(key);
195 if (retv)
197 retv->in_use = TRUE;
199 return g_object_ref(retv->pb);
201 return NULL;