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