1da2ca87845c41f6ad16411aed3e5ac2d674a111
[platform/upstream/gstreamer.git] / gst / gsttaglist.c
1 /* GStreamer
2  * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
3  *
4  * gsttaglist.c: tag support (aka metadata)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gsttaglist
24  * @short_description: List of tags and values used to describe media metadata
25  *
26  * List of tags and values used to describe media metadata.
27  *
28  * Strings must be in ASCII or UTF-8 encoding. No other encodings are allowed.
29  *
30  * Last reviewed on 2009-06-09 (0.10.23)
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #  include "config.h"
35 #endif
36
37 #include "gst_private.h"
38 #include "math-compat.h"
39 #include "gst-i18n-lib.h"
40 #include "gsttaglist.h"
41 #include "gstinfo.h"
42 #include "gstvalue.h"
43 #include "gstbuffer.h"
44 #include "gstquark.h"
45 #include "gststructure.h"
46
47 #include <gobject/gvaluecollector.h>
48 #include <string.h>
49
50 /* FIXME: add category for tags */
51 #define GST_CAT_TAGS GST_CAT_DEFAULT
52
53 #define GST_TAG_IS_VALID(tag)           (gst_tag_get_info (tag) != NULL)
54
55 typedef struct _GstTagListImpl
56 {
57   GstTagList taglist;
58
59   GstStructure *structure;
60 } GstTagListImpl;
61
62 #define GST_TAG_LIST_STRUCTURE(taglist)  ((GstTagListImpl*)(taglist))->structure
63
64 typedef struct
65 {
66   GType type;                   /* type the data is in */
67
68   const gchar *nick;            /* translated short description */
69   const gchar *blurb;           /* translated long description  */
70
71   GstTagMergeFunc merge_func;   /* functions to merge the values */
72   GstTagFlag flag;              /* type of tag */
73   GQuark name_quark;            /* quark for the name */
74 }
75 GstTagInfo;
76
77 #define g_value_get_char g_value_get_schar
78
79 static GMutex __tag_mutex;
80 #define TAG_LOCK g_mutex_lock (&__tag_mutex)
81 #define TAG_UNLOCK g_mutex_unlock (&__tag_mutex)
82
83 /* tags hash table: maps tag name string => GstTagInfo */
84 static GHashTable *__tags;
85
86 GST_DEFINE_MINI_OBJECT_TYPE (GstTagList, gst_tag_list);
87
88 static void __gst_tag_list_free (GstTagList * list);
89 static GstTagList *__gst_tag_list_copy (const GstTagList * list);
90
91 /* FIXME: had code:
92  *    g_value_register_transform_func (_gst_tag_list_type, G_TYPE_STRING,
93  *      _gst_structure_transform_to_string);
94  */
95 void
96 _priv_gst_tag_initialize (void)
97 {
98   g_mutex_init (&__tag_mutex);
99
100   __tags = g_hash_table_new (g_str_hash, g_str_equal);
101   gst_tag_register_static (GST_TAG_TITLE, GST_TAG_FLAG_META,
102       G_TYPE_STRING,
103       _("title"), _("commonly used title"), gst_tag_merge_strings_with_comma);
104   gst_tag_register_static (GST_TAG_TITLE_SORTNAME, GST_TAG_FLAG_META,
105       G_TYPE_STRING,
106       _("title sortname"), _("commonly used title for sorting purposes"), NULL);
107   gst_tag_register_static (GST_TAG_ARTIST, GST_TAG_FLAG_META,
108       G_TYPE_STRING,
109       _("artist"),
110       _("person(s) responsible for the recording"),
111       gst_tag_merge_strings_with_comma);
112   gst_tag_register_static (GST_TAG_ARTIST_SORTNAME, GST_TAG_FLAG_META,
113       G_TYPE_STRING,
114       _("artist sortname"),
115       _("person(s) responsible for the recording for sorting purposes"), NULL);
116   gst_tag_register_static (GST_TAG_ALBUM, GST_TAG_FLAG_META,
117       G_TYPE_STRING,
118       _("album"),
119       _("album containing this data"), gst_tag_merge_strings_with_comma);
120   gst_tag_register_static (GST_TAG_ALBUM_SORTNAME, GST_TAG_FLAG_META,
121       G_TYPE_STRING,
122       _("album sortname"),
123       _("album containing this data for sorting purposes"), NULL);
124   gst_tag_register_static (GST_TAG_ALBUM_ARTIST, GST_TAG_FLAG_META,
125       G_TYPE_STRING,
126       _("album artist"),
127       _("The artist of the entire album, as it should be displayed"),
128       gst_tag_merge_strings_with_comma);
129   gst_tag_register_static (GST_TAG_ALBUM_ARTIST_SORTNAME, GST_TAG_FLAG_META,
130       G_TYPE_STRING,
131       _("album artist sortname"),
132       _("The artist of the entire album, as it should be sorted"), NULL);
133   gst_tag_register_static (GST_TAG_DATE, GST_TAG_FLAG_META, G_TYPE_DATE,
134       _("date"), _("date the data was created (as a GDate structure)"), NULL);
135   gst_tag_register_static (GST_TAG_DATE_TIME, GST_TAG_FLAG_META,
136       GST_TYPE_DATE_TIME, _("datetime"),
137       _("date and time the data was created (as a GstDateTime structure)"),
138       NULL);
139   gst_tag_register_static (GST_TAG_GENRE, GST_TAG_FLAG_META,
140       G_TYPE_STRING,
141       _("genre"),
142       _("genre this data belongs to"), gst_tag_merge_strings_with_comma);
143   gst_tag_register_static (GST_TAG_COMMENT, GST_TAG_FLAG_META,
144       G_TYPE_STRING,
145       _("comment"),
146       _("free text commenting the data"), gst_tag_merge_use_first);
147   gst_tag_register_static (GST_TAG_EXTENDED_COMMENT, GST_TAG_FLAG_META,
148       G_TYPE_STRING,
149       _("extended comment"),
150       _("free text commenting the data in key=value or key[en]=comment form"),
151       gst_tag_merge_use_first);
152   gst_tag_register_static (GST_TAG_TRACK_NUMBER, GST_TAG_FLAG_META,
153       G_TYPE_UINT,
154       _("track number"),
155       _("track number inside a collection"), gst_tag_merge_use_first);
156   gst_tag_register_static (GST_TAG_TRACK_COUNT, GST_TAG_FLAG_META,
157       G_TYPE_UINT,
158       _("track count"),
159       _("count of tracks inside collection this track belongs to"),
160       gst_tag_merge_use_first);
161   gst_tag_register_static (GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_FLAG_META,
162       G_TYPE_UINT,
163       _("disc number"),
164       _("disc number inside a collection"), gst_tag_merge_use_first);
165   gst_tag_register_static (GST_TAG_ALBUM_VOLUME_COUNT, GST_TAG_FLAG_META,
166       G_TYPE_UINT,
167       _("disc count"),
168       _("count of discs inside collection this disc belongs to"),
169       gst_tag_merge_use_first);
170   gst_tag_register_static (GST_TAG_LOCATION, GST_TAG_FLAG_META,
171       G_TYPE_STRING,
172       _("location"), _("Origin of media as a URI (location, where the "
173           "original of the file or stream is hosted)"),
174       gst_tag_merge_strings_with_comma);
175   gst_tag_register_static (GST_TAG_HOMEPAGE, GST_TAG_FLAG_META,
176       G_TYPE_STRING,
177       _("homepage"),
178       _("Homepage for this media (i.e. artist or movie homepage)"),
179       gst_tag_merge_strings_with_comma);
180   gst_tag_register_static (GST_TAG_DESCRIPTION, GST_TAG_FLAG_META,
181       G_TYPE_STRING, _("description"),
182       _("short text describing the content of the data"),
183       gst_tag_merge_strings_with_comma);
184   gst_tag_register_static (GST_TAG_VERSION, GST_TAG_FLAG_META, G_TYPE_STRING,
185       _("version"), _("version of this data"), NULL);
186   gst_tag_register_static (GST_TAG_ISRC, GST_TAG_FLAG_META, G_TYPE_STRING,
187       _("ISRC"),
188       _
189       ("International Standard Recording Code - see http://www.ifpi.org/isrc/"),
190       NULL);
191   /* FIXME: organization (fix what? tpm) */
192   gst_tag_register_static (GST_TAG_ORGANIZATION, GST_TAG_FLAG_META,
193       G_TYPE_STRING, _("organization"), _("organization"),
194       gst_tag_merge_strings_with_comma);
195   gst_tag_register_static (GST_TAG_COPYRIGHT, GST_TAG_FLAG_META,
196       G_TYPE_STRING, _("copyright"), _("copyright notice of the data"), NULL);
197   gst_tag_register_static (GST_TAG_COPYRIGHT_URI, GST_TAG_FLAG_META,
198       G_TYPE_STRING, _("copyright uri"),
199       _("URI to the copyright notice of the data"), NULL);
200   gst_tag_register_static (GST_TAG_ENCODED_BY, GST_TAG_FLAG_META, G_TYPE_STRING,
201       _("encoded by"), _("name of the encoding person or organization"),
202       gst_tag_merge_strings_with_comma);
203   gst_tag_register_static (GST_TAG_CONTACT, GST_TAG_FLAG_META,
204       G_TYPE_STRING,
205       _("contact"), _("contact information"), gst_tag_merge_strings_with_comma);
206   gst_tag_register_static (GST_TAG_LICENSE, GST_TAG_FLAG_META,
207       G_TYPE_STRING, _("license"), _("license of data"), NULL);
208   gst_tag_register_static (GST_TAG_LICENSE_URI, GST_TAG_FLAG_META,
209       G_TYPE_STRING, _("license uri"),
210       _("URI to the license of the data"), NULL);
211   gst_tag_register_static (GST_TAG_PERFORMER, GST_TAG_FLAG_META,
212       G_TYPE_STRING,
213       _("performer"),
214       _("person(s) performing"), gst_tag_merge_strings_with_comma);
215   gst_tag_register_static (GST_TAG_COMPOSER, GST_TAG_FLAG_META,
216       G_TYPE_STRING,
217       _("composer"),
218       _("person(s) who composed the recording"),
219       gst_tag_merge_strings_with_comma);
220   gst_tag_register_static (GST_TAG_DURATION, GST_TAG_FLAG_DECODED,
221       G_TYPE_UINT64,
222       _("duration"), _("length in GStreamer time units (nanoseconds)"), NULL);
223   gst_tag_register_static (GST_TAG_CODEC, GST_TAG_FLAG_ENCODED,
224       G_TYPE_STRING,
225       _("codec"),
226       _("codec the data is stored in"), gst_tag_merge_strings_with_comma);
227   gst_tag_register_static (GST_TAG_VIDEO_CODEC, GST_TAG_FLAG_ENCODED,
228       G_TYPE_STRING,
229       _("video codec"), _("codec the video data is stored in"), NULL);
230   gst_tag_register_static (GST_TAG_AUDIO_CODEC, GST_TAG_FLAG_ENCODED,
231       G_TYPE_STRING,
232       _("audio codec"), _("codec the audio data is stored in"), NULL);
233   gst_tag_register_static (GST_TAG_SUBTITLE_CODEC, GST_TAG_FLAG_ENCODED,
234       G_TYPE_STRING,
235       _("subtitle codec"), _("codec the subtitle data is stored in"), NULL);
236   gst_tag_register_static (GST_TAG_CONTAINER_FORMAT, GST_TAG_FLAG_ENCODED,
237       G_TYPE_STRING, _("container format"),
238       _("container format the data is stored in"), NULL);
239   gst_tag_register_static (GST_TAG_BITRATE, GST_TAG_FLAG_ENCODED,
240       G_TYPE_UINT, _("bitrate"), _("exact or average bitrate in bits/s"), NULL);
241   gst_tag_register_static (GST_TAG_NOMINAL_BITRATE, GST_TAG_FLAG_ENCODED,
242       G_TYPE_UINT, _("nominal bitrate"), _("nominal bitrate in bits/s"), NULL);
243   gst_tag_register_static (GST_TAG_MINIMUM_BITRATE, GST_TAG_FLAG_ENCODED,
244       G_TYPE_UINT, _("minimum bitrate"), _("minimum bitrate in bits/s"), NULL);
245   gst_tag_register_static (GST_TAG_MAXIMUM_BITRATE, GST_TAG_FLAG_ENCODED,
246       G_TYPE_UINT, _("maximum bitrate"), _("maximum bitrate in bits/s"), NULL);
247   gst_tag_register_static (GST_TAG_ENCODER, GST_TAG_FLAG_ENCODED,
248       G_TYPE_STRING,
249       _("encoder"), _("encoder used to encode this stream"), NULL);
250   gst_tag_register_static (GST_TAG_ENCODER_VERSION, GST_TAG_FLAG_ENCODED,
251       G_TYPE_UINT,
252       _("encoder version"),
253       _("version of the encoder used to encode this stream"), NULL);
254   gst_tag_register_static (GST_TAG_SERIAL, GST_TAG_FLAG_ENCODED,
255       G_TYPE_UINT, _("serial"), _("serial number of track"), NULL);
256   gst_tag_register_static (GST_TAG_TRACK_GAIN, GST_TAG_FLAG_META,
257       G_TYPE_DOUBLE, _("replaygain track gain"), _("track gain in db"), NULL);
258   gst_tag_register_static (GST_TAG_TRACK_PEAK, GST_TAG_FLAG_META,
259       G_TYPE_DOUBLE, _("replaygain track peak"), _("peak of the track"), NULL);
260   gst_tag_register_static (GST_TAG_ALBUM_GAIN, GST_TAG_FLAG_META,
261       G_TYPE_DOUBLE, _("replaygain album gain"), _("album gain in db"), NULL);
262   gst_tag_register_static (GST_TAG_ALBUM_PEAK, GST_TAG_FLAG_META,
263       G_TYPE_DOUBLE, _("replaygain album peak"), _("peak of the album"), NULL);
264   gst_tag_register_static (GST_TAG_REFERENCE_LEVEL, GST_TAG_FLAG_META,
265       G_TYPE_DOUBLE, _("replaygain reference level"),
266       _("reference level of track and album gain values"), NULL);
267   gst_tag_register_static (GST_TAG_LANGUAGE_CODE, GST_TAG_FLAG_META,
268       G_TYPE_STRING, _("language code"),
269       _("language code for this stream, conforming to ISO-639-1 or ISO-639-2"),
270       NULL);
271   gst_tag_register_static (GST_TAG_LANGUAGE_NAME, GST_TAG_FLAG_META,
272       G_TYPE_STRING, _("language name"),
273       _("freeform name of the language this stream is in"), NULL);
274   gst_tag_register_static (GST_TAG_IMAGE, GST_TAG_FLAG_META, GST_TYPE_SAMPLE,
275       _("image"), _("image related to this stream"), gst_tag_merge_use_first);
276   gst_tag_register_static (GST_TAG_PREVIEW_IMAGE, GST_TAG_FLAG_META,
277       GST_TYPE_SAMPLE,
278       /* TRANSLATORS: 'preview image' = image that shows a preview of the full image */
279       _("preview image"), _("preview image related to this stream"), NULL);
280   gst_tag_register_static (GST_TAG_ATTACHMENT, GST_TAG_FLAG_META,
281       GST_TYPE_SAMPLE, _("attachment"), _("file attached to this stream"),
282       gst_tag_merge_use_first);
283   gst_tag_register_static (GST_TAG_BEATS_PER_MINUTE, GST_TAG_FLAG_META,
284       G_TYPE_DOUBLE, _("beats per minute"),
285       _("number of beats per minute in audio"), NULL);
286   gst_tag_register_static (GST_TAG_KEYWORDS, GST_TAG_FLAG_META, G_TYPE_STRING,
287       _("keywords"), _("comma separated keywords describing the content"),
288       gst_tag_merge_strings_with_comma);
289   gst_tag_register_static (GST_TAG_GEO_LOCATION_NAME, GST_TAG_FLAG_META,
290       G_TYPE_STRING, _("geo location name"),
291       _("human readable descriptive location of where "
292           "the media has been recorded or produced"), NULL);
293   gst_tag_register_static (GST_TAG_GEO_LOCATION_LATITUDE, GST_TAG_FLAG_META,
294       G_TYPE_DOUBLE, _("geo location latitude"),
295       _("geo latitude location of where the media has been recorded or "
296           "produced in degrees according to WGS84 (zero at the equator, "
297           "negative values for southern latitudes)"), NULL);
298   gst_tag_register_static (GST_TAG_GEO_LOCATION_LONGITUDE, GST_TAG_FLAG_META,
299       G_TYPE_DOUBLE, _("geo location longitude"),
300       _("geo longitude location of where the media has been recorded or "
301           "produced in degrees according to WGS84 (zero at the prime meridian "
302           "in Greenwich/UK,  negative values for western longitudes)"), NULL);
303   gst_tag_register_static (GST_TAG_GEO_LOCATION_ELEVATION, GST_TAG_FLAG_META,
304       G_TYPE_DOUBLE, _("geo location elevation"),
305       _("geo elevation of where the media has been recorded or produced in "
306           "meters according to WGS84 (zero is average sea level)"), NULL);
307   gst_tag_register_static (GST_TAG_GEO_LOCATION_COUNTRY, GST_TAG_FLAG_META,
308       G_TYPE_STRING, _("geo location country"),
309       _("country (english name) where the media has been recorded "
310           "or produced"), NULL);
311   gst_tag_register_static (GST_TAG_GEO_LOCATION_CITY, GST_TAG_FLAG_META,
312       G_TYPE_STRING, _("geo location city"),
313       _("city (english name) where the media has been recorded "
314           "or produced"), NULL);
315   gst_tag_register_static (GST_TAG_GEO_LOCATION_SUBLOCATION, GST_TAG_FLAG_META,
316       G_TYPE_STRING, _("geo location sublocation"),
317       _("a location whithin a city where the media has been produced "
318           "or created (e.g. the neighborhood)"), NULL);
319   gst_tag_register_static (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR,
320       GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location horizontal error"),
321       _("expected error of the horizontal positioning measures (in meters)"),
322       NULL);
323   gst_tag_register_static (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED,
324       GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location movement speed"),
325       _("movement speed of the capturing device while performing the capture "
326           "in m/s"), NULL);
327   gst_tag_register_static (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION,
328       GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location movement direction"),
329       _("indicates the movement direction of the device performing the capture"
330           " of a media. It is represented as degrees in floating point "
331           "representation, 0 means the geographic north, and increases "
332           "clockwise"), NULL);
333   gst_tag_register_static (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION,
334       GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location capture direction"),
335       _("indicates the direction the device is pointing to when capturing "
336           " a media. It is represented as degrees in floating point "
337           " representation, 0 means the geographic north, and increases "
338           "clockwise"), NULL);
339   gst_tag_register_static (GST_TAG_SHOW_NAME, GST_TAG_FLAG_META, G_TYPE_STRING,
340       /* TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here */
341       _("show name"),
342       _("Name of the tv/podcast/series show the media is from"),
343       gst_tag_merge_strings_with_comma);
344   gst_tag_register_static (GST_TAG_SHOW_SORTNAME, GST_TAG_FLAG_META,
345       G_TYPE_STRING,
346       /* TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here */
347       _("show sortname"),
348       _("Name of the tv/podcast/series show the media is from, for sorting "
349           "purposes"), NULL);
350   gst_tag_register_static (GST_TAG_SHOW_EPISODE_NUMBER, GST_TAG_FLAG_META,
351       G_TYPE_UINT, _("episode number"),
352       _("The episode number in the season the media is part of"),
353       gst_tag_merge_use_first);
354   gst_tag_register_static (GST_TAG_SHOW_SEASON_NUMBER, GST_TAG_FLAG_META,
355       G_TYPE_UINT, _("season number"),
356       _("The season number of the show the media is part of"),
357       gst_tag_merge_use_first);
358   gst_tag_register_static (GST_TAG_LYRICS, GST_TAG_FLAG_META, G_TYPE_STRING,
359       _("lyrics"), _("The lyrics of the media, commonly used for songs"),
360       gst_tag_merge_strings_with_comma);
361   gst_tag_register_static (GST_TAG_COMPOSER_SORTNAME, GST_TAG_FLAG_META,
362       G_TYPE_STRING, _("composer sortname"),
363       _("person(s) who composed the recording, for sorting purposes"), NULL);
364   gst_tag_register_static (GST_TAG_GROUPING, GST_TAG_FLAG_META, G_TYPE_STRING,
365       _("grouping"),
366       _("Groups related media that spans multiple tracks, like the different "
367           "pieces of a concerto. It is a higher level than a track, "
368           "but lower than an album"), NULL);
369   gst_tag_register_static (GST_TAG_USER_RATING, GST_TAG_FLAG_META, G_TYPE_UINT,
370       _("user rating"),
371       _("Rating attributed by a user. The higher the rank, "
372           "the more the user likes this media"), NULL);
373   gst_tag_register_static (GST_TAG_DEVICE_MANUFACTURER, GST_TAG_FLAG_META,
374       G_TYPE_STRING, _("device manufacturer"),
375       _("Manufacturer of the device used to create this media"), NULL);
376   gst_tag_register_static (GST_TAG_DEVICE_MODEL, GST_TAG_FLAG_META,
377       G_TYPE_STRING, _("device model"),
378       _("Model of the device used to create this media"), NULL);
379   gst_tag_register_static (GST_TAG_APPLICATION_NAME, GST_TAG_FLAG_META,
380       G_TYPE_STRING, _("application name"),
381       _("Application used to create the media"), NULL);
382   gst_tag_register_static (GST_TAG_APPLICATION_DATA, GST_TAG_FLAG_META,
383       GST_TYPE_SAMPLE, _("application data"),
384       _("Arbitrary application data to be serialized into the media"), NULL);
385   gst_tag_register_static (GST_TAG_IMAGE_ORIENTATION, GST_TAG_FLAG_META,
386       G_TYPE_STRING, _("image orientation"),
387       _("How the image should be rotated or flipped before display"), NULL);
388 }
389
390 /**
391  * gst_tag_merge_use_first:
392  * @dest: (out caller-allocates): uninitialized GValue to store result in
393  * @src: GValue to copy from
394  *
395  * This is a convenience function for the func argument of gst_tag_register().
396  * It creates a copy of the first value from the list.
397  */
398 void
399 gst_tag_merge_use_first (GValue * dest, const GValue * src)
400 {
401   const GValue *ret = gst_value_list_get_value (src, 0);
402
403   g_value_init (dest, G_VALUE_TYPE (ret));
404   g_value_copy (ret, dest);
405 }
406
407 /**
408  * gst_tag_merge_strings_with_comma:
409  * @dest: (out caller-allocates): uninitialized GValue to store result in
410  * @src: GValue to copy from
411  *
412  * This is a convenience function for the func argument of gst_tag_register().
413  * It concatenates all given strings using a comma. The tag must be registered
414  * as a G_TYPE_STRING or this function will fail.
415  */
416 void
417 gst_tag_merge_strings_with_comma (GValue * dest, const GValue * src)
418 {
419   GString *str;
420   gint i, count;
421
422   count = gst_value_list_get_size (src);
423   str = g_string_new (g_value_get_string (gst_value_list_get_value (src, 0)));
424   for (i = 1; i < count; i++) {
425     /* separator between two strings */
426     g_string_append (str, _(", "));
427     g_string_append (str,
428         g_value_get_string (gst_value_list_get_value (src, i)));
429   }
430
431   g_value_init (dest, G_TYPE_STRING);
432   g_value_take_string (dest, str->str);
433   g_string_free (str, FALSE);
434 }
435
436 static GstTagInfo *
437 gst_tag_lookup (const gchar * tag_name)
438 {
439   GstTagInfo *ret;
440
441   TAG_LOCK;
442   ret = g_hash_table_lookup (__tags, (gpointer) tag_name);
443   TAG_UNLOCK;
444
445   return ret;
446 }
447
448 /**
449  * gst_tag_register:
450  * @name: the name or identifier string
451  * @flag: a flag describing the type of tag info
452  * @type: the type this data is in
453  * @nick: human-readable name
454  * @blurb: a human-readable description about this tag
455  * @func: function for merging multiple values of this tag, or NULL
456  *
457  * Registers a new tag type for the use with GStreamer's type system. If a type
458  * with that name is already registered, that one is used.
459  * The old registration may have used a different type however. So don't rely
460  * on your supplied values.
461  *
462  * Important: if you do not supply a merge function the implication will be
463  * that there can only be one single value for this tag in a tag list and
464  * any additional values will silenty be discarded when being added (unless
465  * #GST_TAG_MERGE_REPLACE, #GST_TAG_MERGE_REPLACE_ALL, or
466  * #GST_TAG_MERGE_PREPEND is used as merge mode, in which case the new
467  * value will replace the old one in the list).
468  *
469  * The merge function will be called from gst_tag_list_copy_value() when
470  * it is required that one or more values for a tag be condensed into
471  * one single value. This may happen from gst_tag_list_get_string(),
472  * gst_tag_list_get_int(), gst_tag_list_get_double() etc. What will happen
473  * exactly in that case depends on how the tag was registered and if a
474  * merge function was supplied and if so which one.
475  *
476  * Two default merge functions are provided: gst_tag_merge_use_first() and
477  * gst_tag_merge_strings_with_comma().
478  */
479 void
480 gst_tag_register (const gchar * name, GstTagFlag flag, GType type,
481     const gchar * nick, const gchar * blurb, GstTagMergeFunc func)
482 {
483   g_return_if_fail (name != NULL);
484   g_return_if_fail (nick != NULL);
485   g_return_if_fail (blurb != NULL);
486   g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
487
488   return gst_tag_register_static (g_intern_string (name), flag, type,
489       g_intern_string (nick), g_intern_string (blurb), func);
490 }
491
492 /**
493  * gst_tag_register_static:
494  * @name: the name or identifier string (string constant)
495  * @flag: a flag describing the type of tag info
496  * @type: the type this data is in
497  * @nick: human-readable name or short description (string constant)
498  * @blurb: a human-readable description for this tag (string constant)
499  * @func: function for merging multiple values of this tag, or NULL
500  *
501  * Registers a new tag type for the use with GStreamer's type system.
502  *
503  * Same as gst_tag_register(), but @name, @nick, and @blurb must be
504  * static strings or inlined strings, as they will not be copied. (GStreamer
505  * plugins will be made resident once loaded, so this function can be used
506  * even from dynamically loaded plugins.)
507  */
508 void
509 gst_tag_register_static (const gchar * name, GstTagFlag flag, GType type,
510     const gchar * nick, const gchar * blurb, GstTagMergeFunc func)
511 {
512   GstTagInfo *info;
513
514   g_return_if_fail (name != NULL);
515   g_return_if_fail (nick != NULL);
516   g_return_if_fail (blurb != NULL);
517   g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
518
519   info = gst_tag_lookup (name);
520
521   if (info) {
522     g_return_if_fail (info->type == type);
523     return;
524   }
525
526   info = g_slice_new (GstTagInfo);
527   info->flag = flag;
528   info->type = type;
529   info->name_quark = g_quark_from_static_string (name);
530   info->nick = nick;
531   info->blurb = blurb;
532   info->merge_func = func;
533
534   TAG_LOCK;
535   g_hash_table_insert (__tags, (gpointer) name, info);
536   TAG_UNLOCK;
537 }
538
539 /**
540  * gst_tag_exists:
541  * @tag: name of the tag
542  *
543  * Checks if the given type is already registered.
544  *
545  * Returns: TRUE if the type is already registered
546  */
547 gboolean
548 gst_tag_exists (const gchar * tag)
549 {
550   g_return_val_if_fail (tag != NULL, FALSE);
551
552   return gst_tag_lookup (tag) != NULL;
553 }
554
555 /**
556  * gst_tag_get_type:
557  * @tag: the tag
558  *
559  * Gets the #GType used for this tag.
560  *
561  * Returns: the #GType of this tag
562  */
563 GType
564 gst_tag_get_type (const gchar * tag)
565 {
566   GstTagInfo *info;
567
568   g_return_val_if_fail (tag != NULL, 0);
569   info = gst_tag_lookup (tag);
570   g_return_val_if_fail (info != NULL, 0);
571
572   return info->type;
573 }
574
575 /**
576  * gst_tag_get_nick:
577  * @tag: the tag
578  *
579  * Returns the human-readable name of this tag, You must not change or free
580  * this string.
581  *
582  * Returns: the human-readable name of this tag
583  */
584 const gchar *
585 gst_tag_get_nick (const gchar * tag)
586 {
587   GstTagInfo *info;
588
589   g_return_val_if_fail (tag != NULL, NULL);
590   info = gst_tag_lookup (tag);
591   g_return_val_if_fail (info != NULL, NULL);
592
593   return info->nick;
594 }
595
596 /**
597  * gst_tag_get_description:
598  * @tag: the tag
599  *
600  * Returns the human-readable description of this tag, You must not change or
601  * free this string.
602  *
603  * Returns: the human-readable description of this tag
604  */
605 const gchar *
606 gst_tag_get_description (const gchar * tag)
607 {
608   GstTagInfo *info;
609
610   g_return_val_if_fail (tag != NULL, NULL);
611   info = gst_tag_lookup (tag);
612   g_return_val_if_fail (info != NULL, NULL);
613
614   return info->blurb;
615 }
616
617 /**
618  * gst_tag_get_flag:
619  * @tag: the tag
620  *
621  * Gets the flag of @tag.
622  *
623  * Returns: the flag of this tag.
624  */
625 GstTagFlag
626 gst_tag_get_flag (const gchar * tag)
627 {
628   GstTagInfo *info;
629
630   g_return_val_if_fail (tag != NULL, GST_TAG_FLAG_UNDEFINED);
631   info = gst_tag_lookup (tag);
632   g_return_val_if_fail (info != NULL, GST_TAG_FLAG_UNDEFINED);
633
634   return info->flag;
635 }
636
637 /**
638  * gst_tag_is_fixed:
639  * @tag: tag to check
640  *
641  * Checks if the given tag is fixed. A fixed tag can only contain one value.
642  * Unfixed tags can contain lists of values.
643  *
644  * Returns: TRUE, if the given tag is fixed.
645  */
646 gboolean
647 gst_tag_is_fixed (const gchar * tag)
648 {
649   GstTagInfo *info;
650
651   g_return_val_if_fail (tag != NULL, FALSE);
652   info = gst_tag_lookup (tag);
653   g_return_val_if_fail (info != NULL, FALSE);
654
655   return info->merge_func == NULL;
656 }
657
658 /* takes ownership of the structure */
659 static GstTagList *
660 gst_tag_list_new_internal (GstStructure * s)
661 {
662   GstTagList *tag_list;
663
664   g_assert (s != NULL);
665
666   tag_list = (GstTagList *) g_slice_new (GstTagListImpl);
667
668   gst_mini_object_init (GST_MINI_OBJECT_CAST (tag_list), 0, GST_TYPE_TAG_LIST,
669       (GstMiniObjectCopyFunction) __gst_tag_list_copy, NULL,
670       (GstMiniObjectFreeFunction) __gst_tag_list_free);
671
672   GST_TAG_LIST_STRUCTURE (tag_list) = s;
673
674 #ifdef DEBUG_REFCOUNT
675   GST_CAT_TRACE (GST_CAT_TAGS, "created taglist %p", tag_list);
676 #endif
677
678   return tag_list;
679 }
680
681 static void
682 __gst_tag_list_free (GstTagList * list)
683 {
684   g_return_if_fail (GST_IS_TAG_LIST (list));
685
686 #ifdef DEBUG_REFCOUNT
687   GST_CAT_TRACE (GST_CAT_TAGS, "freeing taglist %p", list);
688 #endif
689
690   gst_structure_free (GST_TAG_LIST_STRUCTURE (list));
691
692   g_slice_free1 (sizeof (GstTagListImpl), list);
693 }
694
695 static GstTagList *
696 __gst_tag_list_copy (const GstTagList * list)
697 {
698   const GstStructure *s;
699
700   g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
701
702   s = GST_TAG_LIST_STRUCTURE (list);
703   return gst_tag_list_new_internal (gst_structure_copy (s));
704 }
705
706 /**
707  * gst_tag_list_new_empty:
708  *
709  * Creates a new empty GstTagList.
710  *
711  * Free-function: gst_tag_list_unref
712  *
713  * Returns: (transfer full): An empty tag list
714  */
715 GstTagList *
716 gst_tag_list_new_empty (void)
717 {
718   GstStructure *s;
719   GstTagList *tag_list;
720
721   s = gst_structure_new_id_empty (GST_QUARK (TAGLIST));
722   tag_list = gst_tag_list_new_internal (s);
723   return tag_list;
724 }
725
726 /**
727  * gst_tag_list_new:
728  * @tag: tag
729  * @...: NULL-terminated list of values to set
730  *
731  * Creates a new taglist and appends the values for the given tags. It expects
732  * tag-value pairs like gst_tag_list_add(), and a NULL terminator after the
733  * last pair. The type of the values is implicit and is documented in the API
734  * reference, but can also be queried at runtime with gst_tag_get_type(). It
735  * is an error to pass a value of a type not matching the tag type into this
736  * function. The tag list will make copies of any arguments passed
737  * (e.g. strings, buffers).
738  *
739  * Free-function: gst_tag_list_unref
740  *
741  * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_unref()
742  *     when no longer needed.
743  */
744 GstTagList *
745 gst_tag_list_new (const gchar * tag, ...)
746 {
747   GstTagList *list;
748   va_list args;
749
750   g_return_val_if_fail (tag != NULL, NULL);
751
752   list = gst_tag_list_new_empty ();
753   va_start (args, tag);
754   gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, args);
755   va_end (args);
756
757   return list;
758 }
759
760 /**
761  * gst_tag_list_new_valist:
762  * @var_args: tag / value pairs to set
763  *
764  * Just like gst_tag_list_new(), only that it takes a va_list argument.
765  * Useful mostly for language bindings.
766  *
767  * Free-function: gst_tag_list_unref
768  *
769  * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_unref()
770  *     when no longer needed.
771  */
772 GstTagList *
773 gst_tag_list_new_valist (va_list var_args)
774 {
775   GstTagList *list;
776   const gchar *tag;
777
778   list = gst_tag_list_new_empty ();
779
780   tag = va_arg (var_args, gchar *);
781   gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, var_args);
782
783   return list;
784 }
785
786 /**
787  * gst_tag_list_to_string:
788  * @list: a #GstTagList
789  *
790  * Serializes a tag list to a string.
791  *
792  * Returns: a newly-allocated string, or NULL in case of an error. The
793  *    string must be freed with g_free() when no longer needed.
794  */
795 gchar *
796 gst_tag_list_to_string (const GstTagList * list)
797 {
798   g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
799
800   return gst_structure_to_string (GST_TAG_LIST_STRUCTURE (list));
801 }
802
803 /**
804  * gst_tag_list_new_from_string:
805  * @str: a string created with gst_tag_list_to_string()
806  *
807  * Deserializes a tag list.
808  *
809  * Returns: a new #GstTagList, or NULL in case of an error.
810  */
811 GstTagList *
812 gst_tag_list_new_from_string (const gchar * str)
813 {
814   GstTagList *tag_list;
815
816   g_return_val_if_fail (str != NULL, NULL);
817   g_return_val_if_fail (g_str_has_prefix (str, "taglist"), NULL);
818
819   tag_list = gst_tag_list_new_internal (gst_structure_from_string (str, NULL));
820   return tag_list;
821 }
822
823 /**
824  * gst_tag_list_n_tags:
825  * @list: A #GstTagList.
826  *
827  * Get the number of tags in @list.
828  *
829  * Returns: The number of tags in @list.
830  */
831 gint
832 gst_tag_list_n_tags (const GstTagList * list)
833 {
834   g_return_val_if_fail (list != NULL, 0);
835   g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
836
837   return gst_structure_n_fields (GST_TAG_LIST_STRUCTURE (list));
838 }
839
840 /**
841  * gst_tag_list_nth_tag_name:
842  * @list: A #GstTagList.
843  * @index: the index
844  *
845  * Get the name of the tag in @list at @index.
846  *
847  * Returns: The name of the tag at @index.
848  */
849 const gchar *
850 gst_tag_list_nth_tag_name (const GstTagList * list, guint index)
851 {
852   g_return_val_if_fail (list != NULL, 0);
853   g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
854
855   return gst_structure_nth_field_name (GST_TAG_LIST_STRUCTURE (list), index);
856 }
857
858 /**
859  * gst_tag_list_is_empty:
860  * @list: A #GstTagList.
861  *
862  * Checks if the given taglist is empty.
863  *
864  * Returns: TRUE if the taglist is empty, otherwise FALSE.
865  */
866 gboolean
867 gst_tag_list_is_empty (const GstTagList * list)
868 {
869   g_return_val_if_fail (list != NULL, FALSE);
870   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
871
872   return (gst_structure_n_fields (GST_TAG_LIST_STRUCTURE (list)) == 0);
873 }
874
875 static gboolean
876 gst_tag_list_fields_equal (const GValue * value1, const GValue * value2)
877 {
878   gdouble d1, d2;
879
880   if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL)
881     return TRUE;
882
883   /* fields not equal: add some tolerance for doubles, otherwise bail out */
884   if (!G_VALUE_HOLDS_DOUBLE (value1) || !G_VALUE_HOLDS_DOUBLE (value2))
885     return FALSE;
886
887   d1 = g_value_get_double (value1);
888   d2 = g_value_get_double (value2);
889
890   /* This will only work for 'normal' values and values around 0,
891    * which should be good enough for our purposes here
892    * FIXME: maybe add this to gst_value_compare_double() ? */
893   return (fabs (d1 - d2) < 0.0000001);
894 }
895
896 /**
897  * gst_tag_list_is_equal:
898  * @list1: a #GstTagList.
899  * @list2: a #GstTagList.
900  *
901  * Checks if the two given taglists are equal.
902  *
903  * Returns: TRUE if the taglists are equal, otherwise FALSE
904  */
905 gboolean
906 gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2)
907 {
908   const GstStructure *s1, *s2;
909   gint num_fields1, num_fields2, i;
910
911   g_return_val_if_fail (GST_IS_TAG_LIST (list1), FALSE);
912   g_return_val_if_fail (GST_IS_TAG_LIST (list2), FALSE);
913
914   /* we don't just use gst_structure_is_equal() here so we can add some
915    * tolerance for doubles, though maybe we should just add that to
916    * gst_value_compare_double() as well? */
917   s1 = GST_TAG_LIST_STRUCTURE (list1);
918   s2 = GST_TAG_LIST_STRUCTURE (list2);
919
920   num_fields1 = gst_structure_n_fields (s1);
921   num_fields2 = gst_structure_n_fields (s2);
922
923   if (num_fields1 != num_fields2)
924     return FALSE;
925
926   for (i = 0; i < num_fields1; i++) {
927     const GValue *value1, *value2;
928     const gchar *tag_name;
929
930     tag_name = gst_structure_nth_field_name (s1, i);
931     value1 = gst_structure_get_value (s1, tag_name);
932     value2 = gst_structure_get_value (s2, tag_name);
933
934     if (value2 == NULL)
935       return FALSE;
936
937     if (!gst_tag_list_fields_equal (value1, value2))
938       return FALSE;
939   }
940
941   return TRUE;
942 }
943
944 typedef struct
945 {
946   GstTagList *list;
947   GstTagMergeMode mode;
948 }
949 GstTagCopyData;
950
951 static void
952 gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode,
953     const gchar * tag, const GValue * value, GstTagInfo * info)
954 {
955   GstStructure *list = GST_TAG_LIST_STRUCTURE (tag_list);
956   const GValue *value2;
957   GQuark tag_quark;
958
959   if (info == NULL) {
960     info = gst_tag_lookup (tag);
961     if (G_UNLIKELY (info == NULL)) {
962       g_warning ("unknown tag '%s'", tag);
963       return;
964     }
965   }
966
967   if (G_UNLIKELY (!G_VALUE_HOLDS (value, info->type) &&
968           !GST_VALUE_HOLDS_LIST (value))) {
969     g_warning ("tag '%s' should hold value of type '%s', but value of "
970         "type '%s' passed", info->nick, g_type_name (info->type),
971         g_type_name (G_VALUE_TYPE (value)));
972     return;
973   }
974
975   tag_quark = info->name_quark;
976
977   if (info->merge_func
978       && (value2 = gst_structure_id_get_value (list, tag_quark)) != NULL) {
979     GValue dest = { 0, };
980
981     switch (mode) {
982       case GST_TAG_MERGE_REPLACE_ALL:
983       case GST_TAG_MERGE_REPLACE:
984         gst_structure_id_set_value (list, tag_quark, value);
985         break;
986       case GST_TAG_MERGE_PREPEND:
987         gst_value_list_merge (&dest, value, value2);
988         gst_structure_id_set_value (list, tag_quark, &dest);
989         g_value_unset (&dest);
990         break;
991       case GST_TAG_MERGE_APPEND:
992         gst_value_list_merge (&dest, value2, value);
993         gst_structure_id_set_value (list, tag_quark, &dest);
994         g_value_unset (&dest);
995         break;
996       case GST_TAG_MERGE_KEEP:
997       case GST_TAG_MERGE_KEEP_ALL:
998         break;
999       default:
1000         g_assert_not_reached ();
1001         break;
1002     }
1003   } else {
1004     switch (mode) {
1005       case GST_TAG_MERGE_APPEND:
1006       case GST_TAG_MERGE_KEEP:
1007         if (gst_structure_id_get_value (list, tag_quark) != NULL)
1008           break;
1009         /* fall through */
1010       case GST_TAG_MERGE_REPLACE_ALL:
1011       case GST_TAG_MERGE_REPLACE:
1012       case GST_TAG_MERGE_PREPEND:
1013         gst_structure_id_set_value (list, tag_quark, value);
1014         break;
1015       case GST_TAG_MERGE_KEEP_ALL:
1016         break;
1017       default:
1018         g_assert_not_reached ();
1019         break;
1020     }
1021   }
1022 }
1023
1024 static gboolean
1025 gst_tag_list_copy_foreach (GQuark tag_quark, const GValue * value,
1026     gpointer user_data)
1027 {
1028   GstTagCopyData *copy = (GstTagCopyData *) user_data;
1029   const gchar *tag;
1030
1031   tag = g_quark_to_string (tag_quark);
1032   gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value, NULL);
1033
1034   return TRUE;
1035 }
1036
1037 /**
1038  * gst_tag_list_insert:
1039  * @into: list to merge into
1040  * @from: list to merge from
1041  * @mode: the mode to use
1042  *
1043  * Inserts the tags of the @from list into the first list using the given mode.
1044  */
1045 void
1046 gst_tag_list_insert (GstTagList * into, const GstTagList * from,
1047     GstTagMergeMode mode)
1048 {
1049   GstTagCopyData data;
1050
1051   g_return_if_fail (GST_IS_TAG_LIST (into));
1052   g_return_if_fail (gst_tag_list_is_writable (into));
1053   g_return_if_fail (GST_IS_TAG_LIST (from));
1054   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1055
1056   data.list = into;
1057   data.mode = mode;
1058   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
1059     gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (into));
1060   }
1061   gst_structure_foreach (GST_TAG_LIST_STRUCTURE (from),
1062       gst_tag_list_copy_foreach, &data);
1063 }
1064
1065 /**
1066  * gst_tag_list_merge:
1067  * @list1: first list to merge
1068  * @list2: second list to merge
1069  * @mode: the mode to use
1070  *
1071  * Merges the two given lists into a new list. If one of the lists is NULL, a
1072  * copy of the other is returned. If both lists are NULL, NULL is returned.
1073  *
1074  * Free-function: gst_tag_list_unref
1075  *
1076  * Returns: (transfer full): the new list
1077  */
1078 GstTagList *
1079 gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2,
1080     GstTagMergeMode mode)
1081 {
1082   GstTagList *list1_cp;
1083   const GstTagList *list2_cp;
1084
1085   g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL);
1086   g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL);
1087   g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL);
1088
1089   /* nothing to merge */
1090   if (!list1 && !list2) {
1091     return NULL;
1092   }
1093
1094   /* create empty list, we need to do this to correctly handling merge modes */
1095   list1_cp = (list1) ? gst_tag_list_copy (list1) : gst_tag_list_new_empty ();
1096   list2_cp = (list2) ? list2 : gst_tag_list_new_empty ();
1097
1098   gst_tag_list_insert (list1_cp, list2_cp, mode);
1099
1100   if (!list2)
1101     gst_tag_list_unref ((GstTagList *) list2_cp);
1102
1103   return list1_cp;
1104 }
1105
1106 /**
1107  * gst_tag_list_get_tag_size:
1108  * @list: a taglist
1109  * @tag: the tag to query
1110  *
1111  * Checks how many value are stored in this tag list for the given tag.
1112  *
1113  * Returns: The number of tags stored
1114  */
1115 guint
1116 gst_tag_list_get_tag_size (const GstTagList * list, const gchar * tag)
1117 {
1118   const GValue *value;
1119
1120   g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
1121
1122   value = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag);
1123   if (value == NULL)
1124     return 0;
1125   if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
1126     return 1;
1127
1128   return gst_value_list_get_size (value);
1129 }
1130
1131 /**
1132  * gst_tag_list_add:
1133  * @list: list to set tags in
1134  * @mode: the mode to use
1135  * @tag: tag
1136  * @...: NULL-terminated list of values to set
1137  *
1138  * Sets the values for the given tags using the specified mode.
1139  */
1140 void
1141 gst_tag_list_add (GstTagList * list, GstTagMergeMode mode, const gchar * tag,
1142     ...)
1143 {
1144   va_list args;
1145
1146   g_return_if_fail (GST_IS_TAG_LIST (list));
1147   g_return_if_fail (gst_tag_list_is_writable (list));
1148   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1149   g_return_if_fail (tag != NULL);
1150
1151   va_start (args, tag);
1152   gst_tag_list_add_valist (list, mode, tag, args);
1153   va_end (args);
1154 }
1155
1156 /**
1157  * gst_tag_list_add_values:
1158  * @list: list to set tags in
1159  * @mode: the mode to use
1160  * @tag: tag
1161  * @...: GValues to set
1162  *
1163  * Sets the GValues for the given tags using the specified mode.
1164  */
1165 void
1166 gst_tag_list_add_values (GstTagList * list, GstTagMergeMode mode,
1167     const gchar * tag, ...)
1168 {
1169   va_list args;
1170
1171   g_return_if_fail (GST_IS_TAG_LIST (list));
1172   g_return_if_fail (gst_tag_list_is_writable (list));
1173   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1174   g_return_if_fail (tag != NULL);
1175
1176   va_start (args, tag);
1177   gst_tag_list_add_valist_values (list, mode, tag, args);
1178   va_end (args);
1179 }
1180
1181 /**
1182  * gst_tag_list_add_valist:
1183  * @list: list to set tags in
1184  * @mode: the mode to use
1185  * @tag: tag
1186  * @var_args: tag / value pairs to set
1187  *
1188  * Sets the values for the given tags using the specified mode.
1189  */
1190 void
1191 gst_tag_list_add_valist (GstTagList * list, GstTagMergeMode mode,
1192     const gchar * tag, va_list var_args)
1193 {
1194   GstTagInfo *info;
1195   gchar *error = NULL;
1196
1197   g_return_if_fail (GST_IS_TAG_LIST (list));
1198   g_return_if_fail (gst_tag_list_is_writable (list));
1199   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1200   g_return_if_fail (tag != NULL);
1201
1202   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
1203     gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (list));
1204   }
1205
1206   while (tag != NULL) {
1207     GValue value = { 0, };
1208
1209     info = gst_tag_lookup (tag);
1210     if (G_UNLIKELY (info == NULL)) {
1211       g_warning ("unknown tag '%s'", tag);
1212       return;
1213     }
1214     G_VALUE_COLLECT_INIT (&value, info->type, var_args, 0, &error);
1215     if (error) {
1216       g_warning ("%s: %s", G_STRLOC, error);
1217       g_free (error);
1218       /* we purposely leak the value here, it might not be
1219        * in a sane state if an error condition occoured
1220        */
1221       return;
1222     }
1223     gst_tag_list_add_value_internal (list, mode, tag, &value, info);
1224     g_value_unset (&value);
1225     tag = va_arg (var_args, gchar *);
1226   }
1227 }
1228
1229 /**
1230  * gst_tag_list_add_valist_values:
1231  * @list: list to set tags in
1232  * @mode: the mode to use
1233  * @tag: tag
1234  * @var_args: tag / GValue pairs to set
1235  *
1236  * Sets the GValues for the given tags using the specified mode.
1237  */
1238 void
1239 gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode,
1240     const gchar * tag, va_list var_args)
1241 {
1242   g_return_if_fail (GST_IS_TAG_LIST (list));
1243   g_return_if_fail (gst_tag_list_is_writable (list));
1244   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1245   g_return_if_fail (tag != NULL);
1246
1247   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
1248     gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (list));
1249   }
1250
1251   while (tag != NULL) {
1252     GstTagInfo *info;
1253
1254     info = gst_tag_lookup (tag);
1255     if (G_UNLIKELY (info == NULL)) {
1256       g_warning ("unknown tag '%s'", tag);
1257       return;
1258     }
1259     gst_tag_list_add_value_internal (list, mode, tag, va_arg (var_args,
1260             GValue *), info);
1261     tag = va_arg (var_args, gchar *);
1262   }
1263 }
1264
1265 /**
1266  * gst_tag_list_add_value:
1267  * @list: list to set tags in
1268  * @mode: the mode to use
1269  * @tag: tag
1270  * @value: GValue for this tag
1271  *
1272  * Sets the GValue for a given tag using the specified mode.
1273  */
1274 void
1275 gst_tag_list_add_value (GstTagList * list, GstTagMergeMode mode,
1276     const gchar * tag, const GValue * value)
1277 {
1278   g_return_if_fail (GST_IS_TAG_LIST (list));
1279   g_return_if_fail (gst_tag_list_is_writable (list));
1280   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1281   g_return_if_fail (tag != NULL);
1282
1283   gst_tag_list_add_value_internal (list, mode, tag, value, NULL);
1284 }
1285
1286 /**
1287  * gst_tag_list_remove_tag:
1288  * @list: list to remove tag from
1289  * @tag: tag to remove
1290  *
1291  * Removes the given tag from the taglist.
1292  */
1293 void
1294 gst_tag_list_remove_tag (GstTagList * list, const gchar * tag)
1295 {
1296   g_return_if_fail (GST_IS_TAG_LIST (list));
1297   g_return_if_fail (tag != NULL);
1298
1299   gst_structure_remove_field (GST_TAG_LIST_STRUCTURE (list), tag);
1300 }
1301
1302 typedef struct
1303 {
1304   GstTagForeachFunc func;
1305   const GstTagList *tag_list;
1306   gpointer data;
1307 }
1308 TagForeachData;
1309
1310 static int
1311 structure_foreach_wrapper (GQuark field_id, const GValue * value,
1312     gpointer user_data)
1313 {
1314   TagForeachData *data = (TagForeachData *) user_data;
1315
1316   data->func (data->tag_list, g_quark_to_string (field_id), data->data);
1317   return TRUE;
1318 }
1319
1320 /**
1321  * gst_tag_list_foreach:
1322  * @list: list to iterate over
1323  * @func: (scope call): function to be called for each tag
1324  * @user_data: (closure): user specified data
1325  *
1326  * Calls the given function for each tag inside the tag list. Note that if there
1327  * is no tag, the function won't be called at all.
1328  */
1329 void
1330 gst_tag_list_foreach (const GstTagList * list, GstTagForeachFunc func,
1331     gpointer user_data)
1332 {
1333   TagForeachData data;
1334
1335   g_return_if_fail (GST_IS_TAG_LIST (list));
1336   g_return_if_fail (func != NULL);
1337
1338   data.func = func;
1339   data.tag_list = list;
1340   data.data = user_data;
1341   gst_structure_foreach (GST_TAG_LIST_STRUCTURE (list),
1342       structure_foreach_wrapper, &data);
1343 }
1344
1345 /**
1346  * gst_tag_list_get_value_index:
1347  * @list: a #GstTagList
1348  * @tag: tag to read out
1349  * @index: number of entry to read out
1350  *
1351  * Gets the value that is at the given index for the given tag in the given
1352  * list.
1353  *
1354  * Returns: (transfer none): The GValue for the specified entry or NULL if the
1355  *          tag wasn't available or the tag doesn't have as many entries
1356  */
1357 const GValue *
1358 gst_tag_list_get_value_index (const GstTagList * list, const gchar * tag,
1359     guint index)
1360 {
1361   const GValue *value;
1362
1363   g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
1364   g_return_val_if_fail (tag != NULL, NULL);
1365
1366   value = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag);
1367   if (value == NULL)
1368     return NULL;
1369
1370   if (GST_VALUE_HOLDS_LIST (value)) {
1371     if (index >= gst_value_list_get_size (value))
1372       return NULL;
1373     return gst_value_list_get_value (value, index);
1374   } else {
1375     if (index > 0)
1376       return NULL;
1377     return value;
1378   }
1379 }
1380
1381 /**
1382  * gst_tag_list_copy_value:
1383  * @dest: (out caller-allocates): uninitialized #GValue to copy into
1384  * @list: list to get the tag from
1385  * @tag: tag to read out
1386  *
1387  * Copies the contents for the given tag into the value,
1388  * merging multiple values into one if multiple values are associated
1389  * with the tag.
1390  * You must g_value_unset() the value after use.
1391  *
1392  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1393  *          given list.
1394  */
1395 gboolean
1396 gst_tag_list_copy_value (GValue * dest, const GstTagList * list,
1397     const gchar * tag)
1398 {
1399   const GValue *src;
1400
1401   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1402   g_return_val_if_fail (tag != NULL, FALSE);
1403   g_return_val_if_fail (dest != NULL, FALSE);
1404   g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE);
1405
1406   src = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag);
1407   if (!src)
1408     return FALSE;
1409
1410   if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
1411     GstTagInfo *info = gst_tag_lookup (tag);
1412
1413     if (!info)
1414       return FALSE;
1415
1416     /* must be there or lists aren't allowed */
1417     g_assert (info->merge_func);
1418     info->merge_func (dest, src);
1419   } else {
1420     g_value_init (dest, G_VALUE_TYPE (src));
1421     g_value_copy (src, dest);
1422   }
1423   return TRUE;
1424 }
1425
1426 /* FIXME 0.11: this whole merge function business is overdesigned, and the
1427  * _get_foo() API is misleading as well - how many application developers will
1428  * expect gst_tag_list_get_string (list, GST_TAG_ARTIST, &val) might return a
1429  * string with multiple comma-separated artists? _get_foo() should just be
1430  * a convenience wrapper around _get_foo_index (list, tag, 0, &val),
1431  * supplemented by a special _tag_list_get_string_merged() function if needed
1432  * (unless someone can actually think of real use cases where the merge
1433  * function is not 'use first' for non-strings and merge for strings) */
1434
1435 /***** evil macros to get all the gst_tag_list_get_*() functions right *****/
1436
1437 #define TAG_MERGE_FUNCS(name,type,ret)                                  \
1438 gboolean                                                                \
1439 gst_tag_list_get_ ## name (const GstTagList *list, const gchar *tag,    \
1440                            type *value)                                 \
1441 {                                                                       \
1442   GValue v = { 0, };                                                    \
1443                                                                         \
1444   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);                 \
1445   g_return_val_if_fail (tag != NULL, FALSE);                            \
1446   g_return_val_if_fail (value != NULL, FALSE);                          \
1447                                                                         \
1448   if (!gst_tag_list_copy_value (&v, list, tag))                         \
1449       return FALSE;                                                     \
1450   *value = COPY_FUNC (g_value_get_ ## name (&v));                       \
1451   g_value_unset (&v);                                                   \
1452   return ret;                                                           \
1453 }                                                                       \
1454                                                                         \
1455 gboolean                                                                \
1456 gst_tag_list_get_ ## name ## _index (const GstTagList *list,            \
1457                                      const gchar *tag,                  \
1458                                      guint index, type *value)          \
1459 {                                                                       \
1460   const GValue *v;                                                      \
1461                                                                         \
1462   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);                 \
1463   g_return_val_if_fail (tag != NULL, FALSE);                            \
1464   g_return_val_if_fail (value != NULL, FALSE);                          \
1465                                                                         \
1466   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)    \
1467       return FALSE;                                                     \
1468   *value = COPY_FUNC (g_value_get_ ## name (v));                        \
1469   return ret;                                                           \
1470 }
1471
1472 #define COPY_FUNC /**/
1473 /**
1474  * gst_tag_list_get_boolean:
1475  * @list: a #GstTagList to get the tag from
1476  * @tag: tag to read out
1477  * @value: (out): location for the result
1478  *
1479  * Copies the contents for the given tag into the value, merging multiple values
1480  * into one if multiple values are associated with the tag.
1481  *
1482  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1483  *              given list.
1484  */
1485 /**
1486  * gst_tag_list_get_boolean_index:
1487  * @list: a #GstTagList to get the tag from
1488  * @tag: tag to read out
1489  * @index: number of entry to read out
1490  * @value: (out): location for the result
1491  *
1492  * Gets the value that is at the given index for the given tag in the given
1493  * list.
1494  *
1495  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1496  *              given list.
1497  */
1498 TAG_MERGE_FUNCS (boolean, gboolean, TRUE);
1499 /**
1500  * gst_tag_list_get_int:
1501  * @list: a #GstTagList to get the tag from
1502  * @tag: tag to read out
1503  * @value: (out): location for the result
1504  *
1505  * Copies the contents for the given tag into the value, merging multiple values
1506  * into one if multiple values are associated with the tag.
1507  *
1508  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1509  *              given list.
1510  */
1511 /**
1512  * gst_tag_list_get_int_index:
1513  * @list: a #GstTagList to get the tag from
1514  * @tag: tag to read out
1515  * @index: number of entry to read out
1516  * @value: (out): location for the result
1517  *
1518  * Gets the value that is at the given index for the given tag in the given
1519  * list.
1520  *
1521  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1522  *              given list.
1523  */
1524 TAG_MERGE_FUNCS (int, gint, TRUE);
1525 /**
1526  * gst_tag_list_get_uint:
1527  * @list: a #GstTagList to get the tag from
1528  * @tag: tag to read out
1529  * @value: (out): location for the result
1530  *
1531  * Copies the contents for the given tag into the value, merging multiple values
1532  * into one if multiple values are associated with the tag.
1533  *
1534  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1535  *              given list.
1536  */
1537 /**
1538  * gst_tag_list_get_uint_index:
1539  * @list: a #GstTagList to get the tag from
1540  * @tag: tag to read out
1541  * @index: number of entry to read out
1542  * @value: (out): location for the result
1543  *
1544  * Gets the value that is at the given index for the given tag in the given
1545  * list.
1546  *
1547  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1548  *              given list.
1549  */
1550 TAG_MERGE_FUNCS (uint, guint, TRUE);
1551 /**
1552  * gst_tag_list_get_int64_index:
1553  * @list: a #GstTagList to get the tag from
1554  * @tag: tag to read out
1555  * @index: number of entry to read out
1556  * @value: (out): location for the result
1557  *
1558  * Gets the value that is at the given index for the given tag in the given
1559  * list.
1560  *
1561  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1562  *              given list.
1563  */
1564 TAG_MERGE_FUNCS (int64, gint64, TRUE);
1565 /**
1566  * gst_tag_list_get_uint64:
1567  * @list: a #GstTagList to get the tag from
1568  * @tag: tag to read out
1569  * @value: (out): location for the result
1570  *
1571  * Copies the contents for the given tag into the value, merging multiple values
1572  * into one if multiple values are associated with the tag.
1573  *
1574  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1575  *              given list.
1576  */
1577 /**
1578  * gst_tag_list_get_uint64_index:
1579  * @list: a #GstTagList to get the tag from
1580  * @tag: tag to read out
1581  * @index: number of entry to read out
1582  * @value: (out): location for the result
1583  *
1584  * Gets the value that is at the given index for the given tag in the given
1585  * list.
1586  *
1587  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1588  *              given list.
1589  */
1590 TAG_MERGE_FUNCS (uint64, guint64, TRUE);
1591 /**
1592  * gst_tag_list_get_float:
1593  * @list: a #GstTagList to get the tag from
1594  * @tag: tag to read out
1595  * @value: (out): location for the result
1596  *
1597  * Copies the contents for the given tag into the value, merging multiple values
1598  * into one if multiple values are associated with the tag.
1599  *
1600  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1601  *              given list.
1602  */
1603 /**
1604  * gst_tag_list_get_float_index:
1605  * @list: a #GstTagList to get the tag from
1606  * @tag: tag to read out
1607  * @index: number of entry to read out
1608  * @value: (out): location for the result
1609  *
1610  * Gets the value that is at the given index for the given tag in the given
1611  * list.
1612  *
1613  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1614  *              given list.
1615  */
1616 TAG_MERGE_FUNCS (float, gfloat, TRUE);
1617 /**
1618  * gst_tag_list_get_double:
1619  * @list: a #GstTagList to get the tag from
1620  * @tag: tag to read out
1621  * @value: (out): location for the result
1622  *
1623  * Copies the contents for the given tag into the value, merging multiple values
1624  * into one if multiple values are associated with the tag.
1625  *
1626  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1627  *              given list.
1628  */
1629 /**
1630  * gst_tag_list_get_double_index:
1631  * @list: a #GstTagList to get the tag from
1632  * @tag: tag to read out
1633  * @index: number of entry to read out
1634  * @value: (out): location for the result
1635  *
1636  * Gets the value that is at the given index for the given tag in the given
1637  * list.
1638  *
1639  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1640  *              given list.
1641  */
1642 TAG_MERGE_FUNCS (double, gdouble, TRUE);
1643 /**
1644  * gst_tag_list_get_pointer:
1645  * @list: a #GstTagList to get the tag from
1646  * @tag: tag to read out
1647  * @value: (out) (transfer none): location for the result
1648  *
1649  * Copies the contents for the given tag into the value, merging multiple values
1650  * into one if multiple values are associated with the tag.
1651  *
1652  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1653  *              given list.
1654  */
1655 /**
1656  * gst_tag_list_get_pointer_index:
1657  * @list: a #GstTagList to get the tag from
1658  * @tag: tag to read out
1659  * @index: number of entry to read out
1660  * @value: (out) (transfer none): location for the result
1661  *
1662  * Gets the value that is at the given index for the given tag in the given
1663  * list.
1664  *
1665  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1666  *              given list.
1667  */
1668 TAG_MERGE_FUNCS (pointer, gpointer, (*value != NULL));
1669
1670 static inline gchar *
1671 _gst_strdup0 (const gchar * s)
1672 {
1673   if (s == NULL || *s == '\0')
1674     return NULL;
1675
1676   return g_strdup (s);
1677 }
1678
1679 #undef COPY_FUNC
1680 #define COPY_FUNC _gst_strdup0
1681
1682 /**
1683  * gst_tag_list_get_string:
1684  * @list: a #GstTagList to get the tag from
1685  * @tag: tag to read out
1686  * @value: (out callee-allocates) (transfer full): location for the result
1687  *
1688  * Copies the contents for the given tag into the value, possibly merging
1689  * multiple values into one if multiple values are associated with the tag.
1690  *
1691  * Use gst_tag_list_get_string_index (list, tag, 0, value) if you want
1692  * to retrieve the first string associated with this tag unmodified.
1693  *
1694  * The resulting string in @value will be in UTF-8 encoding and should be
1695  * freed by the caller using g_free when no longer needed. The
1696  * returned string is also guaranteed to be non-NULL and non-empty.
1697  *
1698  * Free-function: g_free
1699  *
1700  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1701  *              given list.
1702  */
1703 /**
1704  * gst_tag_list_get_string_index:
1705  * @list: a #GstTagList to get the tag from
1706  * @tag: tag to read out
1707  * @index: number of entry to read out
1708  * @value: (out callee-allocates) (transfer full): location for the result
1709  *
1710  * Gets the value that is at the given index for the given tag in the given
1711  * list.
1712  *
1713  * The resulting string in @value will be in UTF-8 encoding and should be
1714  * freed by the caller using g_free when no longer needed. The
1715  * returned string is also guaranteed to be non-NULL and non-empty.
1716  *
1717  * Free-function: g_free
1718  *
1719  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1720  *              given list.
1721  */
1722 TAG_MERGE_FUNCS (string, gchar *, (*value != NULL));
1723
1724 /*
1725  *FIXME 0.11: Instead of _peek (non-copy) and _get (copy), we could have
1726  *            _get (non-copy) and _dup (copy) for strings, seems more
1727  *            widely used
1728  */
1729 /**
1730  * gst_tag_list_peek_string_index:
1731  * @list: a #GstTagList to get the tag from
1732  * @tag: tag to read out
1733  * @index: number of entry to read out
1734  * @value: (out) (transfer none): location for the result
1735  *
1736  * Peeks at the value that is at the given index for the given tag in the given
1737  * list.
1738  *
1739  * The resulting string in @value will be in UTF-8 encoding and doesn't need
1740  * to be freed by the caller. The returned string is also guaranteed to
1741  * be non-NULL and non-empty.
1742  *
1743  * Returns: TRUE, if a value was set, FALSE if the tag didn't exist in the
1744  *              given list.
1745  */
1746 gboolean
1747 gst_tag_list_peek_string_index (const GstTagList * list,
1748     const gchar * tag, guint index, const gchar ** value)
1749 {
1750   const GValue *v;
1751
1752   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1753   g_return_val_if_fail (tag != NULL, FALSE);
1754   g_return_val_if_fail (value != NULL, FALSE);
1755
1756   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1757     return FALSE;
1758   *value = g_value_get_string (v);
1759   return *value != NULL && **value != '\0';
1760 }
1761
1762 /**
1763  * gst_tag_list_get_date:
1764  * @list: a #GstTagList to get the tag from
1765  * @tag: tag to read out
1766  * @value: (out callee-allocates) (transfer full): address of a GDate pointer
1767  *     variable to store the result into
1768  *
1769  * Copies the first date for the given tag in the taglist into the variable
1770  * pointed to by @value. Free the date with g_date_free() when it is no longer
1771  * needed.
1772  *
1773  * Free-function: g_date_free
1774  *
1775  * Returns: TRUE, if a date was copied, FALSE if the tag didn't exist in the
1776  *              given list or if it was #NULL.
1777  */
1778 gboolean
1779 gst_tag_list_get_date (const GstTagList * list, const gchar * tag,
1780     GDate ** value)
1781 {
1782   GValue v = { 0, };
1783
1784   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1785   g_return_val_if_fail (tag != NULL, FALSE);
1786   g_return_val_if_fail (value != NULL, FALSE);
1787
1788   if (!gst_tag_list_copy_value (&v, list, tag))
1789     return FALSE;
1790   *value = (GDate *) g_value_dup_boxed (&v);
1791   g_value_unset (&v);
1792   return (*value != NULL);
1793 }
1794
1795 /**
1796  * gst_tag_list_get_date_index:
1797  * @list: a #GstTagList to get the tag from
1798  * @tag: tag to read out
1799  * @index: number of entry to read out
1800  * @value: (out callee-allocates) (transfer full): location for the result
1801  *
1802  * Gets the date that is at the given index for the given tag in the given
1803  * list and copies it into the variable pointed to by @value. Free the date
1804  * with g_date_free() when it is no longer needed.
1805  *
1806  * Free-function: g_date_free
1807  *
1808  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1809  *              given list or if it was #NULL.
1810  */
1811 gboolean
1812 gst_tag_list_get_date_index (const GstTagList * list,
1813     const gchar * tag, guint index, GDate ** value)
1814 {
1815   const GValue *v;
1816
1817   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1818   g_return_val_if_fail (tag != NULL, FALSE);
1819   g_return_val_if_fail (value != NULL, FALSE);
1820
1821   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1822     return FALSE;
1823   *value = (GDate *) g_value_dup_boxed (v);
1824   return (*value != NULL);
1825 }
1826
1827 /**
1828  * gst_tag_list_get_date_time:
1829  * @list: a #GstTagList to get the tag from
1830  * @tag: tag to read out
1831  * @value: (out callee-allocates) (transfer full): address of a #GstDateTime
1832  *     pointer variable to store the result into
1833  *
1834  * Copies the first datetime for the given tag in the taglist into the variable
1835  * pointed to by @value. Unref the date with gst_date_time_unref() when
1836  * it is no longer needed.
1837  *
1838  * Free-function: gst_date_time_unref
1839  *
1840  * Returns: TRUE, if a datetime was copied, FALSE if the tag didn't exist in
1841  *              thegiven list or if it was #NULL.
1842  */
1843 gboolean
1844 gst_tag_list_get_date_time (const GstTagList * list, const gchar * tag,
1845     GstDateTime ** value)
1846 {
1847   GValue v = { 0, };
1848
1849   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1850   g_return_val_if_fail (tag != NULL, FALSE);
1851   g_return_val_if_fail (value != NULL, FALSE);
1852
1853   if (!gst_tag_list_copy_value (&v, list, tag))
1854     return FALSE;
1855
1856   g_return_val_if_fail (GST_VALUE_HOLDS_DATE_TIME (&v), FALSE);
1857
1858   *value = (GstDateTime *) g_value_dup_boxed (&v);
1859   g_value_unset (&v);
1860   return (*value != NULL);
1861 }
1862
1863 /**
1864  * gst_tag_list_get_date_time_index:
1865  * @list: a #GstTagList to get the tag from
1866  * @tag: tag to read out
1867  * @index: number of entry to read out
1868  * @value: (out callee-allocates) (transfer full): location for the result
1869  *
1870  * Gets the datetime that is at the given index for the given tag in the given
1871  * list and copies it into the variable pointed to by @value. Unref the datetime
1872  * with gst_date_time_unref() when it is no longer needed.
1873  *
1874  * Free-function: gst_date_time_unref
1875  *
1876  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1877  *              given list or if it was #NULL.
1878  */
1879 gboolean
1880 gst_tag_list_get_date_time_index (const GstTagList * list,
1881     const gchar * tag, guint index, GstDateTime ** value)
1882 {
1883   const GValue *v;
1884
1885   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1886   g_return_val_if_fail (tag != NULL, FALSE);
1887   g_return_val_if_fail (value != NULL, FALSE);
1888
1889   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1890     return FALSE;
1891   *value = (GstDateTime *) g_value_dup_boxed (v);
1892   return (*value != NULL);
1893 }
1894
1895 /**
1896  * gst_tag_list_get_sample:
1897  * @list: a #GstTagList to get the tag from
1898  * @tag: tag to read out
1899  * @sample: (out callee-allocates) (transfer full): address of a GstSample
1900  *     pointer variable to store the result into
1901  *
1902  * Copies the first sample for the given tag in the taglist into the variable
1903  * pointed to by @sample. Free the sample with gst_sample_unref() when it is
1904  * no longer needed. You can retrieve the buffer from the sample using
1905  * gst_sample_get_buffer() and the associated caps (if any) with
1906  * gst_sample_get_caps().
1907  *
1908  * Free-function: gst_sample_unref
1909  *
1910  * Returns: TRUE, if a sample was returned, FALSE if the tag didn't exist in
1911  *              the given list or if it was #NULL.
1912  */
1913 gboolean
1914 gst_tag_list_get_sample (const GstTagList * list, const gchar * tag,
1915     GstSample ** sample)
1916 {
1917   GValue v = { 0, };
1918
1919   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1920   g_return_val_if_fail (tag != NULL, FALSE);
1921   g_return_val_if_fail (sample != NULL, FALSE);
1922
1923   if (!gst_tag_list_copy_value (&v, list, tag))
1924     return FALSE;
1925   *sample = g_value_dup_boxed (&v);
1926   g_value_unset (&v);
1927   return (*sample != NULL);
1928 }
1929
1930 /**
1931  * gst_tag_list_get_sample_index:
1932  * @list: a #GstTagList to get the tag from
1933  * @tag: tag to read out
1934  * @index: number of entry to read out
1935  * @sample: (out callee-allocates) (transfer full): address of a GstSample
1936  *     pointer variable to store the result into
1937  *
1938  * Gets the sample that is at the given index for the given tag in the given
1939  * list and copies it into the variable pointed to by @smple. Free the sample
1940  * with gst_sample_unref() when it is no longer needed. You can retrieve the
1941  * buffer from the sample using gst_sample_get_buffer() and the associated
1942  * caps (if any) with gst_sample_get_caps().
1943  *
1944  * Free-function: gst_sample_unref
1945  *
1946  * Returns: TRUE, if a sample was copied, FALSE if the tag didn't exist in the
1947  *              given list or if it was #NULL.
1948  */
1949 gboolean
1950 gst_tag_list_get_sample_index (const GstTagList * list,
1951     const gchar * tag, guint index, GstSample ** sample)
1952 {
1953   const GValue *v;
1954
1955   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1956   g_return_val_if_fail (tag != NULL, FALSE);
1957   g_return_val_if_fail (sample != NULL, FALSE);
1958
1959   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1960     return FALSE;
1961   *sample = g_value_dup_boxed (v);
1962   return (*sample != NULL);
1963 }