Mercurial > audlegacy
annotate audacious/skinwin.c @ 1938:1d9c1026d9f8 trunk
[svn] - DoubleSize support.
This has bugs, the most notable one being that DoubleSize only works
right if you restart the player.
The second bug is rather obvious too. No osmosis skinengine. No
TinyPlayer. Classic-esque skinengine only. This is because the
doublesize algorithm hates you and wants you to go die in a fire.
author | nenolod |
---|---|
date | Sun, 05 Nov 2006 04:43:16 -0800 |
parents | 6e477dd65024 |
children | f18a5b617c34 |
rev | line source |
---|---|
0 | 1 /* BMP - Cross-platform multimedia player |
2 * Copyright (C) 2003-2004 BMP development team. | |
3 * | |
4 * Based on XMMS: | |
5 * Copyright (C) 1998-2003 XMMS development team. | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or | |
10 * (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
1459 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
0 | 20 */ |
21 | |
22 #ifdef HAVE_CONFIG_H | |
23 # include "config.h" | |
24 #endif | |
25 | |
26 #include "skinwin.h" | |
27 | |
28 #include <glib.h> | |
452
623391b6463b
[svn] Make "Unarchived Winamp 2.x skin" &c translatable.
nenolod
parents:
451
diff
changeset
|
29 #include <glib/gi18n.h> |
0 | 30 #include <gtk/gtk.h> |
1640 | 31 |
32 #include "platform/smartinclude.h" | |
33 | |
0 | 34 #include <stdlib.h> |
35 #include <string.h> | |
36 | |
37 #include "main.h" | |
1547 | 38 #include "widgets/widgetcore.h" |
0 | 39 #include "util.h" |
40 | |
653 | 41 #define EXTENSION_TARGETS 7 |
42 | |
43 static gchar *ext_targets[EXTENSION_TARGETS] = { "bmp", "xpm", "png", "svg", | |
44 "gif", "jpg", "jpeg" }; | |
0 | 45 |
46 #define THUMBNAIL_WIDTH 90 | |
47 #define THUMBNAIL_HEIGHT 40 | |
48 | |
49 | |
50 enum SkinViewCols { | |
51 SKIN_VIEW_COL_PREVIEW, | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
52 SKIN_VIEW_COL_FORMATTEDNAME, |
0 | 53 SKIN_VIEW_COL_NAME, |
54 SKIN_VIEW_N_COLS | |
55 }; | |
56 | |
57 | |
58 GList *skinlist = NULL; | |
59 | |
60 | |
61 | |
62 static gchar * | |
63 get_thumbnail_filename(const gchar * path) | |
64 { | |
65 gchar *basename, *pngname, *thumbname; | |
66 | |
67 g_return_val_if_fail(path != NULL, NULL); | |
68 | |
69 basename = g_path_get_basename(path); | |
70 pngname = g_strconcat(basename, ".png", NULL); | |
71 | |
72 thumbname = g_build_filename(bmp_paths[BMP_PATH_SKIN_THUMB_DIR], | |
73 pngname, NULL); | |
74 | |
75 g_free(basename); | |
76 g_free(pngname); | |
77 | |
78 return thumbname; | |
79 } | |
80 | |
81 | |
82 static GdkPixbuf * | |
83 skin_get_preview(const gchar * path) | |
84 { | |
85 GdkPixbuf *preview = NULL; | |
86 gchar *dec_path, *preview_path; | |
87 gboolean is_archive = FALSE; | |
653 | 88 gint i = 0; |
89 gchar buf[60]; /* gives us lots of room */ | |
0 | 90 |
653 | 91 if (file_is_archive(path)) |
92 { | |
0 | 93 if (!(dec_path = archive_decompress(path))) |
94 return NULL; | |
95 | |
96 is_archive = TRUE; | |
97 } | |
653 | 98 else |
99 { | |
0 | 100 dec_path = g_strdup(path); |
101 } | |
102 | |
653 | 103 for (i = 0; i < EXTENSION_TARGETS; i++) |
104 { | |
105 sprintf(buf, "main.%s", ext_targets[i]); | |
0 | 106 |
674
9e553cf3d756
[svn] - Really fix preview generation for PNG/SVG based skins.
nenolod
parents:
653
diff
changeset
|
107 if ((preview_path = find_file_recursively(dec_path, buf)) != NULL) |
653 | 108 break; |
109 } | |
110 | |
111 if (preview_path) | |
112 { | |
0 | 113 preview = gdk_pixbuf_new_from_file(preview_path, NULL); |
114 g_free(preview_path); | |
115 } | |
116 | |
117 if (is_archive) | |
118 del_directory(dec_path); | |
119 | |
120 g_free(dec_path); | |
121 | |
122 return preview; | |
123 } | |
124 | |
125 | |
126 static GdkPixbuf * | |
127 skin_get_thumbnail(const gchar * path) | |
128 { | |
129 GdkPixbuf *scaled = NULL; | |
130 GdkPixbuf *preview; | |
131 gchar *thumbname; | |
132 | |
133 g_return_val_if_fail(path != NULL, NULL); | |
134 | |
135 if (g_str_has_suffix(path, BMP_SKIN_THUMB_DIR_BASENAME)) | |
136 return NULL; | |
137 | |
138 thumbname = get_thumbnail_filename(path); | |
139 | |
140 if (g_file_test(thumbname, G_FILE_TEST_EXISTS)) { | |
141 scaled = gdk_pixbuf_new_from_file(thumbname, NULL); | |
142 g_free(thumbname); | |
143 return scaled; | |
144 } | |
145 | |
146 if (!(preview = skin_get_preview(path))) { | |
147 g_free(thumbname); | |
148 return NULL; | |
149 } | |
150 | |
151 scaled = gdk_pixbuf_scale_simple(preview, | |
152 THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, | |
153 GDK_INTERP_BILINEAR); | |
154 g_object_unref(preview); | |
155 | |
156 gdk_pixbuf_save(scaled, thumbname, "png", NULL, NULL); | |
157 g_free(thumbname); | |
158 | |
159 return scaled; | |
160 } | |
161 | |
162 static void | |
163 skinlist_add(const gchar * filename) | |
164 { | |
165 SkinNode *node; | |
166 gchar *basename; | |
167 | |
168 g_return_if_fail(filename != NULL); | |
169 | |
170 node = g_new0(SkinNode, 1); | |
171 node->path = g_strdup(filename); | |
172 | |
173 basename = g_path_get_basename(filename); | |
174 | |
175 if (file_is_archive(filename)) { | |
176 node->name = archive_basename(basename); | |
452
623391b6463b
[svn] Make "Unarchived Winamp 2.x skin" &c translatable.
nenolod
parents:
451
diff
changeset
|
177 node->desc = _("Archived Winamp 2.x skin"); |
0 | 178 g_free(basename); |
179 } | |
180 else { | |
181 node->name = basename; | |
452
623391b6463b
[svn] Make "Unarchived Winamp 2.x skin" &c translatable.
nenolod
parents:
451
diff
changeset
|
182 node->desc = _("Unarchived Winamp 2.x skin"); |
0 | 183 } |
184 | |
185 skinlist = g_list_prepend(skinlist, node); | |
186 } | |
187 | |
188 static gboolean | |
189 scan_skindir_func(const gchar * path, const gchar * basename, gpointer data) | |
190 { | |
191 if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) { | |
192 if (file_is_archive(path)) { | |
193 skinlist_add(path); | |
194 } | |
195 } | |
196 else if (g_file_test(path, G_FILE_TEST_IS_DIR)) { | |
197 skinlist_add(path); | |
198 } | |
199 | |
200 return FALSE; | |
201 } | |
202 | |
203 static void | |
204 scan_skindir(const gchar * path) | |
205 { | |
206 GError *error = NULL; | |
207 | |
208 g_return_if_fail(path != NULL); | |
209 | |
210 if (path[0] == '.') | |
211 return; | |
212 | |
213 if (!dir_foreach(path, scan_skindir_func, NULL, &error)) { | |
214 g_warning("Failed to open directory (%s): %s", path, error->message); | |
215 g_error_free(error); | |
216 return; | |
217 } | |
218 } | |
219 | |
220 static gint | |
221 skinlist_compare_func(gconstpointer a, gconstpointer b) | |
222 { | |
223 g_return_val_if_fail(a != NULL && SKIN_NODE(a)->name != NULL, 1); | |
224 g_return_val_if_fail(b != NULL && SKIN_NODE(b)->name != NULL, 1); | |
225 return strcasecmp(SKIN_NODE(a)->name, SKIN_NODE(b)->name); | |
226 } | |
227 | |
228 static void | |
229 skin_free_func(gpointer data) | |
230 { | |
231 g_return_if_fail(data != NULL); | |
232 g_free(SKIN_NODE(data)->name); | |
233 g_free(SKIN_NODE(data)->path); | |
234 g_free(data); | |
235 } | |
236 | |
237 | |
238 static void | |
239 skinlist_clear(void) | |
240 { | |
241 if (!skinlist) | |
242 return; | |
243 | |
244 g_list_foreach(skinlist, (GFunc) skin_free_func, NULL); | |
245 g_list_free(skinlist); | |
246 skinlist = NULL; | |
247 } | |
248 | |
249 void | |
250 skinlist_update(void) | |
251 { | |
252 gchar *skinsdir; | |
253 | |
254 skinlist_clear(); | |
255 | |
256 scan_skindir(bmp_paths[BMP_PATH_USER_SKIN_DIR]); | |
257 scan_skindir(DATA_DIR G_DIR_SEPARATOR_S BMP_SKIN_DIR_BASENAME); | |
258 | |
259 skinsdir = getenv("SKINSDIR"); | |
260 if (skinsdir) { | |
261 gchar **dir_list = g_strsplit(skinsdir, ":", 0); | |
262 gchar **dir; | |
263 | |
264 for (dir = dir_list; *dir; dir++) | |
265 scan_skindir(*dir); | |
266 g_strfreev(dir_list); | |
267 } | |
268 | |
269 skinlist = g_list_sort(skinlist, skinlist_compare_func); | |
270 | |
271 g_assert(skinlist != NULL); | |
272 } | |
273 | |
274 void | |
962
a341792533a6
[svn] - Let's not let the user press the skin refresh button while already refreshing ;)
nhjm449
parents:
674
diff
changeset
|
275 skin_view_update(GtkTreeView * treeview, GtkWidget * refresh_button) |
0 | 276 { |
277 GtkTreeSelection *selection = NULL; | |
278 GtkListStore *store; | |
279 GtkTreeIter iter, iter_current_skin; | |
642
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
280 gboolean have_current_skin = FALSE; |
0 | 281 GtkTreePath *path; |
282 | |
283 GdkPixbuf *thumbnail; | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
284 gchar *formattedname; |
0 | 285 gchar *name; |
286 GList *entry; | |
287 | |
288 gtk_widget_set_sensitive(GTK_WIDGET(treeview), FALSE); | |
962
a341792533a6
[svn] - Let's not let the user press the skin refresh button while already refreshing ;)
nhjm449
parents:
674
diff
changeset
|
289 gtk_widget_set_sensitive(GTK_WIDGET(refresh_button), FALSE); |
0 | 290 |
291 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); | |
292 | |
293 gtk_list_store_clear(store); | |
294 | |
295 skinlist_update(); | |
296 | |
297 for (entry = skinlist; entry; entry = g_list_next(entry)) { | |
298 thumbnail = skin_get_thumbnail(SKIN_NODE(entry->data)->path); | |
299 | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
300 formattedname = g_strdup_printf("<big><b>%s</b></big>\n<i>%s</i>", |
449 | 301 SKIN_NODE(entry->data)->name, SKIN_NODE(entry->data)->desc); |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
302 name = SKIN_NODE(entry->data)->name; |
0 | 303 |
304 gtk_list_store_append(store, &iter); | |
305 gtk_list_store_set(store, &iter, | |
306 SKIN_VIEW_COL_PREVIEW, thumbnail, | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
307 SKIN_VIEW_COL_FORMATTEDNAME, formattedname, |
0 | 308 SKIN_VIEW_COL_NAME, name, -1); |
639
9d2c175e458e
[svn] More skin-related fixups. One segfault fix by Michael Hanselmann and a fix by Daniel Drake to also display skins that lack a thumbnail.
chainsaw
parents:
453
diff
changeset
|
309 if (thumbnail) |
9d2c175e458e
[svn] More skin-related fixups. One segfault fix by Michael Hanselmann and a fix by Daniel Drake to also display skins that lack a thumbnail.
chainsaw
parents:
453
diff
changeset
|
310 g_object_unref(thumbnail); |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
311 g_free(formattedname); |
0 | 312 |
313 if (g_strstr_len(bmp_active_skin->path, | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
314 strlen(bmp_active_skin->path), name) ) { |
642
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
315 iter_current_skin = iter; |
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
316 have_current_skin = TRUE; |
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
317 } |
0 | 318 |
319 while (gtk_events_pending()) | |
320 gtk_main_iteration(); | |
321 } | |
322 | |
642
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
323 if (have_current_skin) { |
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
324 selection = gtk_tree_view_get_selection(treeview); |
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
325 gtk_tree_selection_select_iter(selection, &iter_current_skin); |
0 | 326 |
642
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
327 path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), |
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
328 &iter_current_skin); |
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
329 gtk_tree_view_scroll_to_cell(treeview, path, NULL, TRUE, 0.5, 0.5); |
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
330 gtk_tree_path_free(path); |
880cd914c3fd
[svn] Robustness fix; skinning dialog should deal with incorrect current skin setting gracefully. By external contributor Daniel Drake (Gentoo).
chainsaw
parents:
639
diff
changeset
|
331 } |
0 | 332 |
333 gtk_widget_set_sensitive(GTK_WIDGET(treeview), TRUE); | |
962
a341792533a6
[svn] - Let's not let the user press the skin refresh button while already refreshing ;)
nhjm449
parents:
674
diff
changeset
|
334 gtk_widget_set_sensitive(GTK_WIDGET(refresh_button), TRUE); |
0 | 335 } |
336 | |
337 | |
338 static void | |
339 skin_view_on_cursor_changed(GtkTreeView * treeview, | |
340 gpointer data) | |
341 { | |
342 GtkTreeModel *model; | |
343 GtkTreeSelection *selection; | |
344 GtkTreeIter iter; | |
345 | |
346 GList *node; | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
347 gchar *name; |
0 | 348 gchar *comp = NULL; |
349 | |
350 selection = gtk_tree_view_get_selection(treeview); | |
351 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) | |
352 return; | |
353 | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
354 gtk_tree_model_get(model, &iter, SKIN_VIEW_COL_NAME, &name, -1); |
450
dd84f79979b4
[svn] Dissect the pango markup using scanf and various string delimiter hacks.
nenolod
parents:
449
diff
changeset
|
355 |
0 | 356 for (node = skinlist; node; node = g_list_next(node)) { |
357 comp = SKIN_NODE(node->data)->path; | |
358 if (g_strrstr(comp, name)) | |
359 break; | |
360 } | |
361 | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
362 g_free(name); |
0 | 363 |
364 bmp_active_skin_load(comp); | |
365 } | |
366 | |
367 | |
368 void | |
369 skin_view_realize(GtkTreeView * treeview) | |
370 { | |
371 GtkListStore *store; | |
372 GtkTreeViewColumn *column; | |
373 GtkCellRenderer *renderer; | |
374 GtkTreeSelection *selection; | |
375 | |
376 gtk_widget_show_all(GTK_WIDGET(treeview)); | |
377 | |
378 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); | |
379 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); | |
380 | |
381 store = gtk_list_store_new(SKIN_VIEW_N_COLS, GDK_TYPE_PIXBUF, | |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
382 G_TYPE_STRING , G_TYPE_STRING); |
0 | 383 gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store)); |
384 | |
385 column = gtk_tree_view_column_new(); | |
386 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); | |
387 gtk_tree_view_column_set_spacing(column, 16); | |
388 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), | |
389 GTK_TREE_VIEW_COLUMN(column)); | |
390 | |
391 renderer = gtk_cell_renderer_pixbuf_new(); | |
392 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
393 gtk_tree_view_column_set_attributes(column, renderer, "pixbuf", | |
394 SKIN_VIEW_COL_PREVIEW, NULL); | |
395 | |
396 renderer = gtk_cell_renderer_text_new(); | |
397 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
449 | 398 gtk_tree_view_column_set_attributes(column, renderer, "markup", |
453
257a8d2047fb
[svn] added a new column in the treeview model to store the skin name
giacomo
parents:
452
diff
changeset
|
399 SKIN_VIEW_COL_FORMATTEDNAME, NULL); |
0 | 400 |
401 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); | |
402 gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); | |
403 | |
404 g_signal_connect(treeview, "cursor-changed", | |
405 G_CALLBACK(skin_view_on_cursor_changed), NULL); | |
406 } |