summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>2010-06-23 12:02:24 -0300
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>2010-07-26 12:00:30 -0300
commit5e51a77df4d775457f8f1145f2546c333c81b55c (patch)
tree150aaac2c6dde05782132ddefff310907c0af24a
parent53318f20ccb3ca639ee6e3f58cfbaf2fa1a51295 (diff)
tag: xmp: Maps GST_TAG_DATE_TIME
Adds mapping for GST_TAG_DATE_TIME. Tests included. https://bugzilla.gnome.org/show_bug.cgi?id=594504
-rw-r--r--gst-libs/gst/tag/gstxmptag.c128
-rw-r--r--tests/check/libs/tag.c33
2 files changed, 159 insertions, 2 deletions
diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c
index 51135766b..e0d05575c 100644
--- a/gst-libs/gst/tag/gstxmptag.c
+++ b/gst-libs/gst/tag/gstxmptag.c
@@ -41,6 +41,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <ctype.h>
/*
* Serializes a GValue into a string.
@@ -720,7 +721,7 @@ _init_xmp_tag_map ()
_xmp_tag_add_simple_mapping (GST_TAG_ARTIST, "dc:creator", NULL, NULL);
_xmp_tag_add_simple_mapping (GST_TAG_COPYRIGHT, "dc:rights", NULL, NULL);
_xmp_tag_add_simple_mapping (GST_TAG_DATE, "dc:date", NULL, NULL);
- _xmp_tag_add_simple_mapping (GST_TAG_DATE, "exif:DateTimeOriginal", NULL,
+ _xmp_tag_add_simple_mapping (GST_TAG_DATE_TIME, "exif:DateTimeOriginal", NULL,
NULL);
_xmp_tag_add_simple_mapping (GST_TAG_DESCRIPTION, "dc:description", NULL,
NULL);
@@ -875,7 +876,104 @@ read_one_tag (GstTagList * list, const gchar * tag, XmpTag * xmptag,
break;
}
default:
- if (tag_type == GST_TYPE_DATE) {
+ if (tag_type == GST_TYPE_DATE_TIME) {
+ GstDateTime *datetime;
+ gint year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
+ gint usecs = 0;
+ gint gmt_offset_hour = -1, gmt_offset_min = -1, gmt_offset = -1;
+ gchar usec_str[16];
+ gint ret;
+ gint len;
+
+ len = strlen (v);
+ if (len == 0) {
+ GST_WARNING ("Empty string for datetime parsing");
+ return;
+ }
+
+ GST_DEBUG ("Parsing %s into a datetime", v);
+
+ ret = sscanf (v, "%04d-%02d-%02dT%02d:%02d:%02d.%15s",
+ &year, &month, &day, &hour, &minute, &second, usec_str);
+ if (ret < 3) {
+ /* FIXME theoretically, xmp can express datetimes with only year
+ * or year and month, but gstdatetime doesn't support it */
+ GST_WARNING ("Invalid datetime value: %s", v);
+ }
+
+ /* parse the usecs */
+ if (ret >= 7) {
+ gint num_digits = 0;
+
+ /* find the number of digits */
+ while (isdigit (usec_str[num_digits++]) && num_digits < 6);
+
+ if (num_digits > 0) {
+ /* fill up to 6 digits with 0 */
+ while (num_digits < 6) {
+ usec_str[num_digits++] = 0;
+ }
+
+ g_assert (num_digits == 6);
+
+ usec_str[num_digits] = '\0';
+ usecs = atoi (usec_str);
+ }
+ }
+
+ /* parse the timezone info */
+ if (v[len - 1] == 'Z') {
+ GST_LOG ("UTC timezone");
+
+ /* Having a Z at the end means UTC */
+ datetime = gst_date_time_new (year, month, day, hour, minute,
+ second, usecs, 0);
+ } else {
+ gchar *plus_pos = NULL;
+ gchar *neg_pos = NULL;
+ gchar *pos = NULL;
+
+ GST_LOG ("Checking for timezone information");
+
+ /* check if there is timezone info */
+ plus_pos = strrchr (v, '+');
+ neg_pos = strrchr (v, '-');
+ if (plus_pos) {
+ pos = plus_pos + 1;
+ } else if (neg_pos) {
+ pos = neg_pos + 1;
+ }
+
+ if (pos) {
+ gint ret_tz = sscanf (pos, "%d:%d", &gmt_offset_hour,
+ &gmt_offset_min);
+
+ GST_DEBUG ("Parsing timezone: %s", pos);
+
+ if (ret_tz == 2) {
+ gmt_offset = gmt_offset_hour * 60 + gmt_offset_min;
+ if (neg_pos != NULL && neg_pos + 1 == pos)
+ gmt_offset *= -1;
+
+ GST_LOG ("Timezone offset: %f (%d minutes)", gmt_offset / 60.0,
+ gmt_offset);
+ /* no way to know if it is DST or not */
+ datetime = gst_date_time_new (year, month, day, hour, minute,
+ second, usecs, gmt_offset / 60.0f);
+ } else {
+ GST_WARNING ("Failed to parse timezone information");
+ }
+ } else {
+ GST_WARNING ("No timezone signal found");
+ }
+ }
+
+ if (datetime) {
+ gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, tag, datetime, NULL);
+ gst_date_time_unref (datetime);
+ }
+
+ } else if (tag_type == GST_TYPE_DATE) {
GDate *date;
gint d, m, y;
@@ -1201,6 +1299,32 @@ gst_value_serialize_xmp (const GValue * value)
return g_strdup_printf ("%04d-%02d-%02d",
(gint) g_date_get_year (date), (gint) g_date_get_month (date),
(gint) g_date_get_day (date));
+ } else if (G_VALUE_TYPE (value) == GST_TYPE_DATE_TIME) {
+ gint year, month, day, hour, min, sec, microsec;
+ gint gmt_offset = 0;
+ gint gmt_offset_hour, gmt_offset_min;
+ GstDateTime *datetime = (GstDateTime *) g_value_get_boxed (value);
+
+ year = gst_date_time_get_year (datetime);
+ month = gst_date_time_get_month (datetime);
+ day = gst_date_time_get_day (datetime);
+ hour = gst_date_time_get_hour (datetime);
+ min = gst_date_time_get_minute (datetime);
+ sec = gst_date_time_get_second (datetime);
+ microsec = gst_date_time_get_microsecond (datetime);
+ gmt_offset = (gint) (60 * gst_date_time_get_time_zone_offset (datetime));
+ if (gmt_offset == 0) {
+ /* UTC */
+ return g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02d.%06dZ",
+ year, month, day, hour, min, sec, microsec);
+ } else {
+ gmt_offset_hour = ABS (gmt_offset) / 60;
+ gmt_offset_min = ABS (gmt_offset) % 60;
+
+ return g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02d.%06d%c%02d:%02d",
+ year, month, day, hour, min, sec, microsec,
+ gmt_offset >= 0 ? '+' : '-', gmt_offset_hour, gmt_offset_min);
+ }
} else {
return NULL;
}
diff --git a/tests/check/libs/tag.c b/tests/check/libs/tag.c
index bd57a0aee..1d1f89594 100644
--- a/tests/check/libs/tag.c
+++ b/tests/check/libs/tag.c
@@ -870,6 +870,7 @@ tag_list_equals (GstTagList * taglist, GstTagList * taglist2)
n_recv = gst_structure_n_fields (taglist2);
n_sent = gst_structure_n_fields (taglist);
fail_unless (n_recv == n_sent);
+ fail_unless (n_sent > 0);
/* FIXME: compare taglist values */
for (i = 0; i < n_sent; i++) {
@@ -935,6 +936,7 @@ GST_START_TEST (test_xmp_tags_serialization_deserialization)
{
GValue value = { 0 };
GDate *date;
+ GstDateTime *datetime;
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "my string");
@@ -1051,6 +1053,37 @@ GST_START_TEST (test_xmp_tags_serialization_deserialization)
g_value_set_uint (&value, 22);
do_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
g_value_unset (&value);
+
+ g_value_init (&value, GST_TYPE_DATE_TIME);
+ datetime = gst_date_time_new (2010, 6, 22, 12, 5, 10, 0, 0);
+ g_value_set_boxed (&value, datetime);
+ gst_date_time_unref (datetime);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
+ datetime = gst_date_time_new (2010, 6, 22, 12, 5, 10, 125, 0);
+ g_value_set_boxed (&value, datetime);
+ gst_date_time_unref (datetime);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
+ datetime = gst_date_time_new (2010, 6, 22, 12, 5, 10, 1, 0);
+ g_value_set_boxed (&value, datetime);
+ gst_date_time_unref (datetime);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
+ datetime = gst_date_time_new (2010, 6, 22, 12, 5, 10, 123456, 0);
+ g_value_set_boxed (&value, datetime);
+ gst_date_time_unref (datetime);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
+ datetime = gst_date_time_new (2010, 6, 22, 12, 5, 10, 123456, -3);
+ g_value_set_boxed (&value, datetime);
+ gst_date_time_unref (datetime);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
+ datetime = gst_date_time_new (2010, 6, 22, 12, 5, 10, 123456, 5);
+ g_value_set_boxed (&value, datetime);
+ gst_date_time_unref (datetime);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
+ datetime = gst_date_time_new_local_time (2010, 12, 2, 12, 5, 10, 43);
+ g_value_set_boxed (&value, datetime);
+ gst_date_time_unref (datetime);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
+ g_value_unset (&value);
}
GST_END_TEST;