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