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