1 /* GStreamer non-core tag registration and tag utility functions |
1 /* GStreamer non-core tag registration and tag utility functions |
2 * Copyright (C) 2005 Ross Burton <ross@burtonini.com> |
2 * Copyright (C) 2005 Ross Burton <ross@burtonini.com> |
3 * Copyright (C) 2006-2008 Tim-Philipp Müller <tim centricular net> |
3 * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net> |
4 * |
4 * |
5 * This library is free software; you can redistribute it and/or |
5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public |
6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either |
7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. |
8 * version 2 of the License, or (at your option) any later version. |
49 { |
52 { |
50 #ifdef ENABLE_NLS |
53 #ifdef ENABLE_NLS |
51 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, |
54 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, |
52 LOCALEDIR); |
55 LOCALEDIR); |
53 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
56 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
54 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
|
55 #endif |
57 #endif |
56 |
58 |
57 /* musicbrainz tags */ |
59 /* musicbrainz tags */ |
58 gst_tag_register (GST_TAG_MUSICBRAINZ_TRACKID, GST_TAG_FLAG_META, |
60 gst_tag_register (GST_TAG_MUSICBRAINZ_TRACKID, GST_TAG_FLAG_META, |
59 G_TYPE_STRING, _("track ID"), _("MusicBrainz track ID"), NULL); |
61 G_TYPE_STRING, _("track ID"), _("MusicBrainz track ID"), NULL); |
110 |
112 |
111 static void |
113 static void |
112 register_tag_image_type_enum (GType * id) |
114 register_tag_image_type_enum (GType * id) |
113 { |
115 { |
114 static const GEnumValue image_types[] = { |
116 static const GEnumValue image_types[] = { |
115 {GST_TAG_IMAGE_TYPE_NONE, "GST_TAG_IMAGE_TYPE_NONE", "none"}, |
|
116 {GST_TAG_IMAGE_TYPE_UNDEFINED, "GST_TAG_IMAGE_TYPE_UNDEFINED", "undefined"}, |
117 {GST_TAG_IMAGE_TYPE_UNDEFINED, "GST_TAG_IMAGE_TYPE_UNDEFINED", "undefined"}, |
117 {GST_TAG_IMAGE_TYPE_FRONT_COVER, "GST_TAG_IMAGE_TYPE_FRONT_COVER", |
118 {GST_TAG_IMAGE_TYPE_FRONT_COVER, "GST_TAG_IMAGE_TYPE_FRONT_COVER", |
118 "front-cover"}, |
119 "front-cover"}, |
119 {GST_TAG_IMAGE_TYPE_BACK_COVER, "GST_TAG_IMAGE_TYPE_BACK_COVER", |
120 {GST_TAG_IMAGE_TYPE_BACK_COVER, "GST_TAG_IMAGE_TYPE_BACK_COVER", |
120 "back-cover"}, |
121 "back-cover"}, |
149 "publisher-studio-logo"}, |
150 "publisher-studio-logo"}, |
150 {0, NULL, NULL} |
151 {0, NULL, NULL} |
151 }; |
152 }; |
152 |
153 |
153 *id = g_enum_register_static ("GstTagImageType", image_types); |
154 *id = g_enum_register_static ("GstTagImageType", image_types); |
154 |
|
155 /* work around thread-safety issue with class creation in GLib */ |
|
156 g_type_class_ref (*id); |
|
157 } |
155 } |
158 #ifdef __SYMBIAN32__ |
156 #ifdef __SYMBIAN32__ |
159 EXPORT_C |
157 EXPORT_C |
160 #endif |
158 #endif |
161 |
159 |
162 |
160 |
163 GType |
161 GType |
164 gst_tag_image_type_get_type (void) |
162 gst_tag_image_type_get_type (void) |
165 { |
163 { |
166 static GType id; |
164 static GType id; |
167 |
|
168 static GOnce once = G_ONCE_INIT; |
165 static GOnce once = G_ONCE_INIT; |
169 |
166 |
170 g_once (&once, (GThreadFunc) register_tag_image_type_enum, &id); |
167 g_once (&once, (GThreadFunc) register_tag_image_type_enum, &id); |
171 return id; |
168 return id; |
172 } |
|
173 |
|
174 static inline gboolean |
|
175 gst_tag_image_type_is_valid (GstTagImageType type) |
|
176 { |
|
177 GEnumClass *klass; |
|
178 |
|
179 gboolean res; |
|
180 |
|
181 klass = g_type_class_ref (gst_tag_image_type_get_type ()); |
|
182 res = (g_enum_get_value (klass, type) != NULL); |
|
183 g_type_class_unref (klass); |
|
184 |
|
185 return res; |
|
186 } |
169 } |
187 |
170 |
188 /** |
171 /** |
189 * gst_tag_parse_extended_comment: |
172 * gst_tag_parse_extended_comment: |
190 * @ext_comment: an extended comment string, see #GST_TAG_EXTENDED_COMMENT |
173 * @ext_comment: an extended comment string, see #GST_TAG_EXTENDED_COMMENT |
363 } |
344 } |
364 |
345 |
365 g_free (utf8); |
346 g_free (utf8); |
366 return NULL; |
347 return NULL; |
367 } |
348 } |
368 |
|
369 /** |
|
370 * gst_tag_image_data_to_image_buffer: |
|
371 * @image_data: the (encoded) image |
|
372 * @image_data_len: the length of the encoded image data at @image_data |
|
373 * @image_type: type of the image, or #GST_TAG_IMAGE_TYPE_UNDEFINED. Pass |
|
374 * #GST_TAG_IMAGE_TYPE_NONE if no image type should be set at all (e.g. |
|
375 * for preview images) |
|
376 * |
|
377 * Helper function for tag-reading plugins to create a #GstBuffer suitable to |
|
378 * add to a #GstTagList as an image tag (such as #GST_TAG_IMAGE or |
|
379 * #GST_TAG_PREVIEW_IMAGE) from the encoded image data and an (optional) image |
|
380 * type. |
|
381 * |
|
382 * Background: cover art and other images in tags are usually stored as a |
|
383 * blob of binary image data, often accompanied by a MIME type or some other |
|
384 * content type string (e.g. 'png', 'jpeg', 'jpg'). Sometimes there is also an |
|
385 * 'image type' to indicate what kind of image this is (e.g. front cover, |
|
386 * back cover, artist, etc.). The image data may also be an URI to the image |
|
387 * rather than the image itself. |
|
388 * |
|
389 * In GStreamer, image tags are #GstBuffer<!-- -->s containing the raw image |
|
390 * data, with the buffer caps describing the content type of the image |
|
391 * (e.g. image/jpeg, image/png, text/uri-list). The buffer caps may contain |
|
392 * an additional 'image-type' field of #GST_TYPE_TAG_IMAGE_TYPE to describe |
|
393 * the type of image (front cover, back cover etc.). #GST_TAG_PREVIEW_IMAGE |
|
394 * tags should not carry an image type, their type is already indicated via |
|
395 * the special tag name. |
|
396 * |
|
397 * This function will do various checks and typefind the encoded image |
|
398 * data (we can't trust the declared mime type). |
|
399 * |
|
400 * Returns: a newly-allocated image buffer for use in tag lists, or NULL |
|
401 * |
|
402 * Since: 0.10.20 |
|
403 */ |
|
404 #ifdef __SYMBIAN32__ |
|
405 EXPORT_C |
|
406 #endif |
|
407 |
|
408 GstBuffer * |
|
409 gst_tag_image_data_to_image_buffer (const guint8 * image_data, |
|
410 guint image_data_len, GstTagImageType image_type) |
|
411 { |
|
412 const gchar *name; |
|
413 |
|
414 GstBuffer *image; |
|
415 |
|
416 GstCaps *caps; |
|
417 |
|
418 g_return_val_if_fail (image_data != NULL, NULL); |
|
419 g_return_val_if_fail (image_data_len > 0, NULL); |
|
420 g_return_val_if_fail (gst_tag_image_type_is_valid (image_type), NULL); |
|
421 |
|
422 GST_DEBUG ("image data len: %u bytes", image_data_len); |
|
423 |
|
424 /* allocate space for a NUL terminator for an uri too */ |
|
425 image = gst_buffer_try_new_and_alloc (image_data_len + 1); |
|
426 if (image == NULL) { |
|
427 GST_WARNING ("failed to allocate buffer of %d for image", image_data_len); |
|
428 return NULL; |
|
429 } |
|
430 |
|
431 memcpy (GST_BUFFER_DATA (image), image_data, image_data_len); |
|
432 GST_BUFFER_DATA (image)[image_data_len] = '\0'; |
|
433 |
|
434 /* Find GStreamer media type, can't trust declared type */ |
|
435 caps = gst_type_find_helper_for_buffer (NULL, image, NULL); |
|
436 |
|
437 if (caps == NULL) |
|
438 goto no_type; |
|
439 |
|
440 GST_DEBUG ("Found GStreamer media type: %" GST_PTR_FORMAT, caps); |
|
441 |
|
442 /* sanity check: make sure typefound/declared caps are either URI or image */ |
|
443 name = gst_structure_get_name (gst_caps_get_structure (caps, 0)); |
|
444 |
|
445 if (!g_str_has_prefix (name, "image/") && |
|
446 !g_str_has_prefix (name, "video/") && |
|
447 !g_str_equal (name, "text/uri-list")) { |
|
448 GST_DEBUG ("Unexpected image type '%s', ignoring image frame", name); |
|
449 goto error; |
|
450 } |
|
451 |
|
452 /* Decrease size by 1 if we don't have an URI list |
|
453 * to keep the original size of the image |
|
454 */ |
|
455 if (!g_str_equal (name, "text/uri-list")) |
|
456 GST_BUFFER_SIZE (image) = image_data_len; |
|
457 |
|
458 if (image_type != GST_TAG_IMAGE_TYPE_NONE) { |
|
459 GST_LOG ("Setting image type: %d", image_type); |
|
460 caps = gst_caps_make_writable (caps); |
|
461 gst_caps_set_simple (caps, "image-type", GST_TYPE_TAG_IMAGE_TYPE, |
|
462 image_type, NULL); |
|
463 } |
|
464 |
|
465 gst_buffer_set_caps (image, caps); |
|
466 gst_caps_unref (caps); |
|
467 return image; |
|
468 |
|
469 /* ERRORS */ |
|
470 no_type: |
|
471 { |
|
472 GST_DEBUG ("Could not determine GStreamer media type, ignoring image"); |
|
473 /* fall through */ |
|
474 } |
|
475 error: |
|
476 { |
|
477 if (image) |
|
478 gst_buffer_unref (image); |
|
479 if (caps) |
|
480 gst_caps_unref (caps); |
|
481 return NULL; |
|
482 } |
|
483 } |
|