Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / tests / check / libs / tag.c
1 /* GStreamer
2  *
3  * unit tests for the tag support library
4  *
5  * Copyright (C) 2006-2011 Tim-Philipp Müller <tim centricular net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library 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 GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gst/check/gstcheck.h>
28
29 #include <gst/tag/tag.h>
30 #include <gst/base/gstbytewriter.h>
31 #include <string.h>
32 #include <locale.h>
33
34 GST_START_TEST (test_parse_extended_comment)
35 {
36   gchar *key, *val, *lang;
37
38   /* first check the g_return_val_if_fail conditions */
39   ASSERT_CRITICAL (gst_tag_parse_extended_comment (NULL, NULL, NULL, NULL,
40           FALSE));
41   ASSERT_CRITICAL (gst_tag_parse_extended_comment ("\377\000", NULL, NULL, NULL,
42           FALSE));
43
44   key = val = lang = NULL;
45   fail_unless (gst_tag_parse_extended_comment ("a=b", &key, &lang, &val,
46           FALSE) == TRUE);
47   fail_unless (key != NULL);
48   fail_unless (lang == NULL);
49   fail_unless (val != NULL);
50   fail_unless_equals_string (key, "a");
51   fail_unless_equals_string (val, "b");
52   g_free (key);
53   g_free (lang);
54   g_free (val);
55
56   key = val = lang = NULL;
57   fail_unless (gst_tag_parse_extended_comment ("a[l]=b", &key, &lang, &val,
58           FALSE) == TRUE);
59   fail_unless (key != NULL);
60   fail_unless (lang != NULL);
61   fail_unless (val != NULL);
62   fail_unless_equals_string (key, "a");
63   fail_unless_equals_string (lang, "l");
64   fail_unless_equals_string (val, "b");
65   g_free (key);
66   g_free (lang);
67   g_free (val);
68
69   key = val = lang = NULL;
70   fail_unless (gst_tag_parse_extended_comment ("foo=bar", &key, &lang, &val,
71           FALSE) == TRUE);
72   fail_unless (key != NULL);
73   fail_unless (lang == NULL);
74   fail_unless (val != NULL);
75   fail_unless_equals_string (key, "foo");
76   fail_unless_equals_string (val, "bar");
77   g_free (key);
78   g_free (lang);
79   g_free (val);
80
81   key = val = lang = NULL;
82   fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", &key, &lang, &val,
83           FALSE) == TRUE);
84   fail_unless (key != NULL);
85   fail_unless (lang != NULL);
86   fail_unless (val != NULL);
87   fail_unless_equals_string (key, "foo");
88   fail_unless_equals_string (lang, "fr");
89   fail_unless_equals_string (val, "bar");
90   g_free (key);
91   g_free (lang);
92   g_free (val);
93
94   key = val = lang = NULL;
95   fail_unless (gst_tag_parse_extended_comment ("foo=[fr]bar", &key, &lang, &val,
96           FALSE) == TRUE);
97   fail_unless (key != NULL);
98   fail_unless (lang == NULL);
99   fail_unless (val != NULL);
100   fail_unless_equals_string (key, "foo");
101   fail_unless_equals_string (val, "[fr]bar");
102   g_free (key);
103   g_free (lang);
104   g_free (val);
105
106   /* test NULL for output locations */
107   fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", NULL, NULL, NULL,
108           FALSE) == TRUE);
109
110   /* test strict mode (key must be specified) */
111   fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", NULL, NULL, NULL,
112           TRUE) == TRUE);
113   fail_unless (gst_tag_parse_extended_comment ("foo=bar", NULL, NULL, NULL,
114           TRUE) == TRUE);
115   fail_unless (gst_tag_parse_extended_comment ("foobar", NULL, NULL, NULL,
116           TRUE) == FALSE);
117
118   /* test non-strict mode (if there's no key, that's fine too) */
119   fail_unless (gst_tag_parse_extended_comment ("foobar", NULL, NULL, NULL,
120           FALSE) == TRUE);
121   fail_unless (gst_tag_parse_extended_comment ("[fr]bar", NULL, NULL, NULL,
122           FALSE) == TRUE);
123
124   key = val = lang = NULL;
125   fail_unless (gst_tag_parse_extended_comment ("[fr]bar", &key, &lang, &val,
126           FALSE) == TRUE);
127   fail_unless (key == NULL);
128   fail_unless (lang == NULL);
129   fail_unless (val != NULL);
130   fail_unless_equals_string (val, "[fr]bar");
131   g_free (key);
132   g_free (lang);
133   g_free (val);
134 }
135
136 GST_END_TEST;
137
138 #define ASSERT_TAG_LIST_HAS_STRING(list,field,string)                      \
139   {                                                                        \
140     gboolean got_match = FALSE;                                            \
141     guint i, size;                                                         \
142                                                                            \
143     fail_unless (gst_tag_list_get_tag_size (list,field) > 0);              \
144     size = gst_tag_list_get_tag_size (list,field);                         \
145     for (i = 0; i < size; ++i) {                                           \
146       gchar *___s = NULL;                                                  \
147                                                                            \
148       fail_unless (gst_tag_list_get_string_index (list, field, i, &___s)); \
149       fail_unless (___s != NULL);                                          \
150       if (g_str_equal (___s, string)) {                                    \
151         got_match = TRUE;                                                  \
152         g_free (___s);                                                     \
153         break;                                                             \
154       }                                                                    \
155       g_free (___s);                                                       \
156     }                                                                      \
157     fail_unless (got_match);                                               \
158   }
159
160 #define ASSERT_TAG_LIST_HAS_UINT(list,field,num)                           \
161   {                                                                        \
162     guint ___n;                                                            \
163                                                                            \
164     fail_unless (gst_tag_list_get_tag_size (list,field) > 0);              \
165     fail_unless (gst_tag_list_get_tag_size (list,field) == 1);             \
166     fail_unless (gst_tag_list_get_uint_index (list, field, 0, &___n));     \
167     fail_unless_equals_int (___n, num);                                    \
168   }
169
170 #define MATCH_DOUBLE(p1, p2) ((p1 < p2 + 1e-6) && (p2 < p1 + 1e-6))
171 #define ASSERT_TAG_LIST_HAS_DOUBLE(list,field,d)                           \
172   {                                                                        \
173     gdouble ___d;                                                          \
174                                                                            \
175     fail_unless (gst_tag_list_get_tag_size (list,field) > 0);              \
176     fail_unless (gst_tag_list_get_tag_size (list,field) == 1);             \
177     fail_unless (gst_tag_list_get_double_index (list, field, 0, &___d));   \
178     fail_unless (MATCH_DOUBLE (d, ___d),                                   \
179         "%f does not match expected %f", ___d, d);                         \
180   }
181
182 GST_START_TEST (test_musicbrainz_tag_registration)
183 {
184   GstTagList *list;
185
186   gst_tag_register_musicbrainz_tags ();
187
188   list = gst_tag_list_new_empty ();
189
190   /* musicbrainz tags aren't registered yet */
191   gst_vorbis_tag_add (list, "MUSICBRAINZ_TRACKID", "123456");
192   gst_vorbis_tag_add (list, "MUSICBRAINZ_ARTISTID", "234567");
193   gst_vorbis_tag_add (list, "MUSICBRAINZ_ALBUMID", "345678");
194   gst_vorbis_tag_add (list, "MUSICBRAINZ_ALBUMARTISTID", "4567890");
195   gst_vorbis_tag_add (list, "MUSICBRAINZ_TRMID", "5678901");
196   /* MUSICBRAINZ_SORTNAME = GST_TAG_ARTIST_SORTNAME now */
197   gst_vorbis_tag_add (list, "MUSICBRAINZ_SORTNAME", "Five, 678901");
198
199   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_TRACKID, "123456");
200   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ARTISTID, "234567");
201   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ALBUMID, "345678");
202   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ALBUMARTISTID,
203       "4567890");
204   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_TRMID, "5678901");
205   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST_SORTNAME, "Five, 678901");
206
207   gst_tag_list_free (list);
208 }
209
210 GST_END_TEST;
211
212 /* is there an easier way to compare two structures / tagslists? */
213 static gboolean
214 taglists_are_equal (const GstTagList * list_1, const GstTagList * list_2)
215 {
216   GstCaps *c_list_1 = gst_caps_new_empty ();
217   GstCaps *c_list_2 = gst_caps_new_empty ();
218   gboolean ret;
219
220   gst_caps_append_structure (c_list_1,
221       gst_structure_copy ((GstStructure *) list_1));
222   gst_caps_append_structure (c_list_2,
223       gst_structure_copy ((GstStructure *) list_2));
224
225   ret = gst_caps_is_equal (c_list_2, c_list_1);
226
227   gst_caps_unref (c_list_1);
228   gst_caps_unref (c_list_2);
229
230   return ret;
231 }
232
233 GST_START_TEST (test_vorbis_tags)
234 {
235   GstTagList *list;
236
237   list = gst_tag_list_new_empty ();
238
239   /* NULL pointers aren't allowed */
240   ASSERT_CRITICAL (gst_vorbis_tag_add (NULL, "key", "value"));
241   ASSERT_CRITICAL (gst_vorbis_tag_add (list, NULL, "value"));
242   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key", NULL));
243
244   /* must be UTF-8 */
245   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key", "v\377lue"));
246   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "k\377y", "value"));
247
248   /* key can't have a '=' in it */
249   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "k=y", "value"));
250   ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key=", "value"));
251
252   /* should be allowed in values though */
253   gst_vorbis_tag_add (list, "keeey", "va=ue");
254
255   /* add some tags */
256   gst_vorbis_tag_add (list, "TITLE", "Too");
257   gst_vorbis_tag_add (list, "ALBUM", "Aoo");
258   gst_vorbis_tag_add (list, "ARTIST", "Alboo");
259   gst_vorbis_tag_add (list, "PERFORMER", "Perfoo");
260   gst_vorbis_tag_add (list, "COPYRIGHT", "Copyfoo");
261   gst_vorbis_tag_add (list, "DESCRIPTION", "Descoo");
262   gst_vorbis_tag_add (list, "LICENSE", "Licoo");
263   gst_vorbis_tag_add (list, "LICENSE",
264       "http://creativecommons.org/licenses/by/3.0/");
265   gst_vorbis_tag_add (list, "LOCATION", "Bristol, UK");
266   gst_vorbis_tag_add (list, "ORGANIZATION", "Orgoo");
267   gst_vorbis_tag_add (list, "GENRE", "Goo");
268   gst_vorbis_tag_add (list, "CONTACT", "Coo");
269   gst_vorbis_tag_add (list, "COMMENT", "Stroodle is good");
270   gst_vorbis_tag_add (list, "COMMENT", "Peroxysulfid stroodles the brain");
271
272   gst_vorbis_tag_add (list, "TRACKNUMBER", "5");
273   gst_vorbis_tag_add (list, "TRACKTOTAL", "77");
274   gst_vorbis_tag_add (list, "DISCNUMBER", "1");
275   gst_vorbis_tag_add (list, "DISCTOTAL", "2");
276   gst_vorbis_tag_add (list, "DATE", "1954-12-31");
277
278   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_TITLE, "Too");
279   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ALBUM, "Aoo");
280   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "Alboo");
281   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_PERFORMER, "Perfoo");
282   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COPYRIGHT, "Copyfoo");
283   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_DESCRIPTION, "Descoo");
284   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE, "Licoo");
285   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE_URI,
286       "http://creativecommons.org/licenses/by/3.0/");
287   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GEO_LOCATION_NAME, "Bristol, UK");
288   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ORGANIZATION, "Orgoo");
289   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GENRE, "Goo");
290   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_CONTACT, "Coo");
291   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COMMENT,
292       "Peroxysulfid stroodles the brain");
293   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COMMENT, "Stroodle is good");
294   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_TRACK_NUMBER, 5);
295   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_TRACK_COUNT, 77);
296   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_ALBUM_VOLUME_NUMBER, 1);
297   ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_ALBUM_VOLUME_COUNT, 2);
298
299   {
300     GDate *date = NULL;
301
302     fail_unless (gst_tag_list_get_date (list, GST_TAG_DATE, &date));
303     fail_unless (date != NULL);
304     fail_unless (g_date_get_day (date) == 31);
305     fail_unless (g_date_get_month (date) == G_DATE_DECEMBER);
306     fail_unless (g_date_get_year (date) == 1954);
307
308     g_date_free (date);
309   }
310
311   /* unknown vorbis comments should go into a GST_TAG_EXTENDED_COMMENT */
312   gst_vorbis_tag_add (list, "CoEdSub_ID", "98172AF-973-10-B");
313   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_EXTENDED_COMMENT,
314       "CoEdSub_ID=98172AF-973-10-B");
315   gst_vorbis_tag_add (list, "RuBuWuHash", "1337BA42F91");
316   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_EXTENDED_COMMENT,
317       "RuBuWuHash=1337BA42F91");
318
319   gst_vorbis_tag_add (list, "REPLAYGAIN_REFERENCE_LOUDNESS", "89.");
320   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_REFERENCE_LEVEL, 89.);
321   gst_vorbis_tag_add (list, "REPLAYGAIN_TRACK_GAIN", "+12.36");
322   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_TRACK_GAIN, +12.36);
323   gst_vorbis_tag_add (list, "REPLAYGAIN_TRACK_PEAK", "0.96349");
324   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_TRACK_PEAK, 0.96349);
325   gst_vorbis_tag_add (list, "REPLAYGAIN_ALBUM_GAIN", "+10.12");
326   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_ALBUM_GAIN, +10.12);
327   /* now check that we can parse floating point numbers with any separator
328    * (',' or '.') regardless of the current locale */
329   gst_vorbis_tag_add (list, "REPLAYGAIN_ALBUM_PEAK", "0,98107");
330   ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_ALBUM_PEAK, 0.98107);
331   gst_vorbis_tag_add (list, "LICENSE", "http://foo.com/license-1.html");
332
333   /* make sure we can convert back and forth without loss */
334   {
335     GstTagList *new_list, *even_newer_list;
336     GstBuffer *buf, *buf2;
337     gchar *vendor_id = NULL;
338
339     buf = gst_tag_list_to_vorbiscomment_buffer (list,
340         (const guint8 *) "\003vorbis", 7, "libgstunittest");
341     fail_unless (buf != NULL);
342     new_list = gst_tag_list_from_vorbiscomment_buffer (buf,
343         (const guint8 *) "\003vorbis", 7, &vendor_id);
344     fail_unless (new_list != NULL);
345     fail_unless (vendor_id != NULL);
346     g_free (vendor_id);
347     vendor_id = NULL;
348
349     GST_LOG ("new_list = %" GST_PTR_FORMAT, new_list);
350     fail_unless (taglists_are_equal (list, new_list));
351
352     buf2 = gst_tag_list_to_vorbiscomment_buffer (new_list,
353         (const guint8 *) "\003vorbis", 7, "libgstunittest");
354     fail_unless (buf2 != NULL);
355     even_newer_list = gst_tag_list_from_vorbiscomment_buffer (buf2,
356         (const guint8 *) "\003vorbis", 7, &vendor_id);
357     fail_unless (even_newer_list != NULL);
358     fail_unless (vendor_id != NULL);
359     g_free (vendor_id);
360     vendor_id = NULL;
361
362     GST_LOG ("even_newer_list = %" GST_PTR_FORMAT, even_newer_list);
363     fail_unless (taglists_are_equal (new_list, even_newer_list));
364
365     gst_tag_list_free (new_list);
366     gst_tag_list_free (even_newer_list);
367     gst_buffer_unref (buf);
368     gst_buffer_unref (buf2);
369   }
370
371   /* there can only be one language per taglist ... */
372   gst_tag_list_free (list);
373   list = gst_tag_list_new_empty ();
374   gst_vorbis_tag_add (list, "LANGUAGE", "fr");
375   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
376
377   gst_tag_list_free (list);
378   list = gst_tag_list_new_empty ();
379   gst_vorbis_tag_add (list, "LANGUAGE", "[fr]");
380   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
381
382   gst_tag_list_free (list);
383   list = gst_tag_list_new_empty ();
384   gst_vorbis_tag_add (list, "LANGUAGE", "French [fr]");
385   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr");
386
387   gst_tag_list_free (list);
388   list = gst_tag_list_new_empty ();
389   gst_vorbis_tag_add (list, "LANGUAGE", "[eng] English");
390   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
391
392   gst_tag_list_free (list);
393   list = gst_tag_list_new_empty ();
394   gst_vorbis_tag_add (list, "LANGUAGE", "eng");
395   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
396
397   gst_tag_list_free (list);
398   list = gst_tag_list_new_empty ();
399   gst_vorbis_tag_add (list, "LANGUAGE", "[eng]");
400   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng");
401
402   /* free-form *sigh* */
403   gst_tag_list_free (list);
404   list = gst_tag_list_new_empty ();
405   gst_vorbis_tag_add (list, "LANGUAGE", "English");
406   ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "English");
407
408   /* now, while we still have a taglist, test _to_vorbiscomment_buffer() */
409   {
410     GstBuffer *buf1, *buf2;
411     GstMapInfo map1, map2;
412
413     ASSERT_CRITICAL (gst_tag_list_to_vorbiscomment_buffer (NULL,
414             (const guint8 *) "x", 1, "x"));
415
416     buf1 = gst_tag_list_to_vorbiscomment_buffer (list, NULL, 0, NULL);
417     fail_unless (buf1 != NULL);
418
419     buf2 = gst_tag_list_to_vorbiscomment_buffer (list,
420         (const guint8 *) "foo", 3, NULL);
421     fail_unless (buf2 != NULL);
422
423     gst_buffer_map (buf1, &map1, GST_MAP_READ);
424     gst_buffer_map (buf2, &map2, GST_MAP_READ);
425
426     fail_unless (memcmp (map1.data, map2.data + 3, map1.size) == 0);
427
428     gst_buffer_unmap (buf2, &map2);
429     gst_buffer_unmap (buf1, &map1);
430
431     gst_buffer_unref (buf1);
432     gst_buffer_unref (buf2);
433   }
434
435   gst_tag_list_free (list);
436
437   /* make sure gst_tag_list_from_vorbiscomment_buffer() works with an
438    * empty ID (for Speex) */
439   {
440     const guint8 speex_comments_buf1[] = { 0x03, 0x00, 0x00, 0x00, 'f', 'o',
441       'o', 0x00, 0x00, 0x00, 0x00
442     };
443     GstBuffer *buf;
444     gchar *vendor = NULL;
445
446     buf = gst_buffer_new ();
447     gst_buffer_take_memory (buf, -1,
448         gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
449             (gpointer) speex_comments_buf1,
450             sizeof (speex_comments_buf1), 0, sizeof (speex_comments_buf1), NULL,
451             NULL));
452
453     /* make sure it doesn't memcmp over the end of the buffer */
454     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
455             (const guint8 *) "averylongstringbrownfoxjumpoverthefence", 39,
456             &vendor) == NULL);
457     fail_unless (vendor == NULL);
458
459     /* make sure it bails out if the ID doesn't match */
460     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
461             (guint8 *) "short", 4, &vendor) == NULL);
462     fail_unless (vendor == NULL);
463
464     /* now read properly */
465     list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, &vendor);
466     fail_unless (vendor != NULL);
467     fail_unless_equals_string (vendor, "foo");
468     fail_unless (list != NULL);
469     fail_unless (gst_structure_n_fields ((GstStructure *) list) == 0);
470     g_free (vendor);
471     gst_tag_list_free (list);
472
473     /* now again without vendor */
474     list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, NULL);
475     fail_unless (list != NULL);
476     fail_unless (gst_structure_n_fields ((GstStructure *) list) == 0);
477     gst_tag_list_free (list);
478
479     gst_buffer_unref (buf);
480   }
481
482   /* the same with an ID */
483   {
484     const guint8 vorbis_comments_buf[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's',
485       0x03, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x01, 0x00, 0x00, 0x00,
486       strlen ("ARTIST=foo bar"), 0x00, 0x00, 0x00, 'A', 'R', 'T', 'I', 'S',
487       'T', '=', 'f', 'o', 'o', ' ', 'b', 'a', 'r'
488     };
489     GstBuffer *buf;
490     gchar *vendor = NULL;
491
492     buf = gst_buffer_new ();
493     gst_buffer_take_memory (buf, -1,
494         gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
495             (gpointer) vorbis_comments_buf,
496             sizeof (vorbis_comments_buf), 0, sizeof (vorbis_comments_buf), NULL,
497             NULL));
498
499     /* make sure it doesn't memcmp over the end of the buffer */
500     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
501             (const guint8 *) "averylongstringbrownfoxjumpoverthefence", 39,
502             &vendor) == NULL);
503     fail_unless (vendor == NULL);
504
505     /* make sure it bails out if the ID doesn't match */
506     fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf,
507             (guint8 *) "short", 4, &vendor) == NULL);
508     fail_unless (vendor == NULL);
509
510     /* now read properly */
511     list = gst_tag_list_from_vorbiscomment_buffer (buf,
512         (guint8 *) "\003vorbis", 7, &vendor);
513     fail_unless (vendor != NULL);
514     fail_unless_equals_string (vendor, "foo");
515     fail_unless (list != NULL);
516     fail_unless (gst_structure_n_fields ((GstStructure *) list) == 1);
517     ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "foo bar");
518     g_free (vendor);
519     gst_tag_list_free (list);
520
521     /* now again without vendor */
522     list = gst_tag_list_from_vorbiscomment_buffer (buf,
523         (guint8 *) "\003vorbis", 7, NULL);
524     fail_unless (list != NULL);
525     fail_unless (gst_structure_n_fields ((GstStructure *) list) == 1);
526     ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "foo bar");
527     gst_tag_list_free (list);
528
529     gst_buffer_unref (buf);
530   }
531
532   /* check date with time */
533   {
534     GDate *date = NULL;
535
536     list = gst_tag_list_new_empty ();
537     gst_vorbis_tag_add (list, "DATE", "2006-09-25 22:02:38");
538
539     fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date));
540     fail_unless (date != NULL);
541     fail_unless (g_date_get_day (date) == 25);
542     fail_unless (g_date_get_month (date) == G_DATE_SEPTEMBER);
543     fail_unless (g_date_get_year (date) == 2006);
544
545     g_date_free (date);
546     gst_tag_list_free (list);
547   }
548
549   /* check date with month/day of 00-00 */
550   {
551     GDate *date = NULL;
552
553     list = gst_tag_list_new_empty ();
554     gst_vorbis_tag_add (list, "DATE", "1992-00-00");
555
556     fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date));
557     fail_unless (date != NULL);
558     fail_unless (g_date_get_year (date) == 1992);
559
560     g_date_free (date);
561     gst_tag_list_free (list);
562   }
563
564   /* check date with valid month, but day of 00 */
565   {
566     GDate *date = NULL;
567
568     list = gst_tag_list_new_empty ();
569     gst_vorbis_tag_add (list, "DATE", "1992-05-00");
570
571     fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date));
572     fail_unless (date != NULL);
573     fail_unless (g_date_get_year (date) == 1992);
574     fail_unless (g_date_get_month (date) == G_DATE_MAY);
575
576     g_date_free (date);
577     gst_tag_list_free (list);
578   }
579 }
580
581 GST_END_TEST;
582
583 GST_START_TEST (test_id3_tags)
584 {
585   guint i;
586
587   fail_unless (gst_tag_id3_genre_count () > 0);
588
589   for (i = 0; i < gst_tag_id3_genre_count (); ++i) {
590     const gchar *genre;
591
592     genre = gst_tag_id3_genre_get (i);
593     GST_LOG ("genre: %s", genre);
594     fail_unless (genre != NULL);
595   }
596
597   {
598     /* TODO: GstTagList *gst_tag_list_new_from_id3v1 (const guint8 *data) */
599   }
600
601   /* gst_tag_from_id3_tag */
602   fail_unless (gst_tag_from_id3_tag ("TALB") != NULL);
603   ASSERT_CRITICAL (gst_tag_from_id3_tag (NULL));
604   fail_unless (gst_tag_from_id3_tag ("R2D2") == NULL);
605   fail_unless_equals_string (gst_tag_from_id3_tag ("WCOP"),
606       GST_TAG_COPYRIGHT_URI);
607
608   /* gst_tag_from_id3_user_tag */
609   ASSERT_CRITICAL (gst_tag_from_id3_user_tag (NULL, "foo"));
610   ASSERT_CRITICAL (gst_tag_from_id3_user_tag ("foo", NULL));
611   fail_unless (gst_tag_from_id3_user_tag ("R2D2", "R2D2") == NULL);
612
613   /* gst_tag_to_id3_tag */
614   ASSERT_CRITICAL (gst_tag_to_id3_tag (NULL));
615   fail_unless (gst_tag_to_id3_tag ("R2D2") == NULL);
616   fail_unless (gst_tag_to_id3_tag (GST_TAG_ARTIST) != NULL);
617   fail_unless_equals_string (gst_tag_to_id3_tag (GST_TAG_COPYRIGHT_URI),
618       "WCOP");
619
620   fail_unless (GST_TYPE_TAG_IMAGE_TYPE != 0);
621   fail_unless (g_type_name (GST_TYPE_TAG_IMAGE_TYPE) != NULL);
622 }
623
624 GST_END_TEST;
625
626
627 GST_START_TEST (test_id3v1_utf8_tag)
628 {
629   const guint8 id3v1[128] = {
630     /* marker */
631     'T', 'A', 'G',
632     /* title (30 bytes) */
633     'D', 0xc3, 0xad, 'v', 'k', 'a', ' ', 's',
634     ' ', 'p', 'e', 'r', 'l', 'a', 'm', 'i',
635     ' ', 'v', 'e', ' ', 'v', 'l', 'a', 's',
636     'e', 'c', 'h', 0, 0, 0,
637     /* artist (30 bytes) */
638     'A', 'l', 'e', 0xc5, 0xa1, ' ', 'B', 'r', 'i', 'c', 'h', 't', 'a',
639     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
640     /* album (30 bytes) */
641     'B', 'e', 's', 't', ' ', 'o', 'f', ' ', '(', 'P', 'r', 'o', 's', 't',
642     0xc4, 0x9b, ' ', 0xc3, 0xba, 0xc5, 0xbe, 'a', 's', 'n', 0xc3, 0xbd, ')',
643     0, 0, 0,
644     /* year (4 bytes) */
645     '2', '0', '0', '0',
646     /* comment (28 bytes) */
647     '-', '-', '-', ' ', 0xc4, 0x8d, 'e', 's', 'k', 0xc3, 0xa9, ' ', 'p',
648     0xc3, 0xad, 's', 'n', 'i', 0xc4, 0x8d, 'k', 'y', ' ', '-', '-', '-',
649     0, 0,
650     /* track number */
651     0, 0,
652     /* genre */
653     0x11
654   };
655   GstTagList *tags;
656   GDate *d;
657   gchar *s;
658
659   /* set this, to make sure UTF-8 strings are really interpreted properly
660    * as UTF-8, regardless of the locale set */
661   g_setenv ("GST_ID3V1_TAG_ENCODING", "WINDOWS-1250", TRUE);
662
663   tags = gst_tag_list_new_from_id3v1 (id3v1);
664   fail_unless (tags != NULL);
665
666   GST_LOG ("Got tags: %" GST_PTR_FORMAT, tags);
667
668   s = NULL;
669   fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &s));
670   fail_unless (s != NULL);
671   fail_unless_equals_string (s, "Dívka s perlami ve vlasech");
672   g_free (s);
673
674   s = NULL;
675   fail_unless (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &s));
676   fail_unless (s != NULL);
677   fail_unless_equals_string (s, "Aleš Brichta");
678   g_free (s);
679
680   s = NULL;
681   fail_unless (gst_tag_list_get_string (tags, GST_TAG_ALBUM, &s));
682   fail_unless (s != NULL);
683   fail_unless_equals_string (s, "Best of (Prostě úžasný)");
684   g_free (s);
685
686   d = NULL;
687   fail_unless (gst_tag_list_get_date (tags, GST_TAG_DATE, &d));
688   fail_unless (d != NULL);
689   fail_unless_equals_int (g_date_get_year (d), 2000);
690   g_date_free (d);
691   d = NULL;
692
693   gst_tag_list_free (tags);
694
695   g_unsetenv ("GST_ID3V1_TAG_ENCODING");
696 }
697
698 GST_END_TEST;
699
700 GST_START_TEST (test_language_utils)
701 {
702   gchar **lang_codes, **c;
703
704 #define ASSERT_STRINGS_EQUAL fail_unless_equals_string
705
706   lang_codes = gst_tag_get_language_codes ();
707   fail_unless (lang_codes != NULL);
708   fail_unless (*lang_codes != NULL);
709
710   for (c = lang_codes; c != NULL && *c != NULL; ++c) {
711     const gchar *lang_name, *c1, *c2t, *c2b;
712
713     lang_name = gst_tag_get_language_name (*c);
714     fail_unless (lang_name != NULL);
715     fail_unless (g_utf8_validate (lang_name, -1, NULL));
716
717     c1 = gst_tag_get_language_code_iso_639_1 (*c);
718     fail_unless (c1 != NULL);
719     fail_unless (g_utf8_validate (c1, -1, NULL));
720
721     c2t = gst_tag_get_language_code_iso_639_2T (*c);
722     fail_unless (c2t != NULL);
723     fail_unless (g_utf8_validate (c2t, -1, NULL));
724
725     c2b = gst_tag_get_language_code_iso_639_2B (*c);
726     fail_unless (c2b != NULL);
727     fail_unless (g_utf8_validate (c2b, -1, NULL));
728
729     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (*c), *c);
730     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2t), *c);
731     ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2b), *c);
732
733     GST_DEBUG ("[%s] %s %s %s : %s\n", *c, c1, c2t, c2b, lang_name);
734
735   }
736   g_strfreev (lang_codes);
737
738   fail_unless (gst_tag_get_language_name ("de") != NULL);
739   fail_unless (gst_tag_get_language_name ("deu") != NULL);
740   fail_unless (gst_tag_get_language_name ("ger") != NULL);
741   fail_unless_equals_string (gst_tag_get_language_name ("deu"),
742       gst_tag_get_language_name ("ger"));
743   fail_unless_equals_string (gst_tag_get_language_name ("de"),
744       gst_tag_get_language_name ("ger"));
745   fail_unless (gst_tag_get_language_name ("de") !=
746       gst_tag_get_language_name ("fr"));
747
748   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("deu"), "de");
749   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("de"), "de");
750   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("ger"), "de");
751
752   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("deu"), "de");
753   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("de"), "de");
754   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("ger"), "de");
755
756   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("de"), "deu");
757   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("deu"), "deu");
758   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("ger"), "deu");
759
760   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("de"), "ger");
761   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("deu"), "ger");
762   ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("ger"), "ger");
763
764   fail_unless (gst_tag_check_language_code ("de"));
765   fail_unless (gst_tag_check_language_code ("deu"));
766   fail_unless (gst_tag_check_language_code ("ger"));
767   fail_if (gst_tag_check_language_code ("xxx"));
768   fail_if (gst_tag_check_language_code ("und"));
769   fail_if (gst_tag_check_language_code ("un"));
770   fail_if (gst_tag_check_language_code (""));
771   fail_if (gst_tag_check_language_code ("\377"));
772   fail_if (gst_tag_check_language_code ("deutsch"));
773 }
774
775 GST_END_TEST;
776
777 #define SPECIFIC_L "http://creativecommons.org/licenses/by-nc-sa/2.5/scotland/"
778 #define GENERIC_L "http://creativecommons.org/licenses/by/1.0/"
779 #define DERIVED_L "http://creativecommons.org/licenses/sampling+/1.0/tw/"
780
781 GST_START_TEST (test_license_utils)
782 {
783   GHashTable *ht;
784   GError *err = NULL;
785   gchar **liblicense_refs, **r;
786   gchar **lrefs, **l;
787   gchar *path, *data = NULL;
788   gsize data_len;
789
790   gst_debug_set_threshold_for_name ("tag-licenses", GST_LEVEL_NONE);
791
792   /* test jurisdiction-specific license */
793   fail_unless_equals_int (gst_tag_get_license_flags (SPECIFIC_L), 0x01010703);
794   fail_unless_equals_string (gst_tag_get_license_nick (SPECIFIC_L),
795       "CC BY-NC-SA 2.5 SCOTLAND");
796   fail_unless_equals_string (gst_tag_get_license_version (SPECIFIC_L), "2.5");
797   fail_unless_equals_string (gst_tag_get_license_jurisdiction (SPECIFIC_L),
798       "scotland");
799
800   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
801   fail_unless_equals_string (gst_tag_get_license_title (SPECIFIC_L),
802       "Attribution-NonCommercial-ShareAlike");
803   fail_unless (gst_tag_get_license_description (SPECIFIC_L) == NULL);
804
805   /* test generic license */
806   fail_unless_equals_int (gst_tag_get_license_flags (GENERIC_L), 0x01000307);
807   fail_unless_equals_string (gst_tag_get_license_nick (GENERIC_L), "CC BY 1.0");
808   fail_unless_equals_string (gst_tag_get_license_version (GENERIC_L), "1.0");
809   fail_unless (gst_tag_get_license_jurisdiction (GENERIC_L) == NULL);
810
811   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
812   fail_unless_equals_string (gst_tag_get_license_title (GENERIC_L),
813       "Attribution");
814   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
815       "You must attribute the work in the manner specified by the author or licensor.");
816
817 #ifdef ENABLE_NLS
818   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "fr", TRUE);
819   fail_unless_equals_string (gst_tag_get_license_title (GENERIC_L),
820       "Paternité");
821   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
822       "L'offrant autorise les autres à reproduire, distribuer et communiquer cette création au public. En échange, les personnes qui acceptent ce contrat doivent citer le nom de l'auteur original.");
823 #endif
824
825   /* test derived (for a certain jurisdiction) license */
826   fail_unless_equals_int (gst_tag_get_license_flags (DERIVED_L), 0x0100030d);
827   fail_unless_equals_string (gst_tag_get_license_nick (DERIVED_L),
828       "CC SAMPLING+ 1.0 TW");
829   fail_unless_equals_string (gst_tag_get_license_version (DERIVED_L), "1.0");
830   fail_unless_equals_string (gst_tag_get_license_jurisdiction (DERIVED_L),
831       "tw");
832
833   g_setenv ("GST_TAG_LICENSE_TRANSLATIONS_LANG", "C", TRUE);
834   fail_unless_equals_string (gst_tag_get_license_title (DERIVED_L),
835       "Sampling Plus");
836   fail_unless_equals_string (gst_tag_get_license_description (GENERIC_L),
837       "You must attribute the work in the manner specified by the author or licensor.");
838
839   /* test all we know about */
840   lrefs = gst_tag_get_licenses ();
841   fail_unless (lrefs != NULL);
842   fail_unless (*lrefs != NULL);
843
844   GST_INFO ("%d licenses", g_strv_length (lrefs));
845   fail_unless (g_strv_length (lrefs) >= 376);
846
847   ht = g_hash_table_new (g_str_hash, g_str_equal);
848
849   for (l = lrefs; l != NULL && *l != NULL; ++l) {
850     const gchar *ref, *nick, *title, *desc G_GNUC_UNUSED;
851
852     ref = (const gchar *) *l;
853     nick = gst_tag_get_license_nick (ref);
854     title = gst_tag_get_license_title (ref);
855     desc = gst_tag_get_license_description (ref);
856     fail_unless (nick != NULL, "no nick for license '%s'", ref);
857     fail_unless (title != NULL, "no title for license '%s'", ref);
858     GST_LOG ("ref: %s [nick %s]", ref, (nick) ? nick : "none");
859     GST_TRACE ("    %s : %s", title, (desc) ? desc : "(no description)");
860
861     /* make sure the list contains no duplicates */
862     fail_if (g_hash_table_lookup (ht, (gpointer) ref) != NULL);
863     g_hash_table_insert (ht, (gpointer) ref, (gpointer) "meep");
864   }
865   g_hash_table_destroy (ht);
866
867   /* trailing slash shouldn't make a difference */
868   fail_unless_equals_int (gst_tag_get_license_flags
869       ("http://creativecommons.org/licenses/by-nd/1.0/"),
870       gst_tag_get_license_flags
871       ("http://creativecommons.org/licenses/by-nd/1.0"));
872   fail_unless_equals_string (gst_tag_get_license_nick
873       ("http://creativecommons.org/licenses/by-nd/1.0/"),
874       gst_tag_get_license_nick
875       ("http://creativecommons.org/licenses/by-nd/1.0"));
876   fail_unless_equals_int (gst_tag_get_license_flags
877       ("http://creativecommons.org/licenses/by-nd/2.5/ca/"),
878       gst_tag_get_license_flags
879       ("http://creativecommons.org/licenses/by-nd/2.5/ca"));
880   fail_unless_equals_string (gst_tag_get_license_nick
881       ("http://creativecommons.org/licenses/by-nd/2.5/ca/"),
882       gst_tag_get_license_nick
883       ("http://creativecommons.org/licenses/by-nd/2.5/ca"));
884
885   /* unknown licenses */
886   fail_unless (gst_tag_get_license_nick
887       ("http://creativecommons.org/licenses/by-nd/25/ca/") == NULL);
888   fail_unless (gst_tag_get_license_flags
889       ("http://creativecommons.org/licenses/by-nd/25/ca") == 0);
890   fail_unless (gst_tag_get_license_jurisdiction
891       ("http://creativecommons.org/licenses/by-nd/25/ca/") == NULL);
892   fail_unless (gst_tag_get_license_jurisdiction
893       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
894   fail_unless (gst_tag_get_license_title
895       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
896   fail_unless (gst_tag_get_license_jurisdiction
897       ("http://creativecommons.org/licenses/by-nd/25/ca") == NULL);
898
899   /* unknown prefixes even */
900   fail_unless (gst_tag_get_license_nick
901       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
902   fail_unless (gst_tag_get_license_flags
903       ("http://copycats.org/licenses/by-nd/2.5/ca") == 0);
904   fail_unless (gst_tag_get_license_jurisdiction
905       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
906   fail_unless (gst_tag_get_license_title
907       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
908   fail_unless (gst_tag_get_license_description
909       ("http://copycats.org/licenses/by-nd/2.5/ca/") == NULL);
910
911   /* read list of liblicense refs from file */
912   path = g_build_filename (GST_TEST_FILES_PATH, "license-uris", NULL);
913   GST_LOG ("reading file '%s'", path);
914   if (!g_file_get_contents (path, &data, &data_len, &err)) {
915     g_error ("error loading test file: %s", err->message);
916   }
917
918   while (data_len > 0 && data[data_len - 1] == '\n') {
919     data[--data_len] = '\0';
920   }
921
922   liblicense_refs = g_strsplit (data, "\n", -1);
923   g_free (data);
924   g_free (path);
925
926   fail_unless (g_strv_length (lrefs) >= g_strv_length (liblicense_refs));
927
928   for (r = liblicense_refs; r != NULL && *r != NULL; ++r) {
929     GstTagLicenseFlags flags;
930     const gchar *version, *nick, *jur;
931     const gchar *ref = *r;
932
933     GST_LOG ("liblicense ref: %s", ref);
934
935     version = gst_tag_get_license_version (ref);
936     if (strstr (ref, "publicdomain") != NULL)
937       fail_unless (version == NULL);
938     else
939       fail_unless (version != NULL, "expected version for license %s", ref);
940
941     flags = gst_tag_get_license_flags (ref);
942     fail_unless (flags != 0, "expected non-zero flags for license %s", ref);
943
944     nick = gst_tag_get_license_nick (ref);
945     fail_unless (nick != NULL, "expected nick for license %s", ref);
946
947     jur = gst_tag_get_license_jurisdiction (ref);
948     if (g_str_has_suffix (ref, "de/")) {
949       fail_unless_equals_string (jur, "de");
950     } else if (g_str_has_suffix (ref, "scotland")) {
951       fail_unless_equals_string (jur, "scotland");
952     } else if (g_str_has_suffix (ref, ".0") || g_str_has_suffix (ref, ".1")) {
953       fail_unless (jur == NULL);
954     }
955   }
956
957   g_strfreev (liblicense_refs);
958   g_strfreev (lrefs);
959 }
960
961 GST_END_TEST;
962
963 GST_START_TEST (test_xmp_formatting)
964 {
965   GstTagList *list;
966   GstBuffer *buf;
967   GstMapInfo map;
968   const gchar *text;
969   gsize len;
970
971   /* test data */
972   list = gst_tag_list_new (GST_TAG_TITLE, "test title",
973       GST_TAG_DESCRIPTION, "test decription",
974       GST_TAG_KEYWORDS, "keyword1", GST_TAG_KEYWORDS, "keyword2", NULL);
975
976   buf = gst_tag_list_to_xmp_buffer (list, FALSE);
977   fail_unless (buf != NULL);
978
979   gst_buffer_map (buf, &map, GST_MAP_READ);
980   text = (gchar *) map.data;
981   len = map.size;
982
983   /* check the content */
984   fail_unless (g_strrstr_len (text, len, "<?xpacket begin") == text);
985   fail_unless (g_strrstr_len (text, len, ">test title<") != NULL);
986   fail_unless (g_strrstr_len (text, len, ">test decription<") != NULL);
987   fail_unless (g_strrstr_len (text, len, ">keyword1<") != NULL);
988   fail_unless (g_strrstr_len (text, len, ">keyword2<") != NULL);
989   fail_unless (g_strrstr_len (text, len, "<?xpacket end") != NULL);
990   gst_buffer_unmap (buf, &map);
991
992   gst_buffer_unref (buf);
993   gst_tag_list_free (list);
994 }
995
996 GST_END_TEST;
997
998
999 GST_START_TEST (test_xmp_parsing)
1000 {
1001   GstTagList *list;
1002   GstBuffer *buf;
1003   guint i, j, result_size;
1004   gchar *text;
1005   const gchar *xmp_header =
1006       "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>"
1007       "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"GStreamer\">"
1008       "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
1009
1010   /* We used to write an extra trailing \n after the footer, keep compatibility
1011    * with our old generated media by checking that it still can be parsed */
1012   const gchar *xmp_footers[] = {
1013     "</rdf:RDF>" "</x:xmpmeta>" "<?xpacket end=\"r\"?>",
1014     "</rdf:RDF>" "</x:xmpmeta>" "<?xpacket end=\"r\"?>\n",
1015     NULL
1016   };
1017
1018   struct
1019   {
1020     const gchar *xmp_data;
1021     gint result_size;
1022     gint result_test;
1023   } test_data[] = {
1024     {
1025     "", -1, -1}, {
1026     "<rdf:Description rdf:about=\"\" />", 0, -1}, {
1027     "<rdf:Description rdf:about=\"\"></rdf:Description>", 0, -1}, {
1028     "<rdf:Description    rdf:about=\"\"    ></rdf:Description>", 0, -1}, {
1029     "<rdf:Description rdf:about=\"\"><dc:description>test</dc:description></rdf:Description>",
1030           1, 0}, {
1031     "<rdf:Description rdf:about=\"\" dc:description=\"test\"></rdf:Description>",
1032           1, 0}, {
1033     NULL, -1, -1}
1034   };
1035
1036   /* test data */
1037   j = 0;
1038   i = 0;
1039   while (xmp_footers[j]) {
1040     while (test_data[i].xmp_data) {
1041       gsize len;
1042
1043       GST_DEBUG ("trying test-data %u", i);
1044
1045       text =
1046           g_strconcat (xmp_header, test_data[i].xmp_data, xmp_footers[j], NULL);
1047
1048       buf = gst_buffer_new ();
1049       len = strlen (text) + 1;
1050       gst_buffer_take_memory (buf, -1,
1051           gst_memory_new_wrapped (0, text, len, 0, len, NULL, NULL));
1052
1053       list = gst_tag_list_from_xmp_buffer (buf);
1054       if (test_data[i].result_size >= 0) {
1055         fail_unless (list != NULL);
1056
1057         result_size = gst_structure_n_fields ((GstStructure *) list);
1058         fail_unless (result_size == test_data[i].result_size);
1059
1060         /* check the taglist content */
1061         switch (test_data[i].result_test) {
1062           case 0:
1063             ASSERT_TAG_LIST_HAS_STRING (list, "description", "test");
1064             break;
1065           default:
1066             break;
1067         }
1068       }
1069       if (list)
1070         gst_tag_list_free (list);
1071
1072       gst_buffer_unref (buf);
1073       g_free (text);
1074       i++;
1075     }
1076     j++;
1077   }
1078 }
1079
1080 GST_END_TEST;
1081
1082 static void
1083 do_xmp_tag_serialization_deserialization (GstTagList * taglist,
1084     const gchar ** schemas)
1085 {
1086   GstTagList *taglist2;
1087   GstBuffer *buf;
1088
1089   buf = gst_tag_list_to_xmp_buffer_full (taglist, TRUE, schemas);
1090   taglist2 = gst_tag_list_from_xmp_buffer (buf);
1091
1092   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1093
1094   gst_buffer_unref (buf);
1095   gst_tag_list_free (taglist2);
1096 }
1097
1098 static void
1099 do_simple_xmp_tag_serialization_deserialization (const gchar * gsttag,
1100     GValue * value)
1101 {
1102   GstTagList *taglist = gst_tag_list_new_empty ();
1103
1104   gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
1105
1106   do_xmp_tag_serialization_deserialization (taglist, NULL);
1107   gst_tag_list_free (taglist);
1108 }
1109
1110 GST_START_TEST (test_xmp_tags_serialization_deserialization)
1111 {
1112   GValue value = { 0 };
1113   GDate *date;
1114   GstDateTime *datetime;
1115
1116   gst_tag_register_musicbrainz_tags ();
1117
1118   g_value_init (&value, G_TYPE_STRING);
1119   g_value_set_static_string (&value, "my string");
1120   do_simple_xmp_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1121   do_simple_xmp_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
1122   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DESCRIPTION, &value);
1123   do_simple_xmp_tag_serialization_deserialization (GST_TAG_KEYWORDS, &value);
1124   do_simple_xmp_tag_serialization_deserialization (GST_TAG_TITLE, &value);
1125   do_simple_xmp_tag_serialization_deserialization (GST_TAG_VIDEO_CODEC, &value);
1126   do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_COUNTRY,
1127       &value);
1128   do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_CITY,
1129       &value);
1130   do_simple_xmp_tag_serialization_deserialization
1131       (GST_TAG_GEO_LOCATION_SUBLOCATION, &value);
1132   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MANUFACTURER,
1133       &value);
1134   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MODEL,
1135       &value);
1136   do_simple_xmp_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME,
1137       &value);
1138
1139   g_value_set_static_string (&value, "rotate-0");
1140   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1141       &value);
1142   g_value_set_static_string (&value, "flip-rotate-0");
1143   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1144       &value);
1145   g_value_set_static_string (&value, "rotate-180");
1146   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1147       &value);
1148   g_value_set_static_string (&value, "flip-rotate-180");
1149   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1150       &value);
1151   g_value_set_static_string (&value, "flip-rotate-270");
1152   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1153       &value);
1154   g_value_set_static_string (&value, "rotate-90");
1155   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1156       &value);
1157   g_value_set_static_string (&value, "flip-rotate-90");
1158   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1159       &value);
1160   g_value_set_static_string (&value, "rotate-270");
1161   do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1162       &value);
1163
1164   g_value_unset (&value);
1165   g_value_init (&value, G_TYPE_DOUBLE);
1166
1167   g_value_set_double (&value, 0.0);
1168   do_simple_xmp_tag_serialization_deserialization
1169       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1170   do_simple_xmp_tag_serialization_deserialization
1171       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1172   g_value_set_double (&value, 10.5);
1173   do_simple_xmp_tag_serialization_deserialization
1174       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1175   do_simple_xmp_tag_serialization_deserialization
1176       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1177   g_value_set_double (&value, -32.375);
1178   do_simple_xmp_tag_serialization_deserialization
1179       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1180   do_simple_xmp_tag_serialization_deserialization
1181       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1182
1183   g_value_set_double (&value, 0);
1184   do_simple_xmp_tag_serialization_deserialization
1185       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1186   g_value_set_double (&value, 100);
1187   do_simple_xmp_tag_serialization_deserialization
1188       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1189   g_value_set_double (&value, 500.25);
1190   do_simple_xmp_tag_serialization_deserialization
1191       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1192   g_value_set_double (&value, -12.75);
1193   do_simple_xmp_tag_serialization_deserialization
1194       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1195
1196   g_value_set_double (&value, 0.0);
1197   do_simple_xmp_tag_serialization_deserialization
1198       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1199   g_value_set_double (&value, 10.0);
1200   do_simple_xmp_tag_serialization_deserialization
1201       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1202   g_value_set_double (&value, 786.125);
1203   do_simple_xmp_tag_serialization_deserialization
1204       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1205   g_value_set_double (&value, -2.5);
1206   do_simple_xmp_tag_serialization_deserialization
1207       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1208
1209   g_value_set_double (&value, 0.0);
1210   do_simple_xmp_tag_serialization_deserialization
1211       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1212   g_value_set_double (&value, 180.0);
1213   do_simple_xmp_tag_serialization_deserialization
1214       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1215   g_value_set_double (&value, 359.99);
1216   do_simple_xmp_tag_serialization_deserialization
1217       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1218
1219   g_value_set_double (&value, 0.0);
1220   do_simple_xmp_tag_serialization_deserialization
1221       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1222   g_value_set_double (&value, 90.0);
1223   do_simple_xmp_tag_serialization_deserialization
1224       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1225   g_value_set_double (&value, 359.99);
1226   do_simple_xmp_tag_serialization_deserialization
1227       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1228
1229   g_value_set_double (&value, 0.0);
1230   do_simple_xmp_tag_serialization_deserialization
1231       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1232   g_value_set_double (&value, 1.0);
1233   do_simple_xmp_tag_serialization_deserialization
1234       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1235   g_value_set_double (&value, -2.5);
1236   do_simple_xmp_tag_serialization_deserialization
1237       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1238   g_value_unset (&value);
1239
1240   g_value_init (&value, G_TYPE_DATE);
1241   date = g_date_new_dmy (22, 3, 2010);
1242   g_value_set_boxed (&value, date);
1243   g_date_free (date);
1244   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE, &value);
1245   g_value_unset (&value);
1246
1247   g_value_init (&value, G_TYPE_UINT);
1248   g_value_set_uint (&value, 0);
1249   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1250   g_value_set_uint (&value, 100);
1251   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1252   g_value_set_uint (&value, 22);
1253   do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value);
1254   g_value_unset (&value);
1255
1256   g_value_init (&value, GST_TYPE_DATE_TIME);
1257   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10);
1258   g_value_set_boxed (&value, datetime);
1259   gst_date_time_unref (datetime);
1260   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1261   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000125);
1262   g_value_set_boxed (&value, datetime);
1263   gst_date_time_unref (datetime);
1264   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1265   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000001);
1266   g_value_set_boxed (&value, datetime);
1267   gst_date_time_unref (datetime);
1268   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1269   datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.123456);
1270   g_value_set_boxed (&value, datetime);
1271   gst_date_time_unref (datetime);
1272   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1273   datetime = gst_date_time_new (-3, 2010, 6, 22, 12, 5, 10.123456);
1274   g_value_set_boxed (&value, datetime);
1275   gst_date_time_unref (datetime);
1276   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1277   datetime = gst_date_time_new (5, 2010, 6, 22, 12, 5, 10.123456);
1278   g_value_set_boxed (&value, datetime);
1279   gst_date_time_unref (datetime);
1280   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1281   datetime = gst_date_time_new_local_time (2010, 12, 2, 12, 5, 10.000043);
1282   g_value_set_boxed (&value, datetime);
1283   gst_date_time_unref (datetime);
1284   do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1285   g_value_unset (&value);
1286 }
1287
1288 GST_END_TEST;
1289
1290
1291 GST_START_TEST (test_xmp_compound_tags)
1292 {
1293   const gchar *schemas[] = { "Iptc4xmpExt", NULL };
1294   GstTagList *taglist = gst_tag_list_new_empty ();
1295
1296   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_KEYWORDS, "k1",
1297       GST_TAG_KEYWORDS, "k2", GST_TAG_TITLE, "title", GST_TAG_KEYWORDS, "k3",
1298       NULL);
1299   do_xmp_tag_serialization_deserialization (taglist, NULL);
1300   gst_tag_list_free (taglist);
1301
1302   taglist = gst_tag_list_new_empty ();
1303   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_GEO_LOCATION_COUNTRY,
1304       "Brazil", GST_TAG_GEO_LOCATION_CITY, "Campina Grande", NULL);
1305   do_xmp_tag_serialization_deserialization (taglist, schemas);
1306   gst_tag_list_free (taglist);
1307 }
1308
1309 GST_END_TEST;
1310
1311
1312 GST_START_TEST (test_exif_parsing)
1313 {
1314   GstTagList *taglist;
1315   GstBuffer *buf;
1316   GstByteWriter writer;
1317   const gchar *str = NULL;
1318
1319   gst_byte_writer_init (&writer);
1320
1321   /* write the IFD */
1322   /* 1 entry */
1323   gst_byte_writer_put_uint16_le (&writer, 1);
1324
1325   /* copyright tag */
1326   /* tag id */
1327   gst_byte_writer_put_uint16_le (&writer, 0x8298);
1328   /* tag type */
1329   gst_byte_writer_put_uint16_le (&writer, 0x2);
1330   /* count */
1331   gst_byte_writer_put_uint32_le (&writer, strlen ("my copyright") + 1);
1332   /* offset */
1333   gst_byte_writer_put_uint32_le (&writer, 8 + 14);
1334
1335   /* data */
1336   gst_byte_writer_put_string (&writer, "my copyright");
1337
1338   buf = gst_byte_writer_reset_and_get_buffer (&writer);
1339
1340   taglist = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 8);
1341
1342   fail_unless (gst_tag_list_get_tag_size (taglist, GST_TAG_COPYRIGHT) == 1);
1343   gst_tag_list_peek_string_index (taglist, GST_TAG_COPYRIGHT, 0, &str);
1344   fail_unless_equals_string (str, "my copyright");
1345
1346   gst_tag_list_free (taglist);
1347   gst_buffer_unref (buf);
1348 }
1349
1350 GST_END_TEST;
1351
1352
1353 static void
1354 do_exif_tag_serialization_deserialization (GstTagList * taglist)
1355 {
1356   GstTagList *taglist2;
1357   GstBuffer *buf;
1358
1359   /* LE */
1360   buf = gst_tag_list_to_exif_buffer (taglist, G_LITTLE_ENDIAN, 0);
1361   taglist2 = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 0);
1362   gst_buffer_unref (buf);
1363
1364   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1365   gst_tag_list_free (taglist2);
1366
1367   /* BE */
1368   buf = gst_tag_list_to_exif_buffer (taglist, G_BIG_ENDIAN, 0);
1369   taglist2 = gst_tag_list_from_exif_buffer (buf, G_BIG_ENDIAN, 0);
1370   gst_buffer_unref (buf);
1371
1372   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1373   gst_tag_list_free (taglist2);
1374
1375   /* APP1 */
1376   buf = gst_tag_list_to_exif_buffer_with_tiff_header (taglist);
1377   taglist2 = gst_tag_list_from_exif_buffer_with_tiff_header (buf);
1378   gst_buffer_unref (buf);
1379
1380   fail_unless (gst_tag_list_is_equal (taglist, taglist2));
1381   gst_tag_list_free (taglist2);
1382 }
1383
1384 static void
1385 do_simple_exif_tag_serialization_deserialization (const gchar * gsttag,
1386     GValue * value)
1387 {
1388   GstTagList *taglist = gst_tag_list_new_empty ();
1389
1390   gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
1391   do_exif_tag_serialization_deserialization (taglist);
1392
1393   gst_tag_list_free (taglist);
1394 }
1395
1396 /*
1397  * Adds tags from multiple ifd tables and tries serializing them
1398  */
1399 GST_START_TEST (test_exif_multiple_tags)
1400 {
1401   GstTagList *taglist;
1402   GstDateTime *datetime;
1403   GValue value = { 0 };
1404
1405   gst_tag_register_musicbrainz_tags ();
1406
1407   taglist = gst_tag_list_new (GST_TAG_ARTIST, "artist",
1408       GST_TAG_DEVICE_MANUFACTURER, "make",
1409       GST_TAG_DEVICE_MODEL, "model", GST_TAG_GEO_LOCATION_LATITUDE, 45.5,
1410       GST_TAG_GEO_LOCATION_LONGITUDE, -10.25,
1411       GST_TAG_IMAGE_HORIZONTAL_PPI, 300.0,
1412       GST_TAG_IMAGE_VERTICAL_PPI, 300.0, NULL);
1413
1414   g_value_init (&value, GST_TYPE_DATE_TIME);
1415   datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10);
1416   g_value_set_boxed (&value, datetime);
1417   gst_date_time_unref (datetime);
1418   gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, GST_TAG_DATE_TIME,
1419       &value);
1420   g_value_unset (&value);
1421
1422   do_exif_tag_serialization_deserialization (taglist);
1423
1424   gst_tag_list_free (taglist);
1425 }
1426
1427 GST_END_TEST;
1428
1429
1430 GST_START_TEST (test_exif_tags_serialization_deserialization)
1431 {
1432   GValue value = { 0 };
1433   GstDateTime *datetime = NULL;
1434   GstBuffer *buf = NULL;
1435   gint i;
1436   GstTagList *taglist;
1437   GstMapInfo map;
1438   guint8 *data;
1439
1440   gst_tag_register_musicbrainz_tags ();
1441
1442   g_value_init (&value, G_TYPE_STRING);
1443   g_value_set_static_string (&value, "my string");
1444   do_simple_exif_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
1445   g_value_set_static_string (&value, "ty");
1446   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1447   g_value_set_static_string (&value, "Company Software 1.2b (info)");
1448   do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME,
1449       &value);
1450
1451   /* non ascii chars */
1452   g_value_set_static_string (&value, "AaÄäEeËëIiÏïOoÖöUuÜü");
1453   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1454   g_value_set_static_string (&value, "Äë");
1455   do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
1456
1457   /* image orientation tests */
1458   g_value_set_static_string (&value, "rotate-0");
1459   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1460       &value);
1461   g_value_set_static_string (&value, "flip-rotate-0");
1462   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1463       &value);
1464   g_value_set_static_string (&value, "rotate-180");
1465   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1466       &value);
1467   g_value_set_static_string (&value, "flip-rotate-180");
1468   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1469       &value);
1470   g_value_set_static_string (&value, "flip-rotate-270");
1471   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1472       &value);
1473   g_value_set_static_string (&value, "rotate-90");
1474   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1475       &value);
1476   g_value_set_static_string (&value, "flip-rotate-90");
1477   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1478       &value);
1479   g_value_set_static_string (&value, "rotate-270");
1480   do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION,
1481       &value);
1482
1483   /* exposure program */
1484   g_value_set_static_string (&value, "undefined");
1485   do_simple_exif_tag_serialization_deserialization
1486       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1487   g_value_set_static_string (&value, "manual");
1488   do_simple_exif_tag_serialization_deserialization
1489       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1490   g_value_set_static_string (&value, "normal");
1491   do_simple_exif_tag_serialization_deserialization
1492       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1493   g_value_set_static_string (&value, "aperture-priority");
1494   do_simple_exif_tag_serialization_deserialization
1495       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1496   g_value_set_static_string (&value, "shutter-priority");
1497   do_simple_exif_tag_serialization_deserialization
1498       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1499   g_value_set_static_string (&value, "creative");
1500   do_simple_exif_tag_serialization_deserialization
1501       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1502   g_value_set_static_string (&value, "action");
1503   do_simple_exif_tag_serialization_deserialization
1504       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1505   g_value_set_static_string (&value, "portrait");
1506   do_simple_exif_tag_serialization_deserialization
1507       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1508   g_value_set_static_string (&value, "landscape");
1509   do_simple_exif_tag_serialization_deserialization
1510       (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value);
1511
1512   /* exposure mode */
1513   g_value_set_static_string (&value, "auto-exposure");
1514   do_simple_exif_tag_serialization_deserialization
1515       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1516   g_value_set_static_string (&value, "manual-exposure");
1517   do_simple_exif_tag_serialization_deserialization
1518       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1519   g_value_set_static_string (&value, "auto-bracket");
1520   do_simple_exif_tag_serialization_deserialization
1521       (GST_TAG_CAPTURING_EXPOSURE_MODE, &value);
1522
1523   /* scene capture type */
1524   g_value_set_static_string (&value, "standard");
1525   do_simple_exif_tag_serialization_deserialization
1526       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1527   g_value_set_static_string (&value, "portrait");
1528   do_simple_exif_tag_serialization_deserialization
1529       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1530   g_value_set_static_string (&value, "landscape");
1531   do_simple_exif_tag_serialization_deserialization
1532       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1533   g_value_set_static_string (&value, "night-scene");
1534   do_simple_exif_tag_serialization_deserialization
1535       (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value);
1536
1537   g_value_set_static_string (&value, "none");
1538   do_simple_exif_tag_serialization_deserialization
1539       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1540   g_value_set_static_string (&value, "high-gain-up");
1541   do_simple_exif_tag_serialization_deserialization
1542       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1543   g_value_set_static_string (&value, "low-gain-up");
1544   do_simple_exif_tag_serialization_deserialization
1545       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1546   g_value_set_static_string (&value, "high-gain-down");
1547   do_simple_exif_tag_serialization_deserialization
1548       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1549   g_value_set_static_string (&value, "low-gain-down");
1550   do_simple_exif_tag_serialization_deserialization
1551       (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value);
1552
1553   g_value_set_static_string (&value, "auto");
1554   do_simple_exif_tag_serialization_deserialization
1555       (GST_TAG_CAPTURING_WHITE_BALANCE, &value);
1556   g_value_set_static_string (&value, "manual");
1557   do_simple_exif_tag_serialization_deserialization
1558       (GST_TAG_CAPTURING_WHITE_BALANCE, &value);
1559
1560   g_value_set_static_string (&value, "normal");
1561   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1562       &value);
1563   g_value_set_static_string (&value, "hard");
1564   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1565       &value);
1566   g_value_set_static_string (&value, "soft");
1567   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST,
1568       &value);
1569
1570   g_value_set_static_string (&value, "normal");
1571   do_simple_exif_tag_serialization_deserialization
1572       (GST_TAG_CAPTURING_SATURATION, &value);
1573   g_value_set_static_string (&value, "low-saturation");
1574   do_simple_exif_tag_serialization_deserialization
1575       (GST_TAG_CAPTURING_SATURATION, &value);
1576   g_value_set_static_string (&value, "high-saturation");
1577   do_simple_exif_tag_serialization_deserialization
1578       (GST_TAG_CAPTURING_SATURATION, &value);
1579
1580   g_value_set_static_string (&value, "normal");
1581   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1582       &value);
1583   g_value_set_static_string (&value, "hard");
1584   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1585       &value);
1586   g_value_set_static_string (&value, "soft");
1587   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS,
1588       &value);
1589
1590   g_value_set_static_string (&value, "unknown");
1591   do_simple_exif_tag_serialization_deserialization
1592       (GST_TAG_CAPTURING_METERING_MODE, &value);
1593   g_value_set_static_string (&value, "average");
1594   do_simple_exif_tag_serialization_deserialization
1595       (GST_TAG_CAPTURING_METERING_MODE, &value);
1596   g_value_set_static_string (&value, "center-weighted-average");
1597   do_simple_exif_tag_serialization_deserialization
1598       (GST_TAG_CAPTURING_METERING_MODE, &value);
1599   g_value_set_static_string (&value, "spot");
1600   do_simple_exif_tag_serialization_deserialization
1601       (GST_TAG_CAPTURING_METERING_MODE, &value);
1602   g_value_set_static_string (&value, "multi-spot");
1603   do_simple_exif_tag_serialization_deserialization
1604       (GST_TAG_CAPTURING_METERING_MODE, &value);
1605   g_value_set_static_string (&value, "pattern");
1606   do_simple_exif_tag_serialization_deserialization
1607       (GST_TAG_CAPTURING_METERING_MODE, &value);
1608   g_value_set_static_string (&value, "partial");
1609   do_simple_exif_tag_serialization_deserialization
1610       (GST_TAG_CAPTURING_METERING_MODE, &value);
1611   g_value_set_static_string (&value, "other");
1612   do_simple_exif_tag_serialization_deserialization
1613       (GST_TAG_CAPTURING_METERING_MODE, &value);
1614
1615   g_value_set_static_string (&value, "dsc");
1616   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1617       &value);
1618   g_value_set_static_string (&value, "other");
1619   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1620       &value);
1621   g_value_set_static_string (&value, "transparent-scanner");
1622   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1623       &value);
1624   g_value_set_static_string (&value, "reflex-scanner");
1625   do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE,
1626       &value);
1627   g_value_unset (&value);
1628
1629   g_value_init (&value, G_TYPE_DOUBLE);
1630   g_value_set_double (&value, 30.5);
1631   do_simple_exif_tag_serialization_deserialization
1632       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1633   g_value_set_double (&value, -12.125);
1634   do_simple_exif_tag_serialization_deserialization
1635       (GST_TAG_GEO_LOCATION_LATITUDE, &value);
1636   g_value_set_double (&value, 0);
1637   do_simple_exif_tag_serialization_deserialization
1638       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1639   g_value_set_double (&value, 65.0);
1640   do_simple_exif_tag_serialization_deserialization
1641       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1642   g_value_set_double (&value, -0.75);
1643   do_simple_exif_tag_serialization_deserialization
1644       (GST_TAG_GEO_LOCATION_LONGITUDE, &value);
1645
1646   g_value_set_double (&value, 0.0);
1647   do_simple_exif_tag_serialization_deserialization
1648       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1649   g_value_set_double (&value, 180.5);
1650   do_simple_exif_tag_serialization_deserialization
1651       (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value);
1652   g_value_set_double (&value, 0.12345);
1653   do_simple_exif_tag_serialization_deserialization
1654       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1655   g_value_set_double (&value, 359.9);
1656   do_simple_exif_tag_serialization_deserialization
1657       (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value);
1658
1659   g_value_set_double (&value, 0.0);
1660   do_simple_exif_tag_serialization_deserialization
1661       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1662   g_value_set_double (&value, 321.456);
1663   do_simple_exif_tag_serialization_deserialization
1664       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1665   g_value_set_double (&value, -12.56);
1666   do_simple_exif_tag_serialization_deserialization
1667       (GST_TAG_GEO_LOCATION_ELEVATION, &value);
1668
1669   g_value_set_double (&value, 0);
1670   do_simple_exif_tag_serialization_deserialization
1671       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1672   g_value_set_double (&value, 100 / 3.6);
1673   do_simple_exif_tag_serialization_deserialization
1674       (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
1675
1676   g_value_set_double (&value, 0);
1677   do_simple_exif_tag_serialization_deserialization
1678       (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value);
1679   g_value_set_double (&value, 50.25);
1680   do_simple_exif_tag_serialization_deserialization
1681       (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value);
1682
1683   g_value_set_double (&value, 0);
1684   do_simple_exif_tag_serialization_deserialization
1685       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1686   g_value_set_double (&value, 2.5);
1687   do_simple_exif_tag_serialization_deserialization
1688       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1689   g_value_set_double (&value, 8.75);
1690   do_simple_exif_tag_serialization_deserialization
1691       (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value);
1692
1693   g_value_set_double (&value, 20.0);
1694   do_simple_exif_tag_serialization_deserialization
1695       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1696   g_value_set_double (&value, 5.5);
1697   do_simple_exif_tag_serialization_deserialization
1698       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1699
1700   g_value_set_double (&value, 16);
1701   do_simple_exif_tag_serialization_deserialization
1702       (GST_TAG_CAPTURING_FOCAL_RATIO, &value);
1703   g_value_set_double (&value, 2.7);
1704   do_simple_exif_tag_serialization_deserialization
1705       (GST_TAG_CAPTURING_FOCAL_LENGTH, &value);
1706
1707   g_value_set_double (&value, 96.0);
1708   do_simple_exif_tag_serialization_deserialization
1709       (GST_TAG_IMAGE_HORIZONTAL_PPI, &value);
1710   g_value_set_double (&value, 300.0);
1711   do_simple_exif_tag_serialization_deserialization
1712       (GST_TAG_IMAGE_HORIZONTAL_PPI, &value);
1713   g_value_set_double (&value, 87.5);
1714   do_simple_exif_tag_serialization_deserialization
1715       (GST_TAG_IMAGE_VERTICAL_PPI, &value);
1716   g_value_set_double (&value, 600.0);
1717   do_simple_exif_tag_serialization_deserialization
1718       (GST_TAG_IMAGE_VERTICAL_PPI, &value);
1719
1720   g_value_set_double (&value, 0.0);
1721   do_simple_exif_tag_serialization_deserialization
1722       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1723   g_value_set_double (&value, 1.0);
1724   do_simple_exif_tag_serialization_deserialization
1725       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1726   g_value_set_double (&value, -2.5);
1727   do_simple_exif_tag_serialization_deserialization
1728       (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value);
1729   g_value_unset (&value);
1730
1731   g_value_init (&value, G_TYPE_INT);
1732   g_value_set_int (&value, 400);
1733   do_simple_exif_tag_serialization_deserialization
1734       (GST_TAG_CAPTURING_ISO_SPEED, &value);
1735   g_value_set_int (&value, 1600);
1736   do_simple_exif_tag_serialization_deserialization
1737       (GST_TAG_CAPTURING_ISO_SPEED, &value);
1738   g_value_unset (&value);
1739
1740   g_value_init (&value, GST_TYPE_DATE_TIME);
1741   datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10);
1742   g_value_set_boxed (&value, datetime);
1743   gst_date_time_unref (datetime);
1744   do_simple_exif_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
1745   g_value_unset (&value);
1746
1747   g_value_init (&value, GST_TYPE_BUFFER);
1748   buf = gst_buffer_new_and_alloc (1024);
1749   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1750   data = map.data;
1751   for (i = 0; i < 1024; i++)
1752     data[i] = i % 255;
1753   gst_buffer_unmap (buf, &map);
1754   gst_value_set_buffer (&value, buf);
1755   gst_buffer_unref (buf);
1756   do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_DATA,
1757       &value);
1758   g_value_unset (&value);
1759
1760   g_value_init (&value, GST_TYPE_FRACTION);
1761   gst_value_set_fraction (&value, 1, 1);
1762   do_simple_exif_tag_serialization_deserialization
1763       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1764   gst_value_set_fraction (&value, 1, 30);
1765   do_simple_exif_tag_serialization_deserialization
1766       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1767   gst_value_set_fraction (&value, 1, 200);
1768   do_simple_exif_tag_serialization_deserialization
1769       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1770   gst_value_set_fraction (&value, 1, 8000);
1771   do_simple_exif_tag_serialization_deserialization
1772       (GST_TAG_CAPTURING_SHUTTER_SPEED, &value);
1773   g_value_unset (&value);
1774
1775   /* flash is a little bit more tricky, because 2 tags are merged into 1 in
1776    * exif */
1777   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, FALSE,
1778       GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL);
1779   do_exif_tag_serialization_deserialization (taglist);
1780   gst_tag_list_free (taglist);
1781
1782   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
1783       GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL);
1784   do_exif_tag_serialization_deserialization (taglist);
1785   gst_tag_list_free (taglist);
1786
1787   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, FALSE,
1788       GST_TAG_CAPTURING_FLASH_MODE, "never", NULL);
1789   do_exif_tag_serialization_deserialization (taglist);
1790   gst_tag_list_free (taglist);
1791
1792   taglist = gst_tag_list_new (GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
1793       GST_TAG_CAPTURING_FLASH_MODE, "always", NULL);
1794   do_exif_tag_serialization_deserialization (taglist);
1795   gst_tag_list_free (taglist);
1796 }
1797
1798 GST_END_TEST;
1799
1800 static Suite *
1801 tag_suite (void)
1802 {
1803   Suite *s = suite_create ("tag support library");
1804   TCase *tc_chain = tcase_create ("general");
1805
1806   suite_add_tcase (s, tc_chain);
1807   tcase_add_test (tc_chain, test_musicbrainz_tag_registration);
1808   tcase_add_test (tc_chain, test_parse_extended_comment);
1809   tcase_add_test (tc_chain, test_vorbis_tags);
1810   tcase_add_test (tc_chain, test_id3_tags);
1811   tcase_add_test (tc_chain, test_id3v1_utf8_tag);
1812   tcase_add_test (tc_chain, test_language_utils);
1813   tcase_add_test (tc_chain, test_license_utils);
1814   tcase_add_test (tc_chain, test_xmp_formatting);
1815   tcase_add_test (tc_chain, test_xmp_parsing);
1816   tcase_add_test (tc_chain, test_xmp_tags_serialization_deserialization);
1817   tcase_add_test (tc_chain, test_xmp_compound_tags);
1818   tcase_add_test (tc_chain, test_exif_parsing);
1819   tcase_add_test (tc_chain, test_exif_tags_serialization_deserialization);
1820   tcase_add_test (tc_chain, test_exif_multiple_tags);
1821   return s;
1822 }
1823
1824 int
1825 main (int argc, char **argv)
1826 {
1827   int nf;
1828
1829   Suite *s = tag_suite ();
1830   SRunner *sr = srunner_create (s);
1831
1832   gst_check_init (&argc, &argv);
1833
1834   srunner_run_all (sr, CK_NORMAL);
1835   nf = srunner_ntests_failed (sr);
1836   srunner_free (sr);
1837
1838   return nf;
1839 }