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