miniobjects: pass copy, dispose and free function to gst_mini_object_init()
[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_BUFFER, _("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), 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 caps %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  * Since: 0.10.24
745  */
746 GstTagList *
747 gst_tag_list_new (const gchar * tag, ...)
748 {
749   GstTagList *list;
750   va_list args;
751
752   g_return_val_if_fail (tag != NULL, NULL);
753
754   list = gst_tag_list_new_empty ();
755   va_start (args, tag);
756   gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, args);
757   va_end (args);
758
759   return list;
760 }
761
762 /**
763  * gst_tag_list_new_valist:
764  * @var_args: tag / value pairs to set
765  *
766  * Just like gst_tag_list_new(), only that it takes a va_list argument.
767  * Useful mostly for language bindings.
768  *
769  * Free-function: gst_tag_list_unref
770  *
771  * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_unref()
772  *     when no longer needed.
773  *
774  * Since: 0.10.24
775  */
776 GstTagList *
777 gst_tag_list_new_valist (va_list var_args)
778 {
779   GstTagList *list;
780   const gchar *tag;
781
782   list = gst_tag_list_new_empty ();
783
784   tag = va_arg (var_args, gchar *);
785   gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, var_args);
786
787   return list;
788 }
789
790 /**
791  * gst_tag_list_to_string:
792  * @list: a #GstTagList
793  *
794  * Serializes a tag list to a string.
795  *
796  * Returns: a newly-allocated string, or NULL in case of an error. The
797  *    string must be freed with g_free() when no longer needed.
798  *
799  * Since: 0.10.36
800  */
801 gchar *
802 gst_tag_list_to_string (const GstTagList * list)
803 {
804   g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
805
806   return gst_structure_to_string (GST_TAG_LIST_STRUCTURE (list));
807 }
808
809 /**
810  * gst_tag_list_new_from_string:
811  * @str: a string created with gst_tag_list_to_string()
812  *
813  * Deserializes a tag list.
814  *
815  * Returns: a new #GstTagList, or NULL in case of an error.
816  *
817  * Since: 0.10.36
818  */
819 GstTagList *
820 gst_tag_list_new_from_string (const gchar * str)
821 {
822   GstTagList *tag_list;
823
824   g_return_val_if_fail (str != NULL, NULL);
825   g_return_val_if_fail (g_str_has_prefix (str, "taglist"), NULL);
826
827   tag_list = gst_tag_list_new_internal (gst_structure_from_string (str, NULL));
828   return tag_list;
829 }
830
831 /**
832  * gst_tag_list_n_tags:
833  * @list: A #GstTagList.
834  *
835  * Get the number of tags in @list.
836  *
837  * Returns: The number of tags in @list.
838  */
839 gint
840 gst_tag_list_n_tags (const GstTagList * list)
841 {
842   g_return_val_if_fail (list != NULL, 0);
843   g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
844
845   return gst_structure_n_fields (GST_TAG_LIST_STRUCTURE (list));
846 }
847
848 /**
849  * gst_tag_list_nth_tag_name:
850  * @list: A #GstTagList.
851  * @index: the index
852  *
853  * Get the name of the tag in @list at @index.
854  *
855  * Returns: The name of the tag at @index.
856  */
857 const gchar *
858 gst_tag_list_nth_tag_name (const GstTagList * list, guint index)
859 {
860   g_return_val_if_fail (list != NULL, 0);
861   g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
862
863   return gst_structure_nth_field_name (GST_TAG_LIST_STRUCTURE (list), index);
864 }
865
866 /**
867  * gst_tag_list_is_empty:
868  * @list: A #GstTagList.
869  *
870  * Checks if the given taglist is empty.
871  *
872  * Returns: TRUE if the taglist is empty, otherwise FALSE.
873  *
874  * Since: 0.10.11
875  */
876 gboolean
877 gst_tag_list_is_empty (const GstTagList * list)
878 {
879   g_return_val_if_fail (list != NULL, FALSE);
880   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
881
882   return (gst_structure_n_fields (GST_TAG_LIST_STRUCTURE (list)) == 0);
883 }
884
885 static gboolean
886 gst_tag_list_fields_equal (const GValue * value1, const GValue * value2)
887 {
888   gdouble d1, d2;
889
890   if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL)
891     return TRUE;
892
893   /* fields not equal: add some tolerance for doubles, otherwise bail out */
894   if (!G_VALUE_HOLDS_DOUBLE (value1) || !G_VALUE_HOLDS_DOUBLE (value2))
895     return FALSE;
896
897   d1 = g_value_get_double (value1);
898   d2 = g_value_get_double (value2);
899
900   /* This will only work for 'normal' values and values around 0,
901    * which should be good enough for our purposes here
902    * FIXME: maybe add this to gst_value_compare_double() ? */
903   return (fabs (d1 - d2) < 0.0000001);
904 }
905
906 /**
907  * gst_tag_list_is_equal:
908  * @list1: a #GstTagList.
909  * @list2: a #GstTagList.
910  *
911  * Checks if the two given taglists are equal.
912  *
913  * Returns: TRUE if the taglists are equal, otherwise FALSE
914  *
915  * Since: 0.10.36
916  */
917 gboolean
918 gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2)
919 {
920   const GstStructure *s1, *s2;
921   gint num_fields1, num_fields2, i;
922
923   g_return_val_if_fail (GST_IS_TAG_LIST (list1), FALSE);
924   g_return_val_if_fail (GST_IS_TAG_LIST (list2), FALSE);
925
926   /* we don't just use gst_structure_is_equal() here so we can add some
927    * tolerance for doubles, though maybe we should just add that to
928    * gst_value_compare_double() as well? */
929   s1 = GST_TAG_LIST_STRUCTURE (list1);
930   s2 = GST_TAG_LIST_STRUCTURE (list2);
931
932   num_fields1 = gst_structure_n_fields (s1);
933   num_fields2 = gst_structure_n_fields (s2);
934
935   if (num_fields1 != num_fields2)
936     return FALSE;
937
938   for (i = 0; i < num_fields1; i++) {
939     const GValue *value1, *value2;
940     const gchar *tag_name;
941
942     tag_name = gst_structure_nth_field_name (s1, i);
943     value1 = gst_structure_get_value (s1, tag_name);
944     value2 = gst_structure_get_value (s2, tag_name);
945
946     if (value2 == NULL)
947       return FALSE;
948
949     if (!gst_tag_list_fields_equal (value1, value2))
950       return FALSE;
951   }
952
953   return TRUE;
954 }
955
956 typedef struct
957 {
958   GstTagList *list;
959   GstTagMergeMode mode;
960 }
961 GstTagCopyData;
962
963 static void
964 gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode,
965     const gchar * tag, const GValue * value, GstTagInfo * info)
966 {
967   GstStructure *list = GST_TAG_LIST_STRUCTURE (tag_list);
968   const GValue *value2;
969   GQuark tag_quark;
970
971   if (info == NULL) {
972     info = gst_tag_lookup (tag);
973     if (G_UNLIKELY (info == NULL)) {
974       g_warning ("unknown tag '%s'", tag);
975       return;
976     }
977   }
978
979   tag_quark = info->name_quark;
980
981   if (info->merge_func
982       && (value2 = gst_structure_id_get_value (list, tag_quark)) != NULL) {
983     GValue dest = { 0, };
984
985     switch (mode) {
986       case GST_TAG_MERGE_REPLACE_ALL:
987       case GST_TAG_MERGE_REPLACE:
988         gst_structure_id_set_value (list, tag_quark, value);
989         break;
990       case GST_TAG_MERGE_PREPEND:
991         gst_value_list_merge (&dest, value, value2);
992         gst_structure_id_set_value (list, tag_quark, &dest);
993         g_value_unset (&dest);
994         break;
995       case GST_TAG_MERGE_APPEND:
996         gst_value_list_merge (&dest, value2, value);
997         gst_structure_id_set_value (list, tag_quark, &dest);
998         g_value_unset (&dest);
999         break;
1000       case GST_TAG_MERGE_KEEP:
1001       case GST_TAG_MERGE_KEEP_ALL:
1002         break;
1003       default:
1004         g_assert_not_reached ();
1005         break;
1006     }
1007   } else {
1008     switch (mode) {
1009       case GST_TAG_MERGE_APPEND:
1010       case GST_TAG_MERGE_KEEP:
1011         if (gst_structure_id_get_value (list, tag_quark) != NULL)
1012           break;
1013         /* fall through */
1014       case GST_TAG_MERGE_REPLACE_ALL:
1015       case GST_TAG_MERGE_REPLACE:
1016       case GST_TAG_MERGE_PREPEND:
1017         gst_structure_id_set_value (list, tag_quark, value);
1018         break;
1019       case GST_TAG_MERGE_KEEP_ALL:
1020         break;
1021       default:
1022         g_assert_not_reached ();
1023         break;
1024     }
1025   }
1026 }
1027
1028 static gboolean
1029 gst_tag_list_copy_foreach (GQuark tag_quark, const GValue * value,
1030     gpointer user_data)
1031 {
1032   GstTagCopyData *copy = (GstTagCopyData *) user_data;
1033   const gchar *tag;
1034
1035   tag = g_quark_to_string (tag_quark);
1036   gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value, NULL);
1037
1038   return TRUE;
1039 }
1040
1041 /**
1042  * gst_tag_list_insert:
1043  * @into: list to merge into
1044  * @from: list to merge from
1045  * @mode: the mode to use
1046  *
1047  * Inserts the tags of the @from list into the first list using the given mode.
1048  */
1049 void
1050 gst_tag_list_insert (GstTagList * into, const GstTagList * from,
1051     GstTagMergeMode mode)
1052 {
1053   GstTagCopyData data;
1054
1055   g_return_if_fail (GST_IS_TAG_LIST (into));
1056   g_return_if_fail (gst_tag_list_is_writable (into));
1057   g_return_if_fail (GST_IS_TAG_LIST (from));
1058   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1059
1060   data.list = into;
1061   data.mode = mode;
1062   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
1063     gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (into));
1064   }
1065   gst_structure_foreach (GST_TAG_LIST_STRUCTURE (from),
1066       gst_tag_list_copy_foreach, &data);
1067 }
1068
1069 /**
1070  * gst_tag_list_merge:
1071  * @list1: first list to merge
1072  * @list2: second list to merge
1073  * @mode: the mode to use
1074  *
1075  * Merges the two given lists into a new list. If one of the lists is NULL, a
1076  * copy of the other is returned. If both lists are NULL, NULL is returned.
1077  *
1078  * Free-function: gst_tag_list_unref
1079  *
1080  * Returns: (transfer full): the new list
1081  */
1082 GstTagList *
1083 gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2,
1084     GstTagMergeMode mode)
1085 {
1086   GstTagList *list1_cp;
1087   const GstTagList *list2_cp;
1088
1089   g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL);
1090   g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL);
1091   g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL);
1092
1093   /* nothing to merge */
1094   if (!list1 && !list2) {
1095     return NULL;
1096   }
1097
1098   /* create empty list, we need to do this to correctly handling merge modes */
1099   list1_cp = (list1) ? gst_tag_list_copy (list1) : gst_tag_list_new_empty ();
1100   list2_cp = (list2) ? list2 : gst_tag_list_new_empty ();
1101
1102   gst_tag_list_insert (list1_cp, list2_cp, mode);
1103
1104   if (!list2)
1105     gst_tag_list_unref ((GstTagList *) list2_cp);
1106
1107   return list1_cp;
1108 }
1109
1110 /**
1111  * gst_tag_list_get_tag_size:
1112  * @list: a taglist
1113  * @tag: the tag to query
1114  *
1115  * Checks how many value are stored in this tag list for the given tag.
1116  *
1117  * Returns: The number of tags stored
1118  */
1119 guint
1120 gst_tag_list_get_tag_size (const GstTagList * list, const gchar * tag)
1121 {
1122   const GValue *value;
1123
1124   g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
1125
1126   value = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag);
1127   if (value == NULL)
1128     return 0;
1129   if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
1130     return 1;
1131
1132   return gst_value_list_get_size (value);
1133 }
1134
1135 /**
1136  * gst_tag_list_add:
1137  * @list: list to set tags in
1138  * @mode: the mode to use
1139  * @tag: tag
1140  * @...: NULL-terminated list of values to set
1141  *
1142  * Sets the values for the given tags using the specified mode.
1143  */
1144 void
1145 gst_tag_list_add (GstTagList * list, GstTagMergeMode mode, const gchar * tag,
1146     ...)
1147 {
1148   va_list args;
1149
1150   g_return_if_fail (GST_IS_TAG_LIST (list));
1151   g_return_if_fail (gst_tag_list_is_writable (list));
1152   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1153   g_return_if_fail (tag != NULL);
1154
1155   va_start (args, tag);
1156   gst_tag_list_add_valist (list, mode, tag, args);
1157   va_end (args);
1158 }
1159
1160 /**
1161  * gst_tag_list_add_values:
1162  * @list: list to set tags in
1163  * @mode: the mode to use
1164  * @tag: tag
1165  * @...: GValues to set
1166  *
1167  * Sets the GValues for the given tags using the specified mode.
1168  */
1169 void
1170 gst_tag_list_add_values (GstTagList * list, GstTagMergeMode mode,
1171     const gchar * tag, ...)
1172 {
1173   va_list args;
1174
1175   g_return_if_fail (GST_IS_TAG_LIST (list));
1176   g_return_if_fail (gst_tag_list_is_writable (list));
1177   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1178   g_return_if_fail (tag != NULL);
1179
1180   va_start (args, tag);
1181   gst_tag_list_add_valist_values (list, mode, tag, args);
1182   va_end (args);
1183 }
1184
1185 /**
1186  * gst_tag_list_add_valist:
1187  * @list: list to set tags in
1188  * @mode: the mode to use
1189  * @tag: tag
1190  * @var_args: tag / value pairs to set
1191  *
1192  * Sets the values for the given tags using the specified mode.
1193  */
1194 void
1195 gst_tag_list_add_valist (GstTagList * list, GstTagMergeMode mode,
1196     const gchar * tag, va_list var_args)
1197 {
1198   GstTagInfo *info;
1199   gchar *error = NULL;
1200
1201   g_return_if_fail (GST_IS_TAG_LIST (list));
1202   g_return_if_fail (gst_tag_list_is_writable (list));
1203   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1204   g_return_if_fail (tag != NULL);
1205
1206   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
1207     gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (list));
1208   }
1209
1210   while (tag != NULL) {
1211     GValue value = { 0, };
1212
1213     info = gst_tag_lookup (tag);
1214     if (G_UNLIKELY (info == NULL)) {
1215       g_warning ("unknown tag '%s'", tag);
1216       return;
1217     }
1218     G_VALUE_COLLECT_INIT (&value, info->type, var_args, 0, &error);
1219     if (error) {
1220       g_warning ("%s: %s", G_STRLOC, error);
1221       g_free (error);
1222       /* we purposely leak the value here, it might not be
1223        * in a sane state if an error condition occoured
1224        */
1225       return;
1226     }
1227     gst_tag_list_add_value_internal (list, mode, tag, &value, info);
1228     g_value_unset (&value);
1229     tag = va_arg (var_args, gchar *);
1230   }
1231 }
1232
1233 /**
1234  * gst_tag_list_add_valist_values:
1235  * @list: list to set tags in
1236  * @mode: the mode to use
1237  * @tag: tag
1238  * @var_args: tag / GValue pairs to set
1239  *
1240  * Sets the GValues for the given tags using the specified mode.
1241  */
1242 void
1243 gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode,
1244     const gchar * tag, va_list var_args)
1245 {
1246   g_return_if_fail (GST_IS_TAG_LIST (list));
1247   g_return_if_fail (gst_tag_list_is_writable (list));
1248   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1249   g_return_if_fail (tag != NULL);
1250
1251   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
1252     gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (list));
1253   }
1254
1255   while (tag != NULL) {
1256     GstTagInfo *info;
1257
1258     info = gst_tag_lookup (tag);
1259     if (G_UNLIKELY (info == NULL)) {
1260       g_warning ("unknown tag '%s'", tag);
1261       return;
1262     }
1263     gst_tag_list_add_value_internal (list, mode, tag, va_arg (var_args,
1264             GValue *), info);
1265     tag = va_arg (var_args, gchar *);
1266   }
1267 }
1268
1269 /**
1270  * gst_tag_list_add_value:
1271  * @list: list to set tags in
1272  * @mode: the mode to use
1273  * @tag: tag
1274  * @value: GValue for this tag
1275  *
1276  * Sets the GValue for a given tag using the specified mode.
1277  *
1278  * Since: 0.10.24
1279  */
1280 void
1281 gst_tag_list_add_value (GstTagList * list, GstTagMergeMode mode,
1282     const gchar * tag, const GValue * value)
1283 {
1284   g_return_if_fail (GST_IS_TAG_LIST (list));
1285   g_return_if_fail (gst_tag_list_is_writable (list));
1286   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1287   g_return_if_fail (tag != NULL);
1288
1289   gst_tag_list_add_value_internal (list, mode, tag, value, NULL);
1290 }
1291
1292 /**
1293  * gst_tag_list_remove_tag:
1294  * @list: list to remove tag from
1295  * @tag: tag to remove
1296  *
1297  * Removes the given tag from the taglist.
1298  */
1299 void
1300 gst_tag_list_remove_tag (GstTagList * list, const gchar * tag)
1301 {
1302   g_return_if_fail (GST_IS_TAG_LIST (list));
1303   g_return_if_fail (tag != NULL);
1304
1305   gst_structure_remove_field (GST_TAG_LIST_STRUCTURE (list), tag);
1306 }
1307
1308 typedef struct
1309 {
1310   GstTagForeachFunc func;
1311   const GstTagList *tag_list;
1312   gpointer data;
1313 }
1314 TagForeachData;
1315
1316 static int
1317 structure_foreach_wrapper (GQuark field_id, const GValue * value,
1318     gpointer user_data)
1319 {
1320   TagForeachData *data = (TagForeachData *) user_data;
1321
1322   data->func (data->tag_list, g_quark_to_string (field_id), data->data);
1323   return TRUE;
1324 }
1325
1326 /**
1327  * gst_tag_list_foreach:
1328  * @list: list to iterate over
1329  * @func: (scope call): function to be called for each tag
1330  * @user_data: (closure): user specified data
1331  *
1332  * Calls the given function for each tag inside the tag list. Note that if there
1333  * is no tag, the function won't be called at all.
1334  */
1335 void
1336 gst_tag_list_foreach (const GstTagList * list, GstTagForeachFunc func,
1337     gpointer user_data)
1338 {
1339   TagForeachData data;
1340
1341   g_return_if_fail (GST_IS_TAG_LIST (list));
1342   g_return_if_fail (func != NULL);
1343
1344   data.func = func;
1345   data.tag_list = list;
1346   data.data = user_data;
1347   gst_structure_foreach (GST_TAG_LIST_STRUCTURE (list),
1348       structure_foreach_wrapper, &data);
1349 }
1350
1351 /**
1352  * gst_tag_list_get_value_index:
1353  * @list: a #GstTagList
1354  * @tag: tag to read out
1355  * @index: number of entry to read out
1356  *
1357  * Gets the value that is at the given index for the given tag in the given
1358  * list.
1359  *
1360  * Returns: (transfer none): The GValue for the specified entry or NULL if the
1361  *          tag wasn't available or the tag doesn't have as many entries
1362  */
1363 const GValue *
1364 gst_tag_list_get_value_index (const GstTagList * list, const gchar * tag,
1365     guint index)
1366 {
1367   const GValue *value;
1368
1369   g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
1370   g_return_val_if_fail (tag != NULL, NULL);
1371
1372   value = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag);
1373   if (value == NULL)
1374     return NULL;
1375
1376   if (GST_VALUE_HOLDS_LIST (value)) {
1377     if (index >= gst_value_list_get_size (value))
1378       return NULL;
1379     return gst_value_list_get_value (value, index);
1380   } else {
1381     if (index > 0)
1382       return NULL;
1383     return value;
1384   }
1385 }
1386
1387 /**
1388  * gst_tag_list_copy_value:
1389  * @dest: (out caller-allocates): uninitialized #GValue to copy into
1390  * @list: list to get the tag from
1391  * @tag: tag to read out
1392  *
1393  * Copies the contents for the given tag into the value,
1394  * merging multiple values into one if multiple values are associated
1395  * with the tag.
1396  * You must g_value_unset() the value after use.
1397  *
1398  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1399  *          given list.
1400  */
1401 gboolean
1402 gst_tag_list_copy_value (GValue * dest, const GstTagList * list,
1403     const gchar * tag)
1404 {
1405   const GValue *src;
1406
1407   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1408   g_return_val_if_fail (tag != NULL, FALSE);
1409   g_return_val_if_fail (dest != NULL, FALSE);
1410   g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE);
1411
1412   src = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag);
1413   if (!src)
1414     return FALSE;
1415
1416   if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
1417     GstTagInfo *info = gst_tag_lookup (tag);
1418
1419     if (!info)
1420       return FALSE;
1421
1422     /* must be there or lists aren't allowed */
1423     g_assert (info->merge_func);
1424     info->merge_func (dest, src);
1425   } else {
1426     g_value_init (dest, G_VALUE_TYPE (src));
1427     g_value_copy (src, dest);
1428   }
1429   return TRUE;
1430 }
1431
1432 /* FIXME 0.11: this whole merge function business is overdesigned, and the
1433  * _get_foo() API is misleading as well - how many application developers will
1434  * expect gst_tag_list_get_string (list, GST_TAG_ARTIST, &val) might return a
1435  * string with multiple comma-separated artists? _get_foo() should just be
1436  * a convenience wrapper around _get_foo_index (list, tag, 0, &val),
1437  * supplemented by a special _tag_list_get_string_merged() function if needed
1438  * (unless someone can actually think of real use cases where the merge
1439  * function is not 'use first' for non-strings and merge for strings) */
1440
1441 /***** evil macros to get all the gst_tag_list_get_*() functions right *****/
1442
1443 #define TAG_MERGE_FUNCS(name,type,ret)                                  \
1444 gboolean                                                                \
1445 gst_tag_list_get_ ## name (const GstTagList *list, const gchar *tag,    \
1446                            type *value)                                 \
1447 {                                                                       \
1448   GValue v = { 0, };                                                    \
1449                                                                         \
1450   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);                 \
1451   g_return_val_if_fail (tag != NULL, FALSE);                            \
1452   g_return_val_if_fail (value != NULL, FALSE);                          \
1453                                                                         \
1454   if (!gst_tag_list_copy_value (&v, list, tag))                         \
1455       return FALSE;                                                     \
1456   *value = COPY_FUNC (g_value_get_ ## name (&v));                       \
1457   g_value_unset (&v);                                                   \
1458   return ret;                                                           \
1459 }                                                                       \
1460                                                                         \
1461 gboolean                                                                \
1462 gst_tag_list_get_ ## name ## _index (const GstTagList *list,            \
1463                                      const gchar *tag,                  \
1464                                      guint index, type *value)          \
1465 {                                                                       \
1466   const GValue *v;                                                      \
1467                                                                         \
1468   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);                 \
1469   g_return_val_if_fail (tag != NULL, FALSE);                            \
1470   g_return_val_if_fail (value != NULL, FALSE);                          \
1471                                                                         \
1472   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)    \
1473       return FALSE;                                                     \
1474   *value = COPY_FUNC (g_value_get_ ## name (v));                        \
1475   return ret;                                                           \
1476 }
1477
1478 #define COPY_FUNC /**/
1479 /**
1480  * gst_tag_list_get_boolean:
1481  * @list: a #GstTagList to get the tag from
1482  * @tag: tag to read out
1483  * @value: (out): location for the result
1484  *
1485  * Copies the contents for the given tag into the value, merging multiple values
1486  * into one if multiple values are associated with the tag.
1487  *
1488  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1489  *              given list.
1490  */
1491 /**
1492  * gst_tag_list_get_boolean_index:
1493  * @list: a #GstTagList to get the tag from
1494  * @tag: tag to read out
1495  * @index: number of entry to read out
1496  * @value: (out): location for the result
1497  *
1498  * Gets the value that is at the given index for the given tag in the given
1499  * list.
1500  *
1501  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1502  *              given list.
1503  */
1504 TAG_MERGE_FUNCS (boolean, gboolean, TRUE);
1505 /**
1506  * gst_tag_list_get_int:
1507  * @list: a #GstTagList to get the tag from
1508  * @tag: tag to read out
1509  * @value: (out): location for the result
1510  *
1511  * Copies the contents for the given tag into the value, merging multiple values
1512  * into one if multiple values are associated with the tag.
1513  *
1514  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1515  *              given list.
1516  */
1517 /**
1518  * gst_tag_list_get_int_index:
1519  * @list: a #GstTagList to get the tag from
1520  * @tag: tag to read out
1521  * @index: number of entry to read out
1522  * @value: (out): location for the result
1523  *
1524  * Gets the value that is at the given index for the given tag in the given
1525  * list.
1526  *
1527  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1528  *              given list.
1529  */
1530 TAG_MERGE_FUNCS (int, gint, TRUE);
1531 /**
1532  * gst_tag_list_get_uint:
1533  * @list: a #GstTagList to get the tag from
1534  * @tag: tag to read out
1535  * @value: (out): location for the result
1536  *
1537  * Copies the contents for the given tag into the value, merging multiple values
1538  * into one if multiple values are associated with the tag.
1539  *
1540  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1541  *              given list.
1542  */
1543 /**
1544  * gst_tag_list_get_uint_index:
1545  * @list: a #GstTagList to get the tag from
1546  * @tag: tag to read out
1547  * @index: number of entry to read out
1548  * @value: (out): location for the result
1549  *
1550  * Gets the value that is at the given index for the given tag in the given
1551  * list.
1552  *
1553  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1554  *              given list.
1555  */
1556 TAG_MERGE_FUNCS (uint, guint, TRUE);
1557 /**
1558  * gst_tag_list_get_int64_index:
1559  * @list: a #GstTagList to get the tag from
1560  * @tag: tag to read out
1561  * @index: number of entry to read out
1562  * @value: (out): location for the result
1563  *
1564  * Gets the value that is at the given index for the given tag in the given
1565  * list.
1566  *
1567  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1568  *              given list.
1569  */
1570 TAG_MERGE_FUNCS (int64, gint64, TRUE);
1571 /**
1572  * gst_tag_list_get_uint64:
1573  * @list: a #GstTagList to get the tag from
1574  * @tag: tag to read out
1575  * @value: (out): location for the result
1576  *
1577  * Copies the contents for the given tag into the value, merging multiple values
1578  * into one if multiple values are associated with the tag.
1579  *
1580  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1581  *              given list.
1582  */
1583 /**
1584  * gst_tag_list_get_uint64_index:
1585  * @list: a #GstTagList to get the tag from
1586  * @tag: tag to read out
1587  * @index: number of entry to read out
1588  * @value: (out): location for the result
1589  *
1590  * Gets the value that is at the given index for the given tag in the given
1591  * list.
1592  *
1593  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1594  *              given list.
1595  */
1596 TAG_MERGE_FUNCS (uint64, guint64, TRUE);
1597 /**
1598  * gst_tag_list_get_float:
1599  * @list: a #GstTagList to get the tag from
1600  * @tag: tag to read out
1601  * @value: (out): location for the result
1602  *
1603  * Copies the contents for the given tag into the value, merging multiple values
1604  * into one if multiple values are associated with the tag.
1605  *
1606  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1607  *              given list.
1608  */
1609 /**
1610  * gst_tag_list_get_float_index:
1611  * @list: a #GstTagList to get the tag from
1612  * @tag: tag to read out
1613  * @index: number of entry to read out
1614  * @value: (out): location for the result
1615  *
1616  * Gets the value that is at the given index for the given tag in the given
1617  * list.
1618  *
1619  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1620  *              given list.
1621  */
1622 TAG_MERGE_FUNCS (float, gfloat, TRUE);
1623 /**
1624  * gst_tag_list_get_double:
1625  * @list: a #GstTagList to get the tag from
1626  * @tag: tag to read out
1627  * @value: (out): location for the result
1628  *
1629  * Copies the contents for the given tag into the value, merging multiple values
1630  * into one if multiple values are associated with the tag.
1631  *
1632  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1633  *              given list.
1634  */
1635 /**
1636  * gst_tag_list_get_double_index:
1637  * @list: a #GstTagList to get the tag from
1638  * @tag: tag to read out
1639  * @index: number of entry to read out
1640  * @value: (out): location for the result
1641  *
1642  * Gets the value that is at the given index for the given tag in the given
1643  * list.
1644  *
1645  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1646  *              given list.
1647  */
1648 TAG_MERGE_FUNCS (double, gdouble, TRUE);
1649 /**
1650  * gst_tag_list_get_pointer:
1651  * @list: a #GstTagList to get the tag from
1652  * @tag: tag to read out
1653  * @value: (out) (transfer none): location for the result
1654  *
1655  * Copies the contents for the given tag into the value, merging multiple values
1656  * into one if multiple values are associated with the tag.
1657  *
1658  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1659  *              given list.
1660  */
1661 /**
1662  * gst_tag_list_get_pointer_index:
1663  * @list: a #GstTagList to get the tag from
1664  * @tag: tag to read out
1665  * @index: number of entry to read out
1666  * @value: (out) (transfer none): location for the result
1667  *
1668  * Gets the value that is at the given index for the given tag in the given
1669  * list.
1670  *
1671  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1672  *              given list.
1673  */
1674 TAG_MERGE_FUNCS (pointer, gpointer, (*value != NULL));
1675
1676 static inline gchar *
1677 _gst_strdup0 (const gchar * s)
1678 {
1679   if (s == NULL || *s == '\0')
1680     return NULL;
1681
1682   return g_strdup (s);
1683 }
1684
1685 #undef COPY_FUNC
1686 #define COPY_FUNC _gst_strdup0
1687
1688 /**
1689  * gst_tag_list_get_string:
1690  * @list: a #GstTagList to get the tag from
1691  * @tag: tag to read out
1692  * @value: (out callee-allocates) (transfer full): location for the result
1693  *
1694  * Copies the contents for the given tag into the value, possibly merging
1695  * multiple values into one if multiple values are associated with the tag.
1696  *
1697  * Use gst_tag_list_get_string_index (list, tag, 0, value) if you want
1698  * to retrieve the first string associated with this tag unmodified.
1699  *
1700  * The resulting string in @value will be in UTF-8 encoding and should be
1701  * freed by the caller using g_free when no longer needed. Since 0.10.24 the
1702  * returned string is also guaranteed to be non-NULL and non-empty.
1703  *
1704  * Free-function: g_free
1705  *
1706  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1707  *              given list.
1708  */
1709 /**
1710  * gst_tag_list_get_string_index:
1711  * @list: a #GstTagList to get the tag from
1712  * @tag: tag to read out
1713  * @index: number of entry to read out
1714  * @value: (out callee-allocates) (transfer full): location for the result
1715  *
1716  * Gets the value that is at the given index for the given tag in the given
1717  * list.
1718  *
1719  * The resulting string in @value will be in UTF-8 encoding and should be
1720  * freed by the caller using g_free when no longer needed. Since 0.10.24 the
1721  * returned string is also guaranteed to be non-NULL and non-empty.
1722  *
1723  * Free-function: g_free
1724  *
1725  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1726  *              given list.
1727  */
1728 TAG_MERGE_FUNCS (string, gchar *, (*value != NULL));
1729
1730 /*
1731  *FIXME 0.11: Instead of _peek (non-copy) and _get (copy), we could have
1732  *            _get (non-copy) and _dup (copy) for strings, seems more
1733  *            widely used
1734  */
1735 /**
1736  * gst_tag_list_peek_string_index:
1737  * @list: a #GstTagList to get the tag from
1738  * @tag: tag to read out
1739  * @index: number of entry to read out
1740  * @value: (out) (transfer none): location for the result
1741  *
1742  * Peeks at the value that is at the given index for the given tag in the given
1743  * list.
1744  *
1745  * The resulting string in @value will be in UTF-8 encoding and doesn't need
1746  * to be freed by the caller. The returned string is also guaranteed to
1747  * be non-NULL and non-empty.
1748  *
1749  * Returns: TRUE, if a value was set, FALSE if the tag didn't exist in the
1750  *              given list.
1751  */
1752 gboolean
1753 gst_tag_list_peek_string_index (const GstTagList * list,
1754     const gchar * tag, guint index, const gchar ** value)
1755 {
1756   const GValue *v;
1757
1758   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1759   g_return_val_if_fail (tag != NULL, FALSE);
1760   g_return_val_if_fail (value != NULL, FALSE);
1761
1762   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1763     return FALSE;
1764   *value = g_value_get_string (v);
1765   return *value != NULL && **value != '\0';
1766 }
1767
1768 /**
1769  * gst_tag_list_get_date:
1770  * @list: a #GstTagList to get the tag from
1771  * @tag: tag to read out
1772  * @value: (out callee-allocates) (transfer full): address of a GDate pointer
1773  *     variable to store the result into
1774  *
1775  * Copies the first date for the given tag in the taglist into the variable
1776  * pointed to by @value. Free the date with g_date_free() when it is no longer
1777  * needed.
1778  *
1779  * Free-function: g_date_free
1780  *
1781  * Returns: TRUE, if a date was copied, FALSE if the tag didn't exist in the
1782  *              given list or if it was #NULL.
1783  */
1784 gboolean
1785 gst_tag_list_get_date (const GstTagList * list, const gchar * tag,
1786     GDate ** value)
1787 {
1788   GValue v = { 0, };
1789
1790   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1791   g_return_val_if_fail (tag != NULL, FALSE);
1792   g_return_val_if_fail (value != NULL, FALSE);
1793
1794   if (!gst_tag_list_copy_value (&v, list, tag))
1795     return FALSE;
1796   *value = (GDate *) g_value_dup_boxed (&v);
1797   g_value_unset (&v);
1798   return (*value != NULL);
1799 }
1800
1801 /**
1802  * gst_tag_list_get_date_index:
1803  * @list: a #GstTagList to get the tag from
1804  * @tag: tag to read out
1805  * @index: number of entry to read out
1806  * @value: (out callee-allocates) (transfer full): location for the result
1807  *
1808  * Gets the date that is at the given index for the given tag in the given
1809  * list and copies it into the variable pointed to by @value. Free the date
1810  * with g_date_free() when it is no longer needed.
1811  *
1812  * Free-function: g_date_free
1813  *
1814  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1815  *              given list or if it was #NULL.
1816  */
1817 gboolean
1818 gst_tag_list_get_date_index (const GstTagList * list,
1819     const gchar * tag, guint index, GDate ** value)
1820 {
1821   const GValue *v;
1822
1823   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1824   g_return_val_if_fail (tag != NULL, FALSE);
1825   g_return_val_if_fail (value != NULL, FALSE);
1826
1827   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1828     return FALSE;
1829   *value = (GDate *) g_value_dup_boxed (v);
1830   return (*value != NULL);
1831 }
1832
1833 /**
1834  * gst_tag_list_get_date_time:
1835  * @list: a #GstTagList to get the tag from
1836  * @tag: tag to read out
1837  * @value: (out callee-allocates) (transfer full): address of a #GstDateTime
1838  *     pointer variable to store the result into
1839  *
1840  * Copies the first datetime for the given tag in the taglist into the variable
1841  * pointed to by @value. Unref the date with gst_date_time_unref() when
1842  * it is no longer needed.
1843  *
1844  * Free-function: gst_date_time_unref
1845  *
1846  * Returns: TRUE, if a datetime was copied, FALSE if the tag didn't exist in
1847  *              thegiven list or if it was #NULL.
1848  *
1849  * Since: 0.10.31
1850  */
1851 gboolean
1852 gst_tag_list_get_date_time (const GstTagList * list, const gchar * tag,
1853     GstDateTime ** value)
1854 {
1855   GValue v = { 0, };
1856
1857   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1858   g_return_val_if_fail (tag != NULL, FALSE);
1859   g_return_val_if_fail (value != NULL, FALSE);
1860
1861   if (!gst_tag_list_copy_value (&v, list, tag))
1862     return FALSE;
1863
1864   g_return_val_if_fail (GST_VALUE_HOLDS_DATE_TIME (&v), FALSE);
1865
1866   *value = (GstDateTime *) g_value_dup_boxed (&v);
1867   g_value_unset (&v);
1868   return (*value != NULL);
1869 }
1870
1871 /**
1872  * gst_tag_list_get_date_time_index:
1873  * @list: a #GstTagList to get the tag from
1874  * @tag: tag to read out
1875  * @index: number of entry to read out
1876  * @value: (out callee-allocates) (transfer full): location for the result
1877  *
1878  * Gets the datetime that is at the given index for the given tag in the given
1879  * list and copies it into the variable pointed to by @value. Unref the datetime
1880  * with gst_date_time_unref() when it is no longer needed.
1881  *
1882  * Free-function: gst_date_time_unref
1883  *
1884  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1885  *              given list or if it was #NULL.
1886  *
1887  * Since: 0.10.31
1888  */
1889 gboolean
1890 gst_tag_list_get_date_time_index (const GstTagList * list,
1891     const gchar * tag, guint index, GstDateTime ** value)
1892 {
1893   const GValue *v;
1894
1895   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1896   g_return_val_if_fail (tag != NULL, FALSE);
1897   g_return_val_if_fail (value != NULL, FALSE);
1898
1899   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1900     return FALSE;
1901   *value = (GstDateTime *) g_value_dup_boxed (v);
1902   return (*value != NULL);
1903 }
1904
1905 /**
1906  * gst_tag_list_get_buffer:
1907  * @list: a #GstTagList to get the tag from
1908  * @tag: tag to read out
1909  * @value: (out callee-allocates) (transfer full): address of a GstBuffer
1910  *     pointer variable to store the result into
1911  *
1912  * Copies the first buffer for the given tag in the taglist into the variable
1913  * pointed to by @value. Free the buffer with gst_buffer_unref() when it is
1914  * no longer needed.
1915  *
1916  * Free-function: gst_buffer_unref
1917  *
1918  * Returns: TRUE, if a buffer was copied, FALSE if the tag didn't exist in the
1919  *              given list or if it was #NULL.
1920  *
1921  * Since: 0.10.23
1922  */
1923 gboolean
1924 gst_tag_list_get_buffer (const GstTagList * list, const gchar * tag,
1925     GstBuffer ** value)
1926 {
1927   GValue v = { 0, };
1928
1929   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1930   g_return_val_if_fail (tag != NULL, FALSE);
1931   g_return_val_if_fail (value != NULL, FALSE);
1932
1933   if (!gst_tag_list_copy_value (&v, list, tag))
1934     return FALSE;
1935   *value = g_value_dup_boxed (&v);
1936   g_value_unset (&v);
1937   return (*value != NULL);
1938 }
1939
1940 /**
1941  * gst_tag_list_get_buffer_index:
1942  * @list: a #GstTagList to get the tag from
1943  * @tag: tag to read out
1944  * @index: number of entry to read out
1945  * @value: (out callee-allocates) (transfer full): address of a GstBuffer
1946  *     pointer variable to store the result into
1947  *
1948  * Gets the buffer that is at the given index for the given tag in the given
1949  * list and copies it into the variable pointed to by @value. Free the buffer
1950  * with gst_buffer_unref() when it is no longer needed.
1951  *
1952  * Free-function: gst_buffer_unref
1953  *
1954  * Returns: TRUE, if a buffer was copied, FALSE if the tag didn't exist in the
1955  *              given list or if it was #NULL.
1956  *
1957  * Since: 0.10.23
1958  */
1959 gboolean
1960 gst_tag_list_get_buffer_index (const GstTagList * list,
1961     const gchar * tag, guint index, GstBuffer ** value)
1962 {
1963   const GValue *v;
1964
1965   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1966   g_return_val_if_fail (tag != NULL, FALSE);
1967   g_return_val_if_fail (value != NULL, FALSE);
1968
1969   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1970     return FALSE;
1971   *value = g_value_dup_boxed (v);
1972   return (*value != NULL);
1973 }