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