1541
|
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
|
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20 */
|
|
21
|
|
22 #ifdef HAVE_CONFIG_H
|
|
23 # include "config.h"
|
|
24 #endif
|
|
25
|
|
26 /* TODO: enforce default sizes! */
|
|
27
|
|
28 #include <glib.h>
|
|
29 #include <stdio.h>
|
|
30 #include <stdlib.h>
|
|
31 #include <string.h>
|
|
32 #include <ctype.h>
|
|
33
|
|
34 #include "equalizer.h"
|
|
35 #include "main.h"
|
|
36 #include "ui_playlist.h"
|
|
37 #include "skin.h"
|
|
38 #include "skinwin.h"
|
|
39 #include "util.h"
|
|
40
|
|
41 #include "debug.h"
|
|
42
|
|
43 #include <gdk/gdkx.h>
|
|
44 #include <X11/Xlib.h>
|
|
45
|
|
46 #define EXTENSION_TARGETS 7
|
|
47
|
|
48 static gchar *ext_targets[EXTENSION_TARGETS] = { "bmp", "xpm", "png", "svg",
|
|
49 "gif", "jpg", "jpeg" };
|
|
50
|
|
51 struct _SkinPixmapIdMapping {
|
|
52 SkinPixmapId id;
|
|
53 const gchar *name;
|
|
54 const gchar *alt_name;
|
|
55 gint width, height;
|
|
56 };
|
|
57
|
|
58 struct _SkinMaskInfo {
|
|
59 gint width, height;
|
|
60 gchar *inistr;
|
|
61 };
|
|
62
|
|
63 typedef struct _SkinPixmapIdMapping SkinPixmapIdMapping;
|
|
64 typedef struct _SkinMaskInfo SkinMaskInfo;
|
|
65
|
|
66
|
|
67 Skin *bmp_active_skin = NULL;
|
|
68
|
|
69 static gint skin_current_num;
|
|
70
|
|
71 static SkinMaskInfo skin_mask_info[] = {
|
|
72 {275, 116, "Normal"},
|
|
73 {275, 16, "WindowShade"},
|
|
74 {275, 116, "Equalizer"},
|
|
75 {275, 16, "EqualizerWS"}
|
|
76 };
|
|
77
|
|
78 static SkinPixmapIdMapping skin_pixmap_id_map[] = {
|
|
79 {SKIN_MAIN, "main", NULL, 0, 0},
|
|
80 {SKIN_CBUTTONS, "cbuttons", NULL, 0, 0},
|
|
81 {SKIN_SHUFREP, "shufrep", NULL, 0, 0},
|
|
82 {SKIN_TEXT, "text", NULL, 0, 0},
|
|
83 {SKIN_TITLEBAR, "titlebar", NULL, 0, 0},
|
|
84 {SKIN_VOLUME, "volume", NULL, 0, 0},
|
|
85 {SKIN_BALANCE, "balance", "volume", 0, 0},
|
|
86 {SKIN_MONOSTEREO, "monoster", NULL, 0, 0},
|
|
87 {SKIN_PLAYPAUSE, "playpaus", NULL, 0, 0},
|
|
88 {SKIN_NUMBERS, "nums_ex", "numbers", 0, 0},
|
|
89 {SKIN_POSBAR, "posbar", NULL, 0, 0},
|
|
90 {SKIN_EQMAIN, "eqmain", NULL, 0, 0},
|
|
91 {SKIN_PLEDIT, "pledit", NULL, 0, 0},
|
|
92 {SKIN_EQ_EX, "eq_ex", NULL, 0, 0}
|
|
93 };
|
|
94
|
|
95 static guint skin_pixmap_id_map_size = G_N_ELEMENTS(skin_pixmap_id_map);
|
|
96
|
|
97 static const guchar skin_default_viscolor[24][3] = {
|
|
98 {9, 34, 53},
|
|
99 {10, 18, 26},
|
|
100 {0, 54, 108},
|
|
101 {0, 58, 116},
|
|
102 {0, 62, 124},
|
|
103 {0, 66, 132},
|
|
104 {0, 70, 140},
|
|
105 {0, 74, 148},
|
|
106 {0, 78, 156},
|
|
107 {0, 82, 164},
|
|
108 {0, 86, 172},
|
|
109 {0, 92, 184},
|
|
110 {0, 98, 196},
|
|
111 {0, 104, 208},
|
|
112 {0, 110, 220},
|
|
113 {0, 116, 232},
|
|
114 {0, 122, 244},
|
|
115 {0, 128, 255},
|
|
116 {0, 128, 255},
|
|
117 {0, 104, 208},
|
|
118 {0, 80, 160},
|
|
119 {0, 56, 112},
|
|
120 {0, 32, 64},
|
|
121 {200, 200, 200}
|
|
122 };
|
|
123
|
|
124 static GdkBitmap *
|
|
125 skin_create_transparent_mask(const gchar *,
|
|
126 const gchar *,
|
|
127 const gchar *,
|
|
128 GdkWindow *,
|
|
129 gint, gint);
|
|
130
|
|
131 static void
|
|
132 skin_setup_masks(Skin * skin);
|
|
133
|
|
134 static void
|
|
135 skin_set_default_vis_color(Skin * skin);
|
|
136
|
|
137
|
|
138 void
|
|
139 skin_lock(Skin * skin)
|
|
140 {
|
|
141 g_mutex_lock(skin->lock);
|
|
142 }
|
|
143
|
|
144 void
|
|
145 skin_unlock(Skin * skin)
|
|
146 {
|
|
147 g_mutex_unlock(skin->lock);
|
|
148 }
|
|
149
|
|
150 gboolean
|
|
151 bmp_active_skin_reload(void)
|
|
152 {
|
|
153 return bmp_active_skin_load(bmp_active_skin->path);
|
|
154 }
|
|
155
|
|
156 gboolean
|
|
157 bmp_active_skin_load(const gchar * path)
|
|
158 {
|
|
159 g_return_val_if_fail(bmp_active_skin != NULL, FALSE);
|
|
160
|
|
161 memset(&bmp_active_skin->properties, 0, sizeof(SkinProperties));
|
|
162
|
|
163 if (!skin_load(bmp_active_skin, path))
|
|
164 return FALSE;
|
|
165
|
|
166 skin_setup_masks(bmp_active_skin);
|
|
167
|
|
168 if (cfg.playlist_transparent)
|
|
169 {
|
|
170 if (rootpix != NULL)
|
|
171 g_object_unref(rootpix);
|
|
172
|
|
173 rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(),
|
|
174 skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG));
|
|
175 }
|
|
176
|
|
177 draw_main_window(TRUE);
|
|
178 draw_playlist_window(TRUE);
|
|
179 draw_equalizer_window(TRUE);
|
|
180
|
|
181 vis_set_window(mainwin_vis, mainwin->window);
|
|
182 playlistwin_update_list();
|
|
183
|
|
184 return TRUE;
|
|
185 }
|
|
186
|
|
187 void
|
|
188 skin_pixmap_free(SkinPixmap * p)
|
|
189 {
|
|
190 g_return_if_fail(p != NULL);
|
|
191 g_return_if_fail(p->pixmap != NULL);
|
|
192
|
|
193 g_object_unref(p->pixmap);
|
|
194 p->pixmap = NULL;
|
|
195 }
|
|
196
|
|
197 Skin *
|
|
198 skin_new(void)
|
|
199 {
|
|
200 Skin *skin;
|
|
201 skin = g_new0(Skin, 1);
|
|
202 skin->lock = g_mutex_new();
|
|
203 return skin;
|
|
204 }
|
|
205
|
|
206 void
|
|
207 skin_free(Skin * skin)
|
|
208 {
|
|
209 gint i;
|
|
210
|
|
211 g_return_if_fail(skin != NULL);
|
|
212
|
|
213 skin_lock(skin);
|
|
214
|
|
215 for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
|
|
216 skin_pixmap_free(&skin->pixmaps[i]);
|
|
217
|
|
218 for (i = 0; i < SKIN_PIXMAP_COUNT; i++) {
|
|
219 if (skin->masks[i])
|
|
220 g_object_unref(skin->masks[i]);
|
|
221
|
|
222 skin->masks[i] = NULL;
|
|
223 }
|
|
224
|
|
225 skin_set_default_vis_color(skin);
|
|
226 skin_unlock(skin);
|
|
227 }
|
|
228
|
|
229 void
|
|
230 skin_destroy(Skin * skin)
|
|
231 {
|
|
232 g_return_if_fail(skin != NULL);
|
|
233 skin_free(skin);
|
|
234 g_mutex_free(skin->lock);
|
|
235 g_free(skin);
|
|
236 }
|
|
237
|
|
238 const SkinPixmapIdMapping *
|
|
239 skin_pixmap_id_lookup(guint id)
|
|
240 {
|
|
241 guint i;
|
|
242
|
|
243 for (i = 0; i < skin_pixmap_id_map_size; i++) {
|
|
244 if (id == skin_pixmap_id_map[i].id) {
|
|
245 return &skin_pixmap_id_map[i];
|
|
246 }
|
|
247 }
|
|
248
|
|
249 return NULL;
|
|
250 }
|
|
251
|
|
252 const gchar *
|
|
253 skin_pixmap_id_to_name(SkinPixmapId id)
|
|
254 {
|
|
255 guint i;
|
|
256
|
|
257 for (i = 0; i < skin_pixmap_id_map_size; i++) {
|
|
258 if (id == skin_pixmap_id_map[i].id)
|
|
259 return skin_pixmap_id_map[i].name;
|
|
260 }
|
|
261 return NULL;
|
|
262 }
|
|
263
|
|
264 static void
|
|
265 skin_set_default_vis_color(Skin * skin)
|
|
266 {
|
|
267 memcpy(skin->vis_color, skin_default_viscolor,
|
|
268 sizeof(skin_default_viscolor));
|
|
269 }
|
|
270
|
|
271 /*
|
|
272 * I have rewritten this to take an array of possible targets,
|
|
273 * once we find a matching target we now return, instead of loop
|
|
274 * recursively. This allows for us to support many possible format
|
|
275 * targets for our skinning engine than just the original winamp
|
|
276 * formats.
|
|
277 *
|
|
278 * -- nenolod, 16 January 2006
|
|
279 */
|
|
280 gchar *
|
|
281 skin_pixmap_locate(const gchar * dirname, gchar ** basenames)
|
|
282 {
|
|
283 gchar *filename;
|
|
284 gint i;
|
|
285
|
|
286 for (i = 0; basenames[i]; i++)
|
|
287 if (!(filename = find_file_recursively(dirname, basenames[i])))
|
|
288 g_free(filename);
|
|
289 else
|
|
290 return filename;
|
|
291
|
|
292 /* can't find any targets -- sorry */
|
|
293 return NULL;
|
|
294 }
|
|
295
|
|
296 /* FIXME: this function is temporary. It will be removed when the skinning system
|
|
297 uses GdkPixbuf in place of GdkPixmap */
|
|
298
|
|
299 static GdkPixmap *
|
|
300 pixmap_new_from_file(const gchar * filename)
|
|
301 {
|
|
302 GdkPixbuf *pixbuf;
|
|
303 GdkPixmap *pixmap;
|
|
304 gint width, height;
|
|
305
|
|
306 if (!(pixbuf = gdk_pixbuf_new_from_file(filename, NULL)))
|
|
307 return NULL;
|
|
308
|
|
309 width = gdk_pixbuf_get_width(pixbuf);
|
|
310 height = gdk_pixbuf_get_height(pixbuf);
|
|
311
|
|
312 if (!(pixmap = gdk_pixmap_new(mainwin->window, width, height,
|
|
313 gdk_rgb_get_visual()->depth))) {
|
|
314 g_object_unref(pixbuf);
|
|
315 return NULL;
|
|
316 }
|
|
317
|
|
318 gdk_pixbuf_render_to_drawable(pixbuf, pixmap, mainwin_gc, 0, 0, 0, 0,
|
|
319 width, height, GDK_RGB_DITHER_MAX, 0, 0);
|
|
320 g_object_unref(pixbuf);
|
|
321
|
|
322 return pixmap;
|
|
323 }
|
|
324
|
|
325 static gboolean
|
|
326 skin_load_pixmap_id(Skin * skin, SkinPixmapId id, const gchar * path_p)
|
|
327 {
|
|
328 const gchar *path;
|
|
329 gchar *filename;
|
|
330 gint width, height;
|
|
331 const SkinPixmapIdMapping *pixmap_id_mapping;
|
|
332 GdkPixmap *gpm;
|
|
333 SkinPixmap *pm = NULL;
|
|
334 gchar *basenames[EXTENSION_TARGETS * 2 + 1]; /* alternate basenames */
|
|
335 gint i, y;
|
|
336
|
|
337 g_return_val_if_fail(skin != NULL, FALSE);
|
|
338 g_return_val_if_fail(id < SKIN_PIXMAP_COUNT, FALSE);
|
|
339
|
|
340 pixmap_id_mapping = skin_pixmap_id_lookup(id);
|
|
341 g_return_val_if_fail(pixmap_id_mapping != NULL, FALSE);
|
|
342
|
|
343 memset(&basenames, 0, sizeof(basenames));
|
|
344
|
|
345 for (i = 0, y = 0; i < EXTENSION_TARGETS; i++, y++)
|
|
346 {
|
|
347 basenames[y] = g_strdup_printf("%s.%s", pixmap_id_mapping->name,
|
|
348 ext_targets[i]);
|
|
349
|
|
350 if (pixmap_id_mapping->alt_name)
|
|
351 basenames[++y] = g_strdup_printf("%s.%s",
|
|
352 pixmap_id_mapping->alt_name, ext_targets[i]);
|
|
353 }
|
|
354
|
|
355 path = path_p ? path_p : skin->path;
|
|
356 filename = skin_pixmap_locate(path, basenames);
|
|
357
|
|
358 for (i = 0; basenames[i] != NULL; i++)
|
|
359 {
|
|
360 g_free(basenames[i]);
|
|
361 basenames[i] = NULL;
|
|
362 }
|
|
363
|
|
364 if (!(gpm = pixmap_new_from_file(filename))) {
|
|
365 g_warning("loading of %s failed", filename);
|
|
366 g_free(filename);
|
|
367 return FALSE;
|
|
368 }
|
|
369
|
|
370 g_free(filename);
|
|
371
|
|
372 gdk_window_get_size(gpm, &width, &height);
|
|
373 pm = &skin->pixmaps[id];
|
|
374 pm->pixmap = gpm;
|
|
375 pm->width = width;
|
|
376 pm->height = height;
|
|
377 pm->current_width = width;
|
|
378 pm->current_height = height;
|
|
379
|
|
380 return TRUE;
|
|
381 }
|
|
382
|
|
383 void
|
|
384 skin_mask_create(Skin * skin,
|
|
385 const gchar * path,
|
|
386 gint id,
|
|
387 GdkWindow * window)
|
|
388 {
|
|
389 skin->masks[id] =
|
|
390 skin_create_transparent_mask(path, "region.txt",
|
|
391 skin_mask_info[id].inistr, window,
|
|
392 skin_mask_info[id].width,
|
|
393 skin_mask_info[id].height);
|
|
394 }
|
|
395
|
|
396 static void
|
|
397 skin_setup_masks(Skin * skin)
|
|
398 {
|
|
399 GdkBitmap *mask;
|
|
400
|
|
401 if (cfg.show_wm_decorations)
|
|
402 return;
|
|
403
|
|
404 if (cfg.player_visible) {
|
|
405 mask = skin_get_mask(skin, SKIN_MASK_MAIN + cfg.player_shaded);
|
|
406 gtk_widget_shape_combine_mask(mainwin, mask, 0, 0);
|
|
407 }
|
|
408
|
|
409 mask = skin_get_mask(skin, SKIN_MASK_EQ + cfg.equalizer_shaded);
|
|
410 gtk_widget_shape_combine_mask(equalizerwin, mask, 0, 0);
|
|
411 }
|
|
412
|
|
413 static GdkBitmap *
|
|
414 create_default_mask(GdkWindow * parent, gint w, gint h)
|
|
415 {
|
|
416 GdkBitmap *ret;
|
|
417 GdkGC *gc;
|
|
418 GdkColor pattern;
|
|
419
|
|
420 ret = gdk_pixmap_new(parent, w, h, 1);
|
|
421 gc = gdk_gc_new(ret);
|
|
422 pattern.pixel = 1;
|
|
423 gdk_gc_set_foreground(gc, &pattern);
|
|
424 gdk_draw_rectangle(ret, gc, TRUE, 0, 0, w, h);
|
|
425 gdk_gc_destroy(gc);
|
|
426
|
|
427 return ret;
|
|
428 }
|
|
429
|
|
430 static void
|
|
431 skin_query_color(GdkColormap * cm, GdkColor * c)
|
|
432 {
|
|
433 XColor xc = { 0,0,0,0,0,0 };
|
|
434
|
|
435 xc.pixel = c->pixel;
|
|
436 XQueryColor(GDK_COLORMAP_XDISPLAY(cm), GDK_COLORMAP_XCOLORMAP(cm), &xc);
|
|
437 c->red = xc.red;
|
|
438 c->green = xc.green;
|
|
439 c->blue = xc.blue;
|
|
440 }
|
|
441
|
|
442 static glong
|
|
443 skin_calc_luminance(GdkColor * c)
|
|
444 {
|
|
445 return (0.212671 * c->red + 0.715160 * c->green + 0.072169 * c->blue);
|
|
446 }
|
|
447
|
|
448 static void
|
|
449 skin_get_textcolors(GdkPixmap * text, GdkColor * bgc, GdkColor * fgc)
|
|
450 {
|
|
451 /*
|
|
452 * Try to extract reasonable background and foreground colors
|
|
453 * from the font pixmap
|
|
454 */
|
|
455
|
|
456 GdkImage *gi;
|
|
457 GdkColormap *cm;
|
|
458 gint i;
|
|
459
|
|
460 g_return_if_fail(text != NULL);
|
|
461
|
|
462 /* Get the first line of text */
|
|
463 gi = gdk_drawable_get_image(text, 0, 0, 152, 6);
|
|
464 cm = gdk_window_get_colormap(playlistwin->window);
|
|
465 g_return_if_fail(GDK_IS_WINDOW(playlistwin->window));
|
|
466
|
|
467 for (i = 0; i < 6; i++) {
|
|
468 GdkColor c;
|
|
469 gint x;
|
|
470 glong d, max_d;
|
|
471
|
|
472 /* Get a pixel from the middle of the space character */
|
|
473 bgc[i].pixel = gdk_image_get_pixel(gi, 151, i);
|
|
474 skin_query_color(cm, &bgc[i]);
|
|
475
|
|
476 max_d = 0;
|
|
477 for (x = 1; x < 150; x++) {
|
|
478 c.pixel = gdk_image_get_pixel(gi, x, i);
|
|
479 skin_query_color(cm, &c);
|
|
480
|
|
481 d = labs(skin_calc_luminance(&c) - skin_calc_luminance(&bgc[i]));
|
|
482 if (d > max_d) {
|
|
483 memcpy(&fgc[i], &c, sizeof(GdkColor));
|
|
484 max_d = d;
|
|
485 }
|
|
486 }
|
|
487 }
|
|
488 gdk_image_destroy(gi);
|
|
489 }
|
|
490
|
|
491 gboolean
|
|
492 init_skins(const gchar * path)
|
|
493 {
|
|
494 bmp_active_skin = skin_new();
|
|
495
|
|
496 if (!bmp_active_skin_load(path)) {
|
|
497 /* FIXME: Oddly, g_message() causes a crash if path is NULL on
|
|
498 * Solaris (see bug #165) */
|
|
499 if (path)
|
|
500 g_message("Unable to load skin (%s), trying default...", path);
|
|
501
|
|
502 /* can't load configured skin, retry with default */
|
|
503 if (!bmp_active_skin_load(BMP_DEFAULT_SKIN_PATH)) {
|
|
504 g_message("Unable to load default skin (%s)! Giving up.",
|
|
505 BMP_DEFAULT_SKIN_PATH);
|
|
506 return FALSE;
|
|
507 }
|
|
508 }
|
|
509
|
|
510 if (cfg.random_skin_on_play)
|
|
511 skinlist_update();
|
|
512
|
|
513 return TRUE;
|
|
514 }
|
|
515
|
|
516 /*
|
|
517 * Opens and parses a skin's hints file.
|
|
518 * Hints files are somewhat like "scripts" in Winamp3/5.
|
|
519 * We'll probably add scripts to it next.
|
|
520 */
|
|
521 void
|
|
522 skin_parse_hints(Skin * skin, gchar *path_p)
|
|
523 {
|
|
524 gchar *filename, *tmp;
|
|
525
|
|
526 path_p = path_p ? path_p : skin->path;
|
|
527
|
|
528 filename = find_file_recursively(path_p, "skin.hints");
|
|
529
|
|
530 if (filename == NULL)
|
|
531 return;
|
|
532
|
|
533 #if 0
|
|
534 skin->description = read_ini_string(filename, "skin", "skinDescription");
|
|
535 #endif
|
|
536
|
|
537 tmp = read_ini_string(filename, "skin", "mainwinOthertext");
|
|
538
|
|
539 if (tmp != NULL)
|
|
540 skin->properties.mainwin_othertext = atoi(tmp);
|
|
541 }
|
|
542
|
|
543 static guint
|
|
544 hex_chars_to_int(gchar hi, gchar lo)
|
|
545 {
|
|
546 /*
|
|
547 * Converts a value in the range 0x00-0xFF
|
|
548 * to a integer in the range 0-65535
|
|
549 */
|
|
550 gchar str[3];
|
|
551
|
|
552 str[0] = hi;
|
|
553 str[1] = lo;
|
|
554 str[2] = 0;
|
|
555
|
|
556 return (CLAMP(strtol(str, NULL, 16), 0, 0xFF) << 8);
|
|
557 }
|
|
558
|
|
559 GdkColor *
|
|
560 skin_load_color(const gchar * path, const gchar * file,
|
|
561 const gchar * section, const gchar * key,
|
|
562 gchar * default_hex)
|
|
563 {
|
|
564 gchar *filename, *value;
|
|
565 GdkColor *color = NULL;
|
|
566
|
|
567 filename = find_file_recursively(path, file);
|
|
568 if (filename || default_hex) {
|
|
569 if (filename) {
|
|
570 value = read_ini_string(filename, section, key);
|
|
571 if (value == NULL) {
|
|
572 value = g_strdup(default_hex);
|
|
573 }
|
|
574 } else {
|
|
575 value = g_strdup(default_hex);
|
|
576 }
|
|
577 if (value) {
|
|
578 gchar *ptr = value;
|
|
579 gint len;
|
|
580
|
|
581 color = g_new0(GdkColor, 1);
|
|
582 g_strstrip(value);
|
|
583
|
|
584 if (value[0] == '#')
|
|
585 ptr++;
|
|
586 len = strlen(ptr);
|
|
587 /*
|
|
588 * The handling of incomplete values is done this way
|
|
589 * to maximize winamp compatibility
|
|
590 */
|
|
591 if (len >= 6) {
|
|
592 color->red = hex_chars_to_int(*ptr, *(ptr + 1));
|
|
593 ptr += 2;
|
|
594 }
|
|
595 if (len >= 4) {
|
|
596 color->green = hex_chars_to_int(*ptr, *(ptr + 1));
|
|
597 ptr += 2;
|
|
598 }
|
|
599 if (len >= 2)
|
|
600 color->blue = hex_chars_to_int(*ptr, *(ptr + 1));
|
|
601
|
|
602 gdk_color_alloc(gdk_window_get_colormap(playlistwin->window),
|
|
603 color);
|
|
604 g_free(value);
|
|
605 }
|
|
606 if (filename)
|
|
607 g_free(filename);
|
|
608 }
|
|
609 return color;
|
|
610 }
|
|
611
|
|
612
|
|
613
|
|
614 GdkBitmap *
|
|
615 skin_create_transparent_mask(const gchar * path,
|
|
616 const gchar * file,
|
|
617 const gchar * section,
|
|
618 GdkWindow * window,
|
|
619 gint width,
|
|
620 gint height)
|
|
621 {
|
|
622 GdkBitmap *mask = NULL;
|
|
623 GdkGC *gc = NULL;
|
|
624 GdkColor pattern;
|
|
625 GdkPoint *gpoints;
|
|
626
|
|
627 gchar *filename = NULL;
|
|
628 gboolean created_mask = FALSE;
|
|
629 GArray *num, *point;
|
|
630 guint i, j;
|
|
631 gint k;
|
|
632
|
|
633 if (path)
|
|
634 filename = find_file_recursively(path, file);
|
|
635
|
|
636 /* filename will be null if path wasn't set */
|
|
637 if (!filename) {
|
|
638 return create_default_mask(window, width, height);
|
|
639 }
|
|
640
|
|
641 if ((num = read_ini_array(filename, section, "NumPoints")) == NULL) {
|
|
642 g_free(filename);
|
|
643 return NULL;
|
|
644 }
|
|
645
|
|
646 if ((point = read_ini_array(filename, section, "PointList")) == NULL) {
|
|
647 g_array_free(num, TRUE);
|
|
648 g_free(filename);
|
|
649 return NULL;
|
|
650 }
|
|
651
|
|
652 mask = gdk_pixmap_new(window, width, height, 1);
|
|
653 gc = gdk_gc_new(mask);
|
|
654
|
|
655 pattern.pixel = 0;
|
|
656 gdk_gc_set_foreground(gc, &pattern);
|
|
657 gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
|
|
658 pattern.pixel = 1;
|
|
659 gdk_gc_set_foreground(gc, &pattern);
|
|
660
|
|
661 j = 0;
|
|
662 for (i = 0; i < num->len; i++) {
|
|
663 if ((int)(point->len - j) >= (g_array_index(num, gint, i) * 2)) {
|
|
664 created_mask = TRUE;
|
|
665 gpoints = g_new(GdkPoint, g_array_index(num, gint, i));
|
|
666 for (k = 0; k < g_array_index(num, gint, i); k++) {
|
|
667 gpoints[k].x = g_array_index(point, gint, j + k * 2);
|
|
668 gpoints[k].y = g_array_index(point, gint, j + k * 2 + 1);
|
|
669 }
|
|
670 j += k * 2;
|
|
671 gdk_draw_polygon(mask, gc, TRUE, gpoints,
|
|
672 g_array_index(num, gint, i));
|
|
673 g_free(gpoints);
|
|
674 }
|
|
675 }
|
|
676 g_array_free(num, TRUE);
|
|
677 g_array_free(point, TRUE);
|
|
678 g_free(filename);
|
|
679
|
|
680 if (!created_mask)
|
|
681 gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
|
|
682
|
|
683 gdk_gc_destroy(gc);
|
|
684
|
|
685 return mask;
|
|
686 }
|
|
687
|
|
688 void
|
|
689 skin_load_viscolor(Skin * skin, const gchar * path, const gchar * basename)
|
|
690 {
|
|
691 FILE *file;
|
|
692 gint i, c;
|
|
693 gchar line[256], *filename;
|
|
694 GArray *a;
|
|
695
|
|
696 g_return_if_fail(skin != NULL);
|
|
697 g_return_if_fail(path != NULL);
|
|
698 g_return_if_fail(basename != NULL);
|
|
699
|
|
700 skin_set_default_vis_color(skin);
|
|
701
|
|
702 filename = find_file_recursively(path, basename);
|
|
703 if (!filename)
|
|
704 return;
|
|
705
|
|
706 if (!(file = fopen(filename, "r"))) {
|
|
707 g_free(filename);
|
|
708 return;
|
|
709 }
|
|
710
|
|
711 g_free(filename);
|
|
712
|
|
713 for (i = 0; i < 24; i++) {
|
|
714 if (fgets(line, 255, file)) {
|
|
715 a = string_to_garray(line);
|
|
716 if (a->len > 2) {
|
|
717 for (c = 0; c < 3; c++)
|
|
718 skin->vis_color[i][c] = g_array_index(a, gint, c);
|
|
719 }
|
|
720 g_array_free(a, TRUE);
|
|
721 }
|
|
722 else
|
|
723 break;
|
|
724 }
|
|
725
|
|
726 fclose(file);
|
|
727 }
|
|
728
|
|
729 #if 0
|
|
730 static void
|
|
731 skin_numbers_generate_dash(Skin * skin)
|
|
732 {
|
|
733 GdkGC *gc;
|
|
734 GdkPixmap *pixmap;
|
|
735 SkinPixmap *numbers;
|
|
736
|
|
737 g_return_if_fail(skin != NULL);
|
|
738
|
|
739 numbers = &skin->pixmaps[SKIN_NUMBERS];
|
|
740 if (!numbers->pixmap || numbers->current_width < 99)
|
|
741 return;
|
|
742
|
|
743 gc = gdk_gc_new(numbers->pixmap);
|
|
744 pixmap = gdk_pixmap_new(mainwin->window, 108,
|
|
745 numbers->current_height,
|
|
746 -1);
|
|
747
|
|
748 skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 0, 0, 0, 0, 99, 13);
|
|
749 skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 90, 0, 99, 0, 9, 13);
|
|
750 skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 20, 6, 101, 6, 5, 1);
|
|
751
|
|
752 g_object_unref(numbers->pixmap);
|
|
753 g_object_unref(gc);
|
|
754
|
|
755 numbers->pixmap = pixmap;
|
|
756 numbers->current_width = 108;
|
|
757 }
|
|
758 #endif
|
|
759
|
|
760 static void
|
|
761 skin_load_cursor(Skin * skin, const gchar * dirname)
|
|
762 {
|
|
763 const gchar * basename = "normal.cur";
|
|
764 gchar * filename = NULL;
|
|
765 GdkPixbuf * cursor_pixbuf = NULL;
|
|
766 GdkPixbufAnimation * cursor_animated = NULL;
|
|
767 GdkCursor * cursor_gdk = NULL;
|
|
768 GError * error = NULL;
|
|
769
|
|
770 filename = find_file_recursively(dirname, basename);
|
|
771
|
|
772 if (filename && cfg.custom_cursors) {
|
|
773 cursor_animated = gdk_pixbuf_animation_new_from_file(filename, &error);
|
|
774 cursor_pixbuf = gdk_pixbuf_animation_get_static_image(cursor_animated);
|
|
775 cursor_gdk = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
|
|
776 cursor_pixbuf, 0, 0);
|
|
777 } else {
|
|
778 cursor_gdk = gdk_cursor_new(GDK_LEFT_PTR);
|
|
779 }
|
|
780
|
|
781 gdk_window_set_cursor(mainwin->window, cursor_gdk);
|
|
782 gdk_window_set_cursor(playlistwin->window, cursor_gdk);
|
|
783 gdk_window_set_cursor(equalizerwin->window, cursor_gdk);
|
|
784 gdk_cursor_unref(cursor_gdk);
|
|
785 }
|
|
786
|
|
787 static void
|
|
788 skin_load_pixmaps(Skin * skin, const gchar * path)
|
|
789 {
|
|
790 GdkPixmap *text_pm;
|
|
791 guint i;
|
|
792
|
|
793 for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
|
|
794 skin_load_pixmap_id(skin, i, path);
|
|
795
|
|
796 text_pm = skin->pixmaps[SKIN_TEXT].pixmap;
|
|
797
|
|
798 if (text_pm)
|
|
799 skin_get_textcolors(text_pm, skin->textbg, skin->textfg);
|
|
800
|
|
801 #if 0
|
|
802 if (skin->pixmaps[SKIN_NUMBERS].pixmap)
|
|
803 skin_numbers_generate_dash(skin);
|
|
804 #endif
|
|
805
|
|
806 skin->colors[SKIN_PLEDIT_NORMAL] =
|
|
807 skin_load_color(path, "pledit.txt", "text", "normal", "#2499ff");
|
|
808 skin->colors[SKIN_PLEDIT_CURRENT] =
|
|
809 skin_load_color(path, "pledit.txt", "text", "current", "#ffeeff");
|
|
810 skin->colors[SKIN_PLEDIT_NORMALBG] =
|
|
811 skin_load_color(path, "pledit.txt", "text", "normalbg", "#0a120a");
|
|
812 skin->colors[SKIN_PLEDIT_SELECTEDBG] =
|
|
813 skin_load_color(path, "pledit.txt", "text", "selectedbg", "#0a124a");
|
|
814
|
|
815 skin_mask_create(skin, path, SKIN_MASK_MAIN, mainwin->window);
|
|
816 skin_mask_create(skin, path, SKIN_MASK_MAIN_SHADE, mainwin->window);
|
|
817
|
|
818 skin_mask_create(skin, path, SKIN_MASK_EQ, equalizerwin->window);
|
|
819 skin_mask_create(skin, path, SKIN_MASK_EQ_SHADE, equalizerwin->window);
|
|
820
|
|
821 skin_load_viscolor(skin, path, "viscolor.txt");
|
|
822 }
|
|
823
|
|
824 static gboolean
|
|
825 skin_load_nolock(Skin * skin, const gchar * path, gboolean force)
|
|
826 {
|
|
827 gchar *cpath;
|
|
828
|
|
829 g_return_val_if_fail(skin != NULL, FALSE);
|
|
830 g_return_val_if_fail(path != NULL, FALSE);
|
|
831 REQUIRE_LOCK(skin->lock);
|
|
832
|
|
833 if (!g_file_test(path, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_DIR))
|
|
834 return FALSE;
|
|
835
|
|
836 if (!force) {
|
|
837 if (skin->path)
|
|
838 if (!strcmp(skin->path, path))
|
|
839 return FALSE;
|
|
840 }
|
|
841
|
|
842 skin_current_num++;
|
|
843
|
|
844 skin->path = g_strdup(path);
|
|
845
|
|
846 if (!file_is_archive(path)) {
|
|
847 skin_load_pixmaps(skin, path);
|
|
848 skin_load_cursor(skin, path);
|
|
849
|
|
850 /* Parse the hints for this skin. */
|
|
851 skin_parse_hints(skin, NULL);
|
|
852
|
|
853 return TRUE;
|
|
854 }
|
|
855
|
|
856 if (!(cpath = archive_decompress(path))) {
|
|
857 g_message("Unable to extract skin archive (%s)", path);
|
|
858 return FALSE;
|
|
859 }
|
|
860
|
|
861 skin_load_pixmaps(skin, cpath);
|
|
862 skin_load_cursor(skin, cpath);
|
|
863
|
|
864 /* Parse the hints for this skin. */
|
|
865 skin_parse_hints(skin, cpath);
|
|
866
|
|
867 del_directory(cpath);
|
|
868 g_free(cpath);
|
|
869
|
|
870 return TRUE;
|
|
871 }
|
|
872
|
|
873 void
|
|
874 skin_install_skin(const gchar * path)
|
|
875 {
|
|
876 gchar *command;
|
|
877
|
|
878 g_return_if_fail(path != NULL);
|
|
879
|
|
880 command = g_strdup_printf("cp %s %s", path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
|
|
881 if (system(command)) {
|
|
882 g_message("Unable to install skin (%s) into user directory (%s)",
|
|
883 path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
|
|
884 }
|
|
885 g_free(command);
|
|
886 }
|
|
887
|
|
888
|
|
889 gboolean
|
|
890 skin_load(Skin * skin, const gchar * path)
|
|
891 {
|
|
892 gboolean error;
|
|
893
|
|
894 g_return_val_if_fail(skin != NULL, FALSE);
|
|
895
|
|
896 if (!path)
|
|
897 return FALSE;
|
|
898
|
|
899 skin_lock(skin);
|
|
900 error = skin_load_nolock(skin, path, FALSE);
|
|
901 skin_unlock(skin);
|
|
902
|
|
903 return error;
|
|
904 }
|
|
905
|
|
906 gboolean
|
|
907 skin_reload_forced(void)
|
|
908 {
|
|
909 gboolean error;
|
|
910
|
|
911 skin_lock(bmp_active_skin);
|
|
912 error = skin_load_nolock(bmp_active_skin, bmp_active_skin->path, TRUE);
|
|
913 skin_unlock(bmp_active_skin);
|
|
914
|
|
915 return error;
|
|
916 }
|
|
917
|
|
918 void
|
|
919 skin_reload(Skin * skin)
|
|
920 {
|
|
921 g_return_if_fail(skin != NULL);
|
|
922 skin_load_nolock(skin, skin->path, TRUE);
|
|
923 }
|
|
924
|
|
925
|
|
926 static SkinPixmap *
|
|
927 skin_get_pixmap(Skin * skin, SkinPixmapId map_id)
|
|
928 {
|
|
929 g_return_val_if_fail(skin != NULL, NULL);
|
|
930 g_return_val_if_fail(map_id < SKIN_PIXMAP_COUNT, NULL);
|
|
931
|
|
932 return &skin->pixmaps[map_id];
|
|
933 }
|
|
934
|
|
935 GdkBitmap *
|
|
936 skin_get_mask(Skin * skin, SkinMaskId mi)
|
|
937 {
|
|
938 g_return_val_if_fail(skin != NULL, NULL);
|
|
939 g_return_val_if_fail(mi < SKIN_PIXMAP_COUNT, NULL);
|
|
940
|
|
941 return skin->masks[mi];
|
|
942 }
|
|
943
|
|
944 GdkColor *
|
|
945 skin_get_color(Skin * skin, SkinColorId color_id)
|
|
946 {
|
|
947 GdkColor *ret = NULL;
|
|
948
|
|
949 g_return_val_if_fail(skin != NULL, NULL);
|
|
950
|
|
951 switch (color_id) {
|
|
952 case SKIN_TEXTBG:
|
|
953 if (skin->pixmaps[SKIN_TEXT].pixmap)
|
|
954 ret = skin->textbg;
|
|
955 else
|
|
956 ret = skin->def_textbg;
|
|
957 break;
|
|
958 case SKIN_TEXTFG:
|
|
959 if (skin->pixmaps[SKIN_TEXT].pixmap)
|
|
960 ret = skin->textfg;
|
|
961 else
|
|
962 ret = skin->def_textfg;
|
|
963 break;
|
|
964 default:
|
|
965 if (color_id < SKIN_COLOR_COUNT)
|
|
966 ret = skin->colors[color_id];
|
|
967 break;
|
|
968 }
|
|
969 return ret;
|
|
970 }
|
|
971
|
|
972 void
|
|
973 skin_get_viscolor(Skin * skin, guchar vis_color[24][3])
|
|
974 {
|
|
975 gint i;
|
|
976
|
|
977 g_return_if_fail(skin != NULL);
|
|
978
|
|
979 for (i = 0; i < 24; i++) {
|
|
980 vis_color[i][0] = skin->vis_color[i][0];
|
|
981 vis_color[i][1] = skin->vis_color[i][1];
|
|
982 vis_color[i][2] = skin->vis_color[i][2];
|
|
983 }
|
|
984 }
|
|
985
|
|
986 gint
|
|
987 skin_get_id(void)
|
|
988 {
|
|
989 return skin_current_num;
|
|
990 }
|
|
991
|
|
992 void
|
|
993 skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
|
|
994 SkinPixmapId pixmap_id,
|
|
995 gint xsrc, gint ysrc, gint xdest, gint ydest,
|
|
996 gint width, gint height)
|
|
997 {
|
|
998 SkinPixmap *pixmap;
|
|
999
|
|
1000 g_return_if_fail(skin != NULL);
|
|
1001
|
|
1002 pixmap = skin_get_pixmap(skin, pixmap_id);
|
|
1003 g_return_if_fail(pixmap != NULL);
|
|
1004 g_return_if_fail(pixmap->pixmap != NULL);
|
|
1005
|
|
1006 if (xsrc > pixmap->width || ysrc > pixmap->height)
|
|
1007 return;
|
|
1008
|
|
1009 width = MIN(width, pixmap->width - xsrc);
|
|
1010 height = MIN(height, pixmap->height - ysrc);
|
|
1011 gdk_draw_pixmap(drawable, gc, pixmap->pixmap, xsrc, ysrc,
|
|
1012 xdest, ydest, width, height);
|
|
1013 }
|
|
1014
|
|
1015 void
|
|
1016 skin_get_eq_spline_colors(Skin * skin, guint32 colors[19])
|
|
1017 {
|
|
1018 gint i;
|
|
1019 GdkPixmap *pixmap;
|
|
1020 GdkImage *img;
|
|
1021 SkinPixmap *eqmainpm;
|
|
1022
|
|
1023 g_return_if_fail(skin != NULL);
|
|
1024
|
|
1025 eqmainpm = &skin->pixmaps[SKIN_EQMAIN];
|
|
1026 if (eqmainpm->pixmap &&
|
|
1027 eqmainpm->current_width >= 116 && eqmainpm->current_height >= 313)
|
|
1028 pixmap = eqmainpm->pixmap;
|
|
1029 else
|
|
1030 return;
|
|
1031
|
|
1032 if (!GDK_IS_DRAWABLE(pixmap))
|
|
1033 return;
|
|
1034
|
|
1035 if (!(img = gdk_drawable_get_image(pixmap, 115, 294, 1, 19)))
|
|
1036 return;
|
|
1037
|
|
1038 for (i = 0; i < 19; i++)
|
|
1039 colors[i] = gdk_image_get_pixel(img, 0, i);
|
|
1040
|
|
1041 gdk_image_destroy(img);
|
|
1042 }
|
|
1043
|
|
1044
|
|
1045 static void
|
|
1046 skin_draw_playlistwin_frame_top(Skin * skin,
|
|
1047 GdkDrawable * drawable,
|
|
1048 GdkGC * gc,
|
|
1049 gint width, gint height, gboolean focus)
|
|
1050 {
|
|
1051 /* The title bar skin consists of 2 sets of 4 images, 1 set
|
|
1052 * for focused state and the other for unfocused. The 4 images
|
|
1053 * are:
|
|
1054 *
|
|
1055 * a. right corner (25,20)
|
|
1056 * b. left corner (25,20)
|
|
1057 * c. tiler (25,20)
|
|
1058 * d. title (100,20)
|
|
1059 *
|
|
1060 * min allowed width = 100+25+25 = 150
|
|
1061 */
|
|
1062
|
|
1063 gint i, y, c;
|
|
1064
|
|
1065 /* get y offset of the pixmap set to use */
|
|
1066 if (focus)
|
|
1067 y = 0;
|
|
1068 else
|
|
1069 y = 21;
|
|
1070
|
|
1071 /* left corner */
|
|
1072 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, y, 0, 0, 25, 20);
|
|
1073
|
|
1074 /* titlebar title */
|
|
1075 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 26, y,
|
|
1076 (width - 100) / 2, 0, 100, 20);
|
|
1077
|
|
1078 /* titlebar right corner */
|
|
1079 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 153, y,
|
|
1080 width - 25, 0, 25, 20);
|
|
1081
|
|
1082 /* tile draw the remaining frame */
|
|
1083
|
|
1084 /* compute tile count */
|
|
1085 c = (width - (100 + 25 + 25)) / 25;
|
|
1086
|
|
1087 for (i = 0; i < c / 2; i++) {
|
|
1088 /* left of title */
|
|
1089 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
|
|
1090 25 + i * 25, 0, 25, 20);
|
|
1091
|
|
1092 /* right of title */
|
|
1093 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
|
|
1094 (width + 100) / 2 + i * 25, 0, 25, 20);
|
|
1095 }
|
|
1096
|
|
1097 if (c & 1) {
|
|
1098 /* Odd tile count, so one remaining to draw. Here we split
|
|
1099 * it into two and draw half on either side of the title */
|
|
1100 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
|
|
1101 ((c / 2) * 25) + 25, 0, 12, 20);
|
|
1102 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
|
|
1103 (width / 2) + ((c / 2) * 25) + 50, 0, 13, 20);
|
|
1104 }
|
|
1105 }
|
|
1106
|
|
1107 static void
|
|
1108 skin_draw_playlistwin_frame_bottom(Skin * skin,
|
|
1109 GdkDrawable * drawable,
|
|
1110 GdkGC * gc,
|
|
1111 gint width, gint height, gboolean focus)
|
|
1112 {
|
|
1113 /* The bottom frame skin consists of 1 set of 4 images. The 4
|
|
1114 * images are:
|
|
1115 *
|
|
1116 * a. left corner with menu buttons (125,38)
|
|
1117 * b. visualization window (75,38)
|
|
1118 * c. right corner with play buttons (150,38)
|
|
1119 * d. frame tile (25,38)
|
|
1120 *
|
|
1121 * (min allowed width = 125+150+25=300
|
|
1122 */
|
|
1123
|
|
1124 gint i, c;
|
|
1125
|
|
1126 /* bottom left corner (menu buttons) */
|
|
1127 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 72,
|
|
1128 0, height - 38, 125, 38);
|
|
1129
|
|
1130 c = (width - 275) / 25;
|
|
1131
|
|
1132 /* draw visualization window, if width allows */
|
|
1133 if (c >= 3) {
|
|
1134 c -= 3;
|
|
1135 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 205, 0,
|
|
1136 width - (150 + 75), height - 38, 75, 38);
|
|
1137 }
|
|
1138
|
|
1139 /* Bottom right corner (playbuttons etc) */
|
|
1140 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT,
|
|
1141 126, 72, width - 150, height - 38, 150, 38);
|
|
1142
|
|
1143 /* Tile draw the remaining undrawn portions */
|
|
1144 for (i = 0; i < c; i++)
|
|
1145 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 179, 0,
|
|
1146 125 + i * 25, height - 38, 25, 38);
|
|
1147 }
|
|
1148
|
|
1149 static void
|
|
1150 skin_draw_playlistwin_frame_sides(Skin * skin,
|
|
1151 GdkDrawable * drawable,
|
|
1152 GdkGC * gc,
|
|
1153 gint width, gint height, gboolean focus)
|
|
1154 {
|
|
1155 /* The side frames consist of 2 tile images. 1 for the left, 1 for
|
|
1156 * the right.
|
|
1157 * a. left (12,29)
|
|
1158 * b. right (19,29)
|
|
1159 */
|
|
1160
|
|
1161 gint i;
|
|
1162
|
|
1163 /* frame sides */
|
|
1164 for (i = 0; i < (height - (20 + 38)) / 29; i++) {
|
|
1165 /* left */
|
|
1166 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 42,
|
|
1167 0, 20 + i * 29, 12, 29);
|
|
1168
|
|
1169 /* right */
|
|
1170 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 32, 42,
|
|
1171 width - 19, 20 + i * 29, 19, 29);
|
|
1172 }
|
|
1173 }
|
|
1174
|
|
1175
|
|
1176 void
|
|
1177 skin_draw_playlistwin_frame(Skin * skin,
|
|
1178 GdkDrawable * drawable, GdkGC * gc,
|
|
1179 gint width, gint height, gboolean focus)
|
|
1180 {
|
|
1181 skin_draw_playlistwin_frame_top(skin, drawable, gc, width, height, focus);
|
|
1182 skin_draw_playlistwin_frame_bottom(skin, drawable, gc, width, height,
|
|
1183 focus);
|
|
1184 skin_draw_playlistwin_frame_sides(skin, drawable, gc, width, height,
|
|
1185 focus);
|
|
1186 }
|
|
1187
|
|
1188
|
|
1189 void
|
|
1190 skin_draw_playlistwin_shaded(Skin * skin,
|
|
1191 GdkDrawable * drawable, GdkGC * gc,
|
|
1192 gint width, gboolean focus)
|
|
1193 {
|
|
1194 /* The shade mode titlebar skin consists of 4 images:
|
|
1195 * a) left corner offset (72,42) size (25,14)
|
|
1196 * b) right corner, focused offset (99,57) size (50,14)
|
|
1197 * c) right corner, unfocused offset (99,42) size (50,14)
|
|
1198 * d) bar tile offset (72,57) size (25,14)
|
|
1199 */
|
|
1200
|
|
1201 gint i;
|
|
1202
|
|
1203 /* left corner */
|
|
1204 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14);
|
|
1205
|
|
1206 /* bar tile */
|
|
1207 for (i = 0; i < (width - 75) / 25; i++)
|
|
1208 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 57,
|
|
1209 (i * 25) + 25, 0, 25, 14);
|
|
1210
|
|
1211 /* right corner */
|
|
1212 skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 99, focus ? 57 : 42,
|
|
1213 width - 50, 0, 50, 14);
|
|
1214 }
|
|
1215
|
|
1216
|
|
1217 void
|
|
1218 skin_draw_mainwin_titlebar(Skin * skin,
|
|
1219 GdkDrawable * drawable, GdkGC * gc,
|
|
1220 gboolean shaded, gboolean focus)
|
|
1221 {
|
|
1222 /* The titlebar skin consists of 2 sets of 2 images, one for for
|
|
1223 * shaded and the other for unshaded mode, giving a total of 4.
|
|
1224 * The images are exactly 275x14 pixels, aligned and arranged
|
|
1225 * vertically on each other in the pixmap in the following order:
|
|
1226 *
|
|
1227 * a) unshaded, focused offset (27, 0)
|
|
1228 * b) unshaded, unfocused offset (27, 15)
|
|
1229 * c) shaded, focused offset (27, 29)
|
|
1230 * d) shaded, unfocused offset (27, 42)
|
|
1231 */
|
|
1232
|
|
1233 gint y_offset;
|
|
1234
|
|
1235 if (shaded) {
|
|
1236 if (focus)
|
|
1237 y_offset = 29;
|
|
1238 else
|
|
1239 y_offset = 42;
|
|
1240 }
|
|
1241 else {
|
|
1242 if (focus)
|
|
1243 y_offset = 0;
|
|
1244 else
|
|
1245 y_offset = 15;
|
|
1246 }
|
|
1247
|
|
1248 skin_draw_pixmap(skin, drawable, gc, SKIN_TITLEBAR, 27, y_offset,
|
|
1249 0, 0, MAINWIN_WIDTH, MAINWIN_TITLEBAR_HEIGHT);
|
|
1250 }
|
|
1251
|
|
1252 #if 0
|
|
1253 void
|
|
1254 skin_draw_mainwin(Skin * skin,
|
|
1255 GdkDrawable * drawable, GdkGC gc,
|
|
1256 gboolean doublesize, gboolean shaded, gboolean focus)
|
|
1257 {
|
|
1258
|
|
1259 }
|
|
1260 #endif
|