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