6 #include <glib/gstdio.h>
7 #include "icon_tools.h"
10 #include <gdk-pixbuf/gdk-pixbuf.h>
11 #include <gdk-pixbuf/gdk-pixdata.h>
29 static tag_map_t tag_map[] =
31 {"resources", R_RESOURCES},
32 {"section", R_SECTION},
37 #define TAG_MAP_SZ (sizeof(tag_map)/sizeof(tag_map_t))
49 GList *inc_list = NULL;
52 find_file(GList *list, const gchar *name)
61 inc = (gchar*)link->data;
62 str = g_strdup_printf("%s/%s", inc, name);
63 if (g_file_test(str, G_FILE_TEST_IS_REGULAR))
68 link = g_list_next(link);
70 if (g_file_test(name, G_FILE_TEST_IS_REGULAR))
72 return g_strdup(name);
80 const gchar **attr_names,
81 const gchar **attr_values)
85 if (attr_names == NULL) return NULL;
86 for (ii = 0; attr_names[ii] != NULL; ii++)
88 if (strcmp(name, attr_names[ii]) == 0)
89 return attr_values[ii];
95 read_string_from_file(const gchar *filename)
102 fd = g_fopen(filename, "r");
105 fseek(fd, 0, SEEK_END);
107 fseek(fd, 0, SEEK_SET);
108 buffer = g_malloc(size+1);
109 size = fread(buffer, 1, size, fd);
111 gval = ghb_value_new(G_TYPE_STRING);
112 g_value_take_string(gval, buffer);
119 GMarkupParseContext *ctx,
121 const gchar **attr_names,
122 const gchar **attr_values,
126 parse_data_t *pd = (parse_data_t*)ud;
134 // Check to see if the first element found has been closed
135 // If so, ignore any junk following it.
139 for (ii = 0; ii < TAG_MAP_SZ; ii++)
141 if (strcmp(tag, tag_map[ii].tag) == 0)
143 id.id = tag_map[ii].id;
147 if (ii == TAG_MAP_SZ)
149 g_warning("Unrecognized start tag (%s)", tag);
152 g_queue_push_head(pd->tag_stack, id.pid);
155 GValue *current = g_queue_peek_head(pd->stack);
162 name = lookup_attr_value("name", attr_names, attr_values);
163 if (name && strcmp(name, "icons") == 0)
165 gval = ghb_dict_value_new();
166 if (pd->key) g_free(pd->key);
167 pd->key = g_strdup(name);
168 g_queue_push_head(pd->stack, gval);
176 name = lookup_attr_value("file", attr_names, attr_values);
177 filename = find_file(inc_list, name);
178 name = lookup_attr_value("name", attr_names, attr_values);
179 if (filename && name)
185 pb = gdk_pixbuf_new_from_file(filename, &err);
188 g_warning("Failed to open icon file %s: %s", filename, err->message);
191 gval = ghb_dict_value_new();
192 int colorspace = gdk_pixbuf_get_colorspace(pb);
193 gboolean alpha = gdk_pixbuf_get_has_alpha(pb);
194 int width = gdk_pixbuf_get_width(pb);
195 int height = gdk_pixbuf_get_height(pb);
196 int bps = gdk_pixbuf_get_bits_per_sample(pb);
197 int rowstride = gdk_pixbuf_get_rowstride(pb);
199 ghb_dict_insert(gval, g_strdup("colorspace"),
200 ghb_int_value_new(colorspace));
201 ghb_dict_insert(gval, g_strdup("alpha"),
202 ghb_boolean_value_new(alpha));
203 ghb_dict_insert(gval, g_strdup("width"),
204 ghb_int_value_new(width));
205 ghb_dict_insert(gval, g_strdup("height"),
206 ghb_int_value_new(height));
207 ghb_dict_insert(gval, g_strdup("bps"),
208 ghb_int_value_new(bps));
209 ghb_dict_insert(gval, g_strdup("rowstride"),
210 ghb_int_value_new(rowstride));
212 rd = g_malloc(sizeof(ghb_rawdata_t));
213 rd->data = gdk_pixbuf_get_pixels(pb);
214 rd->size = height * rowstride * bps / 8;
215 GValue *data = ghb_rawdata_value_new(rd);
216 ghb_dict_insert(gval, g_strdup("data"), data);
218 if (pd->key) g_free(pd->key);
219 pd->key = g_strdup(name);
224 g_warning("%s:missing a requried attribute", name);
233 name = lookup_attr_value("file", attr_names, attr_values);
234 filename = find_file(inc_list, name);
235 name = lookup_attr_value("name", attr_names, attr_values);
236 if (filename && name)
238 gval = ghb_plist_parse_file(filename);
239 if (pd->key) g_free(pd->key);
240 pd->key = g_strdup(name);
245 g_warning("%s:missing a requried attribute", name);
254 name = lookup_attr_value("file", attr_names, attr_values);
255 filename = find_file(inc_list, name);
256 name = lookup_attr_value("name", attr_names, attr_values);
257 if (filename && name)
259 gval = read_string_from_file(filename);
260 if (pd->key) g_free(pd->key);
261 pd->key = g_strdup(name);
266 g_warning("%s:missing a requried attribute", name);
271 // Add the element to the current container
273 { // There's an element to add
279 gtype = G_VALUE_TYPE(current);
280 if (gtype == ghb_array_get_type())
282 ghb_array_append(current, gval);
284 else if (gtype == ghb_dict_get_type())
288 g_warning("No key for dictionary item");
289 ghb_value_free(gval);
293 ghb_dict_insert(current, g_strdup(pd->key), gval);
298 g_error("Invalid container type. This shouldn't happen");
305 GMarkupParseContext *ctx,
310 parse_data_t *pd = (parse_data_t*)ud;
319 // Check to see if the first element found has been closed
320 // If so, ignore any junk following it.
324 for (ii = 0; ii < TAG_MAP_SZ; ii++)
326 if (strcmp(name, tag_map[ii].tag) == 0)
332 if (ii == TAG_MAP_SZ)
334 g_warning("Unrecognized start tag (%s)", name);
337 start_id.pid = g_queue_pop_head(pd->tag_stack);
338 if (start_id.id != id)
339 g_warning("start tag != end tag: (%s %d) %d", name, id, id);
342 GValue *current = g_queue_peek_head(pd->stack);
348 g_queue_pop_head(pd->stack);
353 // Get the top of the data structure stack and if it's an array
354 // or dict, add the current element
358 pd->closed_top = TRUE;
361 gtype = G_VALUE_TYPE(current);
362 if (gtype == ghb_array_get_type())
364 ghb_array_append(current, gval);
366 else if (gtype == ghb_dict_get_type())
370 g_warning("No key for dictionary item");
371 ghb_value_free(gval);
375 ghb_dict_insert(current, g_strdup(pd->key), gval);
380 g_error("Invalid container type. This shouldn't happen");
383 if (g_queue_is_empty(pd->tag_stack))
384 pd->closed_top = TRUE;
389 GMarkupParseContext *ctx,
395 parse_data_t *pd = (parse_data_t*)ud;
396 if (pd->value) g_free(pd->value);
397 pd->value = g_strdup(text);
402 GMarkupParseContext *ctx,
408 //parse_data_t *pd = (parse_data_t*)ud;
410 //g_debug("passthrough %s", text);
414 parse_error(GMarkupParseContext *ctx, GError *error, gpointer ud)
416 g_warning("Resource parse error: %s", error->message);
419 // This is required or the parser crashes
421 destroy_notify(gpointer data)
423 //g_debug("destroy parser");
427 ghb_resource_parse(const gchar *buf, gssize len)
429 GMarkupParseContext *ctx;
430 GMarkupParser parser;
434 pd.stack = g_queue_new();
435 pd.tag_stack = g_queue_new();
438 pd.plist = ghb_dict_value_new();
439 g_queue_push_head(pd.stack, pd.plist);
440 pd.closed_top = FALSE;
442 parser.start_element = start_element;
443 parser.end_element = end_element;
444 parser.text = text_data;
445 parser.passthrough = passthrough;
446 parser.error = parse_error;
447 ctx = g_markup_parse_context_new(&parser, 0, &pd, destroy_notify);
449 g_markup_parse_context_parse(ctx, buf, len, &err);
450 g_markup_parse_context_end_parse(ctx, &err);
451 g_markup_parse_context_free(ctx);
452 g_queue_free(pd.stack);
453 g_queue_free(pd.tag_stack);
458 ghb_resource_parse_file(FILE *fd)
466 fseek(fd, 0, SEEK_END);
468 fseek(fd, 0, SEEK_SET);
469 buffer = g_malloc(size+1);
470 size = fread(buffer, 1, size, fd);
472 gval = ghb_resource_parse(buffer, (gssize)size);
481 "Usage: %s [-I <inc path>] <in resource list> <out resource plist>\n"
483 " Creates a resource plist from a resource list\n"
485 " I - Include path to search for files\n"
486 " <in resource list> Input resources file\n"
487 " <out resource plist> Output resources plist file\n"
496 main(gint argc, gchar *argv[])
501 const gchar *src, *dst;
505 opt = getopt(argc, argv, OPTS);
511 inc_list = g_list_prepend(inc_list, g_strdup(optarg));
516 if (optind != argc - 2)
521 src = argv[optind++];
522 dst = argv[optind++];
525 file = g_fopen(src, "r");
528 fprintf(stderr, "Error: failed to open %s\n", src);
532 gval = ghb_resource_parse_file(file);
533 ghb_plist_write_file(dst, gval);