2 * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
4 * gsttaglist.c: tag support (aka metadata)
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.
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.
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.
24 * @short_description: List of tags and values used to describe media metadata
26 * List of tags and values used to describe media metadata.
28 * Strings must be in ASCII or UTF-8 encoding. No other encodings are allowed.
30 * Last reviewed on 2009-06-09 (0.10.23)
37 #include "gst_private.h"
38 #include "math-compat.h"
39 #include "gst-i18n-lib.h"
40 #include "gsttaglist.h"
43 #include "gstbuffer.h"
46 #include <gobject/gvaluecollector.h>
49 #define GST_TAG_IS_VALID(tag) (gst_tag_get_info (tag) != NULL)
51 /* FIXME 0.11: use GParamSpecs or something similar for tag registrations,
52 * possibly even gst_tag_register(). Especially value ranges might be
53 * useful for some tags. */
57 GType type; /* type the data is in */
59 gchar *nick; /* translated name */
60 gchar *blurb; /* translated description of type */
62 GstTagMergeFunc merge_func; /* functions to merge the values */
63 GstTagFlag flag; /* type of tag */
64 GQuark name_quark; /* quark for the name */
68 static GMutex *__tag_mutex;
70 /* tags hash table: maps tag name string => GstTagInfo */
71 static GHashTable *__tags;
73 #define TAG_LOCK g_mutex_lock (__tag_mutex)
74 #define TAG_UNLOCK g_mutex_unlock (__tag_mutex)
77 gst_tag_list_get_type (void)
79 static GType _gst_tag_list_type = 0;
81 if (G_UNLIKELY (_gst_tag_list_type == 0)) {
82 _gst_tag_list_type = g_boxed_type_register_static ("GstTagList",
83 (GBoxedCopyFunc) gst_tag_list_copy, (GBoxedFreeFunc) gst_tag_list_free);
86 g_value_register_transform_func (_gst_tag_list_type, G_TYPE_STRING,
87 _gst_structure_transform_to_string);
91 return _gst_tag_list_type;
95 _priv_gst_tag_initialize (void)
97 __tag_mutex = g_mutex_new ();
98 __tags = g_hash_table_new (g_str_hash, g_str_equal);
99 gst_tag_register (GST_TAG_TITLE, GST_TAG_FLAG_META,
101 _("title"), _("commonly used title"), gst_tag_merge_strings_with_comma);
102 gst_tag_register (GST_TAG_TITLE_SORTNAME, GST_TAG_FLAG_META,
104 _("title sortname"), _("commonly used title for sorting purposes"), NULL);
105 gst_tag_register (GST_TAG_ARTIST, GST_TAG_FLAG_META,
108 _("person(s) responsible for the recording"),
109 gst_tag_merge_strings_with_comma);
110 gst_tag_register (GST_TAG_ARTIST_SORTNAME, GST_TAG_FLAG_META,
112 _("artist sortname"),
113 _("person(s) responsible for the recording for sorting purposes"), NULL);
114 gst_tag_register (GST_TAG_ALBUM, GST_TAG_FLAG_META,
117 _("album containing this data"), gst_tag_merge_strings_with_comma);
118 gst_tag_register (GST_TAG_ALBUM_SORTNAME, GST_TAG_FLAG_META,
121 _("album containing this data for sorting purposes"), NULL);
122 gst_tag_register (GST_TAG_ALBUM_ARTIST, GST_TAG_FLAG_META,
125 _("The artist of the entire album, as it should be displayed"),
126 gst_tag_merge_strings_with_comma);
127 gst_tag_register (GST_TAG_ALBUM_ARTIST_SORTNAME, GST_TAG_FLAG_META,
129 _("album artist sortname"),
130 _("The artist of the entire album, as it should be sorted"), NULL);
131 gst_tag_register (GST_TAG_DATE, GST_TAG_FLAG_META, GST_TYPE_DATE,
132 _("date"), _("date the data was created (as a GDate structure)"), NULL);
133 gst_tag_register (GST_TAG_DATE_TIME, GST_TAG_FLAG_META, GST_TYPE_DATE_TIME,
135 _("date and time the data was created (as a GstDateTime structure)"),
137 gst_tag_register (GST_TAG_GENRE, GST_TAG_FLAG_META,
140 _("genre this data belongs to"), gst_tag_merge_strings_with_comma);
141 gst_tag_register (GST_TAG_COMMENT, GST_TAG_FLAG_META,
144 _("free text commenting the data"), gst_tag_merge_use_first);
145 gst_tag_register (GST_TAG_EXTENDED_COMMENT, GST_TAG_FLAG_META,
147 _("extended comment"),
148 _("free text commenting the data in key=value or key[en]=comment form"),
149 gst_tag_merge_use_first);
150 gst_tag_register (GST_TAG_TRACK_NUMBER, GST_TAG_FLAG_META,
153 _("track number inside a collection"), gst_tag_merge_use_first);
154 gst_tag_register (GST_TAG_TRACK_COUNT, GST_TAG_FLAG_META,
157 _("count of tracks inside collection this track belongs to"),
158 gst_tag_merge_use_first);
159 gst_tag_register (GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_FLAG_META,
162 _("disc number inside a collection"), gst_tag_merge_use_first);
163 gst_tag_register (GST_TAG_ALBUM_VOLUME_COUNT, GST_TAG_FLAG_META,
166 _("count of discs inside collection this disc belongs to"),
167 gst_tag_merge_use_first);
168 gst_tag_register (GST_TAG_LOCATION, GST_TAG_FLAG_META,
170 _("location"), _("Origin of media as a URI (location, where the "
171 "original of the file or stream is hosted)"),
172 gst_tag_merge_strings_with_comma);
173 gst_tag_register (GST_TAG_HOMEPAGE, GST_TAG_FLAG_META,
176 _("Homepage for this media (i.e. artist or movie homepage)"),
177 gst_tag_merge_strings_with_comma);
178 gst_tag_register (GST_TAG_DESCRIPTION, GST_TAG_FLAG_META, G_TYPE_STRING,
179 _("description"), _("short text describing the content of the data"),
180 gst_tag_merge_strings_with_comma);
181 gst_tag_register (GST_TAG_VERSION, GST_TAG_FLAG_META, G_TYPE_STRING,
182 _("version"), _("version of this data"), NULL);
183 gst_tag_register (GST_TAG_ISRC, GST_TAG_FLAG_META, G_TYPE_STRING, _("ISRC"),
185 ("International Standard Recording Code - see http://www.ifpi.org/isrc/"),
187 /* FIXME: organization (fix what? tpm) */
188 gst_tag_register (GST_TAG_ORGANIZATION, GST_TAG_FLAG_META, G_TYPE_STRING,
189 _("organization"), _("organization"), gst_tag_merge_strings_with_comma);
190 gst_tag_register (GST_TAG_COPYRIGHT, GST_TAG_FLAG_META,
191 G_TYPE_STRING, _("copyright"), _("copyright notice of the data"), NULL);
192 gst_tag_register (GST_TAG_COPYRIGHT_URI, GST_TAG_FLAG_META,
193 G_TYPE_STRING, _("copyright uri"),
194 _("URI to the copyright notice of the data"), NULL);
195 gst_tag_register (GST_TAG_ENCODED_BY, GST_TAG_FLAG_META, G_TYPE_STRING,
196 _("encoded by"), _("name of the encoding person or organization"),
197 gst_tag_merge_strings_with_comma);
198 gst_tag_register (GST_TAG_CONTACT, GST_TAG_FLAG_META,
200 _("contact"), _("contact information"), gst_tag_merge_strings_with_comma);
201 gst_tag_register (GST_TAG_LICENSE, GST_TAG_FLAG_META,
202 G_TYPE_STRING, _("license"), _("license of data"), NULL);
203 gst_tag_register (GST_TAG_LICENSE_URI, GST_TAG_FLAG_META,
204 G_TYPE_STRING, _("license uri"),
205 _("URI to the license of the data"), NULL);
206 gst_tag_register (GST_TAG_PERFORMER, GST_TAG_FLAG_META,
209 _("person(s) performing"), gst_tag_merge_strings_with_comma);
210 gst_tag_register (GST_TAG_COMPOSER, GST_TAG_FLAG_META,
213 _("person(s) who composed the recording"),
214 gst_tag_merge_strings_with_comma);
215 gst_tag_register (GST_TAG_DURATION, GST_TAG_FLAG_DECODED,
217 _("duration"), _("length in GStreamer time units (nanoseconds)"), NULL);
218 gst_tag_register (GST_TAG_CODEC, GST_TAG_FLAG_ENCODED,
221 _("codec the data is stored in"), gst_tag_merge_strings_with_comma);
222 gst_tag_register (GST_TAG_VIDEO_CODEC, GST_TAG_FLAG_ENCODED,
224 _("video codec"), _("codec the video data is stored in"), NULL);
225 gst_tag_register (GST_TAG_AUDIO_CODEC, GST_TAG_FLAG_ENCODED,
227 _("audio codec"), _("codec the audio data is stored in"), NULL);
228 gst_tag_register (GST_TAG_SUBTITLE_CODEC, GST_TAG_FLAG_ENCODED,
230 _("subtitle codec"), _("codec the subtitle data is stored in"), NULL);
231 gst_tag_register (GST_TAG_CONTAINER_FORMAT, GST_TAG_FLAG_ENCODED,
232 G_TYPE_STRING, _("container format"),
233 _("container format the data is stored in"), NULL);
234 gst_tag_register (GST_TAG_BITRATE, GST_TAG_FLAG_ENCODED,
235 G_TYPE_UINT, _("bitrate"), _("exact or average bitrate in bits/s"), NULL);
236 gst_tag_register (GST_TAG_NOMINAL_BITRATE, GST_TAG_FLAG_ENCODED,
237 G_TYPE_UINT, _("nominal bitrate"), _("nominal bitrate in bits/s"), NULL);
238 gst_tag_register (GST_TAG_MINIMUM_BITRATE, GST_TAG_FLAG_ENCODED,
239 G_TYPE_UINT, _("minimum bitrate"), _("minimum bitrate in bits/s"), NULL);
240 gst_tag_register (GST_TAG_MAXIMUM_BITRATE, GST_TAG_FLAG_ENCODED,
241 G_TYPE_UINT, _("maximum bitrate"), _("maximum bitrate in bits/s"), NULL);
242 gst_tag_register (GST_TAG_ENCODER, GST_TAG_FLAG_ENCODED,
244 _("encoder"), _("encoder used to encode this stream"), NULL);
245 gst_tag_register (GST_TAG_ENCODER_VERSION, GST_TAG_FLAG_ENCODED,
247 _("encoder version"),
248 _("version of the encoder used to encode this stream"), NULL);
249 gst_tag_register (GST_TAG_SERIAL, GST_TAG_FLAG_ENCODED,
250 G_TYPE_UINT, _("serial"), _("serial number of track"), NULL);
251 gst_tag_register (GST_TAG_TRACK_GAIN, GST_TAG_FLAG_META,
252 G_TYPE_DOUBLE, _("replaygain track gain"), _("track gain in db"), NULL);
253 gst_tag_register (GST_TAG_TRACK_PEAK, GST_TAG_FLAG_META,
254 G_TYPE_DOUBLE, _("replaygain track peak"), _("peak of the track"), NULL);
255 gst_tag_register (GST_TAG_ALBUM_GAIN, GST_TAG_FLAG_META,
256 G_TYPE_DOUBLE, _("replaygain album gain"), _("album gain in db"), NULL);
257 gst_tag_register (GST_TAG_ALBUM_PEAK, GST_TAG_FLAG_META,
258 G_TYPE_DOUBLE, _("replaygain album peak"), _("peak of the album"), NULL);
259 gst_tag_register (GST_TAG_REFERENCE_LEVEL, GST_TAG_FLAG_META,
260 G_TYPE_DOUBLE, _("replaygain reference level"),
261 _("reference level of track and album gain values"), NULL);
262 gst_tag_register (GST_TAG_LANGUAGE_CODE, GST_TAG_FLAG_META, G_TYPE_STRING,
264 _("language code for this stream, conforming to ISO-639-1"), NULL);
265 gst_tag_register (GST_TAG_IMAGE, GST_TAG_FLAG_META, GST_TYPE_BUFFER,
266 _("image"), _("image related to this stream"), gst_tag_merge_use_first);
267 gst_tag_register (GST_TAG_PREVIEW_IMAGE, GST_TAG_FLAG_META, GST_TYPE_BUFFER,
268 /* TRANSLATORS: 'preview image' = image that shows a preview of the full image */
269 _("preview image"), _("preview image related to this stream"), NULL);
270 gst_tag_register (GST_TAG_ATTACHMENT, GST_TAG_FLAG_META, GST_TYPE_BUFFER,
271 _("attachment"), _("file attached to this stream"),
272 gst_tag_merge_use_first);
273 gst_tag_register (GST_TAG_BEATS_PER_MINUTE, GST_TAG_FLAG_META, G_TYPE_DOUBLE,
274 _("beats per minute"), _("number of beats per minute in audio"), NULL);
275 gst_tag_register (GST_TAG_KEYWORDS, GST_TAG_FLAG_META, G_TYPE_STRING,
276 _("keywords"), _("comma separated keywords describing the content"),
277 gst_tag_merge_strings_with_comma);
278 gst_tag_register (GST_TAG_GEO_LOCATION_NAME, GST_TAG_FLAG_META, G_TYPE_STRING,
279 _("geo location name"), _("human readable descriptive location of where "
280 "the media has been recorded or produced"), NULL);
281 gst_tag_register (GST_TAG_GEO_LOCATION_LATITUDE, GST_TAG_FLAG_META,
282 G_TYPE_DOUBLE, _("geo location latitude"),
283 _("geo latitude location of where the media has been recorded or "
284 "produced in degrees according to WGS84 (zero at the equator, "
285 "negative values for southern latitudes)"), NULL);
286 gst_tag_register (GST_TAG_GEO_LOCATION_LONGITUDE, GST_TAG_FLAG_META,
287 G_TYPE_DOUBLE, _("geo location longitude"),
288 _("geo longitude location of where the media has been recorded or "
289 "produced in degrees according to WGS84 (zero at the prime meridian "
290 "in Greenwich/UK, negative values for western longitudes)"), NULL);
291 gst_tag_register (GST_TAG_GEO_LOCATION_ELEVATION, GST_TAG_FLAG_META,
292 G_TYPE_DOUBLE, _("geo location elevation"),
293 _("geo elevation of where the media has been recorded or produced in "
294 "meters according to WGS84 (zero is average sea level)"), NULL);
295 gst_tag_register (GST_TAG_GEO_LOCATION_COUNTRY, GST_TAG_FLAG_META,
296 G_TYPE_STRING, _("geo location country"),
297 _("country (english name) where the media has been recorded "
298 "or produced"), NULL);
299 gst_tag_register (GST_TAG_GEO_LOCATION_CITY, GST_TAG_FLAG_META,
300 G_TYPE_STRING, _("geo location city"),
301 _("city (english name) where the media has been recorded "
302 "or produced"), NULL);
303 gst_tag_register (GST_TAG_GEO_LOCATION_SUBLOCATION, GST_TAG_FLAG_META,
304 G_TYPE_STRING, _("geo location sublocation"),
305 _("a location whithin a city where the media has been produced "
306 "or created (e.g. the neighborhood)"), NULL);
307 gst_tag_register (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, GST_TAG_FLAG_META,
308 G_TYPE_DOUBLE, _("geo location horizontal error"),
309 _("expected error of the horizontal positioning measures (in meters)"),
311 gst_tag_register (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, GST_TAG_FLAG_META,
312 G_TYPE_DOUBLE, _("geo location movement speed"),
313 _("movement speed of the capturing device while performing the capture "
315 gst_tag_register (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, GST_TAG_FLAG_META,
316 G_TYPE_DOUBLE, _("geo location movement direction"),
317 _("indicates the movement direction of the device performing the capture"
318 " of a media. It is represented as degrees in floating point "
319 "representation, 0 means the geographic north, and increases "
321 gst_tag_register (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, GST_TAG_FLAG_META,
322 G_TYPE_DOUBLE, _("geo location capture direction"),
323 _("indicates the direction the device is pointing to when capturing "
324 " a media. It is represented as degrees in floating point "
325 " representation, 0 means the geographic north, and increases "
327 gst_tag_register (GST_TAG_SHOW_NAME, GST_TAG_FLAG_META, G_TYPE_STRING,
328 /* TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here */
330 _("Name of the tv/podcast/series show the media is from"),
331 gst_tag_merge_strings_with_comma);
332 gst_tag_register (GST_TAG_SHOW_SORTNAME, GST_TAG_FLAG_META, G_TYPE_STRING,
333 /* TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here */
335 _("Name of the tv/podcast/series show the media is from, for sorting "
337 gst_tag_register (GST_TAG_SHOW_EPISODE_NUMBER, GST_TAG_FLAG_META, G_TYPE_UINT,
339 _("The episode number in the season the media is part of"),
340 gst_tag_merge_use_first);
341 gst_tag_register (GST_TAG_SHOW_SEASON_NUMBER, GST_TAG_FLAG_META, G_TYPE_UINT,
343 _("The season number of the show the media is part of"),
344 gst_tag_merge_use_first);
345 gst_tag_register (GST_TAG_LYRICS, GST_TAG_FLAG_META, G_TYPE_STRING,
346 _("lyrics"), _("The lyrics of the media, commonly used for songs"),
347 gst_tag_merge_strings_with_comma);
348 gst_tag_register (GST_TAG_COMPOSER_SORTNAME, GST_TAG_FLAG_META, G_TYPE_STRING,
349 _("composer sortname"),
350 _("person(s) who composed the recording, for sorting purposes"), NULL);
351 gst_tag_register (GST_TAG_GROUPING, GST_TAG_FLAG_META, G_TYPE_STRING,
353 _("Groups related media that spans multiple tracks, like the different "
354 "pieces of a concerto. It is a higher level than a track, "
355 "but lower than an album"), NULL);
356 gst_tag_register (GST_TAG_USER_RATING, GST_TAG_FLAG_META, G_TYPE_UINT,
358 _("Rating attributed by a user. The higher the rank, "
359 "the more the user likes this media"), NULL);
360 gst_tag_register (GST_TAG_DEVICE_MANUFACTURER, GST_TAG_FLAG_META,
361 G_TYPE_STRING, _("device manufacturer"),
362 _("Manufacturer of the device used to create this media"), NULL);
363 gst_tag_register (GST_TAG_DEVICE_MODEL, GST_TAG_FLAG_META, G_TYPE_STRING,
365 _("Model of the device used to create this media"), NULL);
366 gst_tag_register (GST_TAG_APPLICATION_NAME, GST_TAG_FLAG_META, G_TYPE_STRING,
367 _("application name"), _("Application used to create the media"), NULL);
368 gst_tag_register (GST_TAG_APPLICATION_DATA, GST_TAG_FLAG_META,
369 GST_TYPE_BUFFER, _("application data"),
370 _("Arbitrary application data to be serialized into the media"), NULL);
371 gst_tag_register (GST_TAG_IMAGE_ORIENTATION, GST_TAG_FLAG_META, G_TYPE_STRING,
372 _("image orientation"),
373 _("How the image should be rotated or flipped before display"), NULL);
377 * gst_tag_merge_use_first:
378 * @dest: (out caller-allocates): uninitialized GValue to store result in
379 * @src: GValue to copy from
381 * This is a convenience function for the func argument of gst_tag_register().
382 * It creates a copy of the first value from the list.
385 gst_tag_merge_use_first (GValue * dest, const GValue * src)
387 const GValue *ret = gst_value_list_get_value (src, 0);
389 g_value_init (dest, G_VALUE_TYPE (ret));
390 g_value_copy (ret, dest);
394 * gst_tag_merge_strings_with_comma:
395 * @dest: (out caller-allocates): uninitialized GValue to store result in
396 * @src: GValue to copy from
398 * This is a convenience function for the func argument of gst_tag_register().
399 * It concatenates all given strings using a comma. The tag must be registered
400 * as a G_TYPE_STRING or this function will fail.
403 gst_tag_merge_strings_with_comma (GValue * dest, const GValue * src)
408 count = gst_value_list_get_size (src);
409 str = g_string_new (g_value_get_string (gst_value_list_get_value (src, 0)));
410 for (i = 1; i < count; i++) {
411 /* separator between two strings */
412 g_string_append (str, _(", "));
413 g_string_append (str,
414 g_value_get_string (gst_value_list_get_value (src, i)));
417 g_value_init (dest, G_TYPE_STRING);
418 g_value_take_string (dest, str->str);
419 g_string_free (str, FALSE);
423 gst_tag_lookup (const gchar * tag_name)
428 ret = g_hash_table_lookup (__tags, (gpointer) tag_name);
436 * @name: the name or identifier string
437 * @flag: a flag describing the type of tag info
438 * @type: the type this data is in
439 * @nick: human-readable name
440 * @blurb: a human-readable description about this tag
441 * @func: function for merging multiple values of this tag, or NULL
443 * Registers a new tag type for the use with GStreamer's type system. If a type
444 * with that name is already registered, that one is used.
445 * The old registration may have used a different type however. So don't rely
446 * on your supplied values.
448 * Important: if you do not supply a merge function the implication will be
449 * that there can only be one single value for this tag in a tag list and
450 * any additional values will silenty be discarded when being added (unless
451 * #GST_TAG_MERGE_REPLACE, #GST_TAG_MERGE_REPLACE_ALL, or
452 * #GST_TAG_MERGE_PREPEND is used as merge mode, in which case the new
453 * value will replace the old one in the list).
455 * The merge function will be called from gst_tag_list_copy_value() when
456 * it is required that one or more values for a tag be condensed into
457 * one single value. This may happen from gst_tag_list_get_string(),
458 * gst_tag_list_get_int(), gst_tag_list_get_double() etc. What will happen
459 * exactly in that case depends on how the tag was registered and if a
460 * merge function was supplied and if so which one.
462 * Two default merge functions are provided: gst_tag_merge_use_first() and
463 * gst_tag_merge_strings_with_comma().
466 gst_tag_register (const gchar * name, GstTagFlag flag, GType type,
467 const gchar * nick, const gchar * blurb, GstTagMergeFunc func)
472 g_return_if_fail (name != NULL);
473 g_return_if_fail (nick != NULL);
474 g_return_if_fail (blurb != NULL);
475 g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
477 info = gst_tag_lookup (name);
480 g_return_if_fail (info->type == type);
484 info = g_slice_new (GstTagInfo);
487 info->nick = g_strdup (nick);
488 info->blurb = g_strdup (blurb);
489 info->merge_func = func;
491 /* we make a copy for the hash table anyway, which will stay around, so
492 * can use that for the quark table too */
493 name_dup = g_strdup (name);
494 info->name_quark = g_quark_from_static_string (name_dup);
497 g_hash_table_insert (__tags, (gpointer) name_dup, info);
503 * @tag: name of the tag
505 * Checks if the given type is already registered.
507 * Returns: TRUE if the type is already registered
510 gst_tag_exists (const gchar * tag)
512 g_return_val_if_fail (tag != NULL, FALSE);
514 return gst_tag_lookup (tag) != NULL;
521 * Gets the #GType used for this tag.
523 * Returns: the #GType of this tag
526 gst_tag_get_type (const gchar * tag)
530 g_return_val_if_fail (tag != NULL, 0);
531 info = gst_tag_lookup (tag);
532 g_return_val_if_fail (info != NULL, 0);
541 * Returns the human-readable name of this tag, You must not change or free
544 * Returns: the human-readable name of this tag
547 gst_tag_get_nick (const gchar * tag)
551 g_return_val_if_fail (tag != NULL, NULL);
552 info = gst_tag_lookup (tag);
553 g_return_val_if_fail (info != NULL, NULL);
559 * gst_tag_get_description:
562 * Returns the human-readable description of this tag, You must not change or
565 * Returns: the human-readable description of this tag
568 gst_tag_get_description (const gchar * tag)
572 g_return_val_if_fail (tag != NULL, NULL);
573 info = gst_tag_lookup (tag);
574 g_return_val_if_fail (info != NULL, NULL);
583 * Gets the flag of @tag.
585 * Returns: the flag of this tag.
588 gst_tag_get_flag (const gchar * tag)
592 g_return_val_if_fail (tag != NULL, GST_TAG_FLAG_UNDEFINED);
593 info = gst_tag_lookup (tag);
594 g_return_val_if_fail (info != NULL, GST_TAG_FLAG_UNDEFINED);
603 * Checks if the given tag is fixed. A fixed tag can only contain one value.
604 * Unfixed tags can contain lists of values.
606 * Returns: TRUE, if the given tag is fixed.
609 gst_tag_is_fixed (const gchar * tag)
613 g_return_val_if_fail (tag != NULL, FALSE);
614 info = gst_tag_lookup (tag);
615 g_return_val_if_fail (info != NULL, FALSE);
617 return info->merge_func == NULL;
623 * Creates a new empty GstTagList.
625 * Free-function: gst_tag_list_free
627 * Returns: (transfer full): An empty tag list
630 gst_tag_list_new (void)
632 return GST_TAG_LIST (gst_structure_id_empty_new (GST_QUARK (TAGLIST)));
636 * gst_tag_list_new_full:
638 * @...: NULL-terminated list of values to set
640 * Creates a new taglist and appends the values for the given tags. It expects
641 * tag-value pairs like gst_tag_list_add(), and a NULL terminator after the
642 * last pair. The type of the values is implicit and is documented in the API
643 * reference, but can also be queried at runtime with gst_tag_get_type(). It
644 * is an error to pass a value of a type not matching the tag type into this
645 * function. The tag list will make copies of any arguments passed
646 * (e.g. strings, buffers).
648 * Free-function: gst_tag_list_free
650 * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_free()
651 * when no longer needed.
655 /* FIXME 0.11: rename gst_tag_list_new_full to _new and _new to _new_empty */
657 gst_tag_list_new_full (const gchar * tag, ...)
662 g_return_val_if_fail (tag != NULL, NULL);
664 list = gst_tag_list_new ();
665 va_start (args, tag);
666 gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, args);
673 * gst_tag_list_new_full_valist:
674 * @var_args: tag / value pairs to set
676 * Just like gst_tag_list_new_full(), only that it takes a va_list argument.
677 * Useful mostly for language bindings.
679 * Free-function: gst_tag_list_free
681 * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_free()
682 * when no longer needed.
687 gst_tag_list_new_full_valist (va_list var_args)
692 list = gst_tag_list_new ();
694 tag = va_arg (var_args, gchar *);
695 gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, var_args);
701 * gst_tag_list_to_string:
702 * @list: a #GstTagList
704 * Serializes a tag list to a string.
706 * Returns: a newly-allocated string, or NULL in case of an error. The
707 * string must be freed with g_free() when no longer needed.
712 gst_tag_list_to_string (const GstTagList * list)
714 g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
716 return gst_structure_to_string (GST_STRUCTURE (list));
720 * gst_tag_list_new_from_string:
721 * @str: a string created with gst_tag_list_to_string()
723 * Deserializes a tag list.
725 * Returns: a new #GstTagList, or NULL in case of an error.
730 gst_tag_list_new_from_string (const gchar * str)
732 g_return_val_if_fail (str != NULL, NULL);
733 g_return_val_if_fail (g_str_has_prefix (str, "taglist"), NULL);
735 return GST_TAG_LIST (gst_structure_from_string (str, NULL));
739 * gst_tag_list_is_empty:
740 * @list: A #GstTagList.
742 * Checks if the given taglist is empty.
744 * Returns: TRUE if the taglist is empty, otherwise FALSE.
749 gst_tag_list_is_empty (const GstTagList * list)
751 g_return_val_if_fail (list != NULL, FALSE);
752 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
754 return (gst_structure_n_fields ((GstStructure *) list) == 0);
758 gst_tag_list_fields_equal (const GValue * value1, const GValue * value2)
762 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL)
765 /* fields not equal: add some tolerance for doubles, otherwise bail out */
766 if (!G_VALUE_HOLDS_DOUBLE (value1) || !G_VALUE_HOLDS_DOUBLE (value2))
769 d1 = g_value_get_double (value1);
770 d2 = g_value_get_double (value2);
772 /* This will only work for 'normal' values and values around 0,
773 * which should be good enough for our purposes here
774 * FIXME: maybe add this to gst_value_compare_double() ? */
775 return (fabs (d1 - d2) < 0.0000001);
779 * gst_tag_list_is_equal:
780 * @list1: a #GstTagList.
781 * @list2: a #GstTagList.
783 * Checks if the two given taglists are equal.
785 * Returns: TRUE if the taglists are equal, otherwise FALSE
790 gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2)
792 const GstStructure *s1, *s2;
793 gint num_fields1, num_fields2, i;
795 g_return_val_if_fail (GST_IS_TAG_LIST (list1), FALSE);
796 g_return_val_if_fail (GST_IS_TAG_LIST (list2), FALSE);
798 /* we don't just use gst_structure_is_equal() here so we can add some
799 * tolerance for doubles, though maybe we should just add that to
800 * gst_value_compare_double() as well? */
801 s1 = (const GstStructure *) list1;
802 s2 = (const GstStructure *) list2;
804 num_fields1 = gst_structure_n_fields (s1);
805 num_fields2 = gst_structure_n_fields (s2);
807 if (num_fields1 != num_fields2)
810 for (i = 0; i < num_fields1; i++) {
811 const GValue *value1, *value2;
812 const gchar *tag_name;
814 tag_name = gst_structure_nth_field_name (s1, i);
815 value1 = gst_structure_get_value (s1, tag_name);
816 value2 = gst_structure_get_value (s2, tag_name);
821 if (!gst_tag_list_fields_equal (value1, value2))
830 * @p: Object that might be a taglist
832 * Checks if the given pointer is a taglist.
834 * Returns: TRUE, if the given pointer is a taglist
837 gst_is_tag_list (gconstpointer p)
839 GstStructure *s = (GstStructure *) p;
841 g_return_val_if_fail (p != NULL, FALSE);
843 return (GST_IS_STRUCTURE (s) && s->name == GST_QUARK (TAGLIST));
849 GstTagMergeMode mode;
854 gst_tag_list_add_value_internal (GstStructure * list, GstTagMergeMode mode,
855 const gchar * tag, const GValue * value, GstTagInfo * info)
857 const GValue *value2;
861 info = gst_tag_lookup (tag);
862 if (G_UNLIKELY (info == NULL)) {
863 g_warning ("unknown tag '%s'", tag);
868 tag_quark = info->name_quark;
871 && (value2 = gst_structure_id_get_value (list, tag_quark)) != NULL) {
872 GValue dest = { 0, };
875 case GST_TAG_MERGE_REPLACE_ALL:
876 case GST_TAG_MERGE_REPLACE:
877 gst_structure_id_set_value (list, tag_quark, value);
879 case GST_TAG_MERGE_PREPEND:
880 gst_value_list_merge (&dest, value, value2);
881 gst_structure_id_set_value (list, tag_quark, &dest);
882 g_value_unset (&dest);
884 case GST_TAG_MERGE_APPEND:
885 gst_value_list_merge (&dest, value2, value);
886 gst_structure_id_set_value (list, tag_quark, &dest);
887 g_value_unset (&dest);
889 case GST_TAG_MERGE_KEEP:
890 case GST_TAG_MERGE_KEEP_ALL:
893 g_assert_not_reached ();
898 case GST_TAG_MERGE_APPEND:
899 case GST_TAG_MERGE_KEEP:
900 if (gst_structure_id_get_value (list, tag_quark) != NULL)
903 case GST_TAG_MERGE_REPLACE_ALL:
904 case GST_TAG_MERGE_REPLACE:
905 case GST_TAG_MERGE_PREPEND:
906 gst_structure_id_set_value (list, tag_quark, value);
908 case GST_TAG_MERGE_KEEP_ALL:
911 g_assert_not_reached ();
918 gst_tag_list_copy_foreach (GQuark tag_quark, const GValue * value,
921 GstTagCopyData *copy = (GstTagCopyData *) user_data;
924 tag = g_quark_to_string (tag_quark);
925 gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value, NULL);
931 * gst_tag_list_insert:
932 * @into: list to merge into
933 * @from: list to merge from
934 * @mode: the mode to use
936 * Inserts the tags of the @from list into the first list using the given mode.
939 gst_tag_list_insert (GstTagList * into, const GstTagList * from,
940 GstTagMergeMode mode)
944 g_return_if_fail (GST_IS_TAG_LIST (into));
945 g_return_if_fail (GST_IS_TAG_LIST (from));
946 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
948 data.list = (GstStructure *) into;
950 if (mode == GST_TAG_MERGE_REPLACE_ALL) {
951 gst_structure_remove_all_fields (data.list);
953 gst_structure_foreach ((GstStructure *) from, gst_tag_list_copy_foreach,
959 * @list: list to copy
961 * Copies a given #GstTagList.
963 * Free-function: gst_tag_list_free
965 * Returns: (transfer full): copy of the given list
968 gst_tag_list_copy (const GstTagList * list)
970 g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
972 return GST_TAG_LIST (gst_structure_copy ((GstStructure *) list));
976 * gst_tag_list_merge:
977 * @list1: first list to merge
978 * @list2: second list to merge
979 * @mode: the mode to use
981 * Merges the two given lists into a new list. If one of the lists is NULL, a
982 * copy of the other is returned. If both lists are NULL, NULL is returned.
984 * Free-function: gst_tag_list_free
986 * Returns: (transfer full): the new list
989 gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2,
990 GstTagMergeMode mode)
992 GstTagList *list1_cp;
993 const GstTagList *list2_cp;
995 g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL);
996 g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL);
997 g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL);
999 /* nothing to merge */
1000 if (!list1 && !list2) {
1004 /* create empty list, we need to do this to correctly handling merge modes */
1005 list1_cp = (list1) ? gst_tag_list_copy (list1) : gst_tag_list_new ();
1006 list2_cp = (list2) ? list2 : gst_tag_list_new ();
1008 gst_tag_list_insert (list1_cp, list2_cp, mode);
1011 gst_tag_list_free ((GstTagList *) list2_cp);
1017 * gst_tag_list_free:
1018 * @list: (in) (transfer full): the list to free
1020 * Frees the given list and all associated values.
1023 gst_tag_list_free (GstTagList * list)
1025 g_return_if_fail (GST_IS_TAG_LIST (list));
1026 gst_structure_free ((GstStructure *) list);
1030 * gst_tag_list_get_tag_size:
1032 * @tag: the tag to query
1034 * Checks how many value are stored in this tag list for the given tag.
1036 * Returns: The number of tags stored
1039 gst_tag_list_get_tag_size (const GstTagList * list, const gchar * tag)
1041 const GValue *value;
1043 g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
1045 value = gst_structure_get_value ((GstStructure *) list, tag);
1048 if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
1051 return gst_value_list_get_size (value);
1056 * @list: list to set tags in
1057 * @mode: the mode to use
1059 * @...: NULL-terminated list of values to set
1061 * Sets the values for the given tags using the specified mode.
1064 gst_tag_list_add (GstTagList * list, GstTagMergeMode mode, const gchar * tag,
1069 g_return_if_fail (GST_IS_TAG_LIST (list));
1070 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1071 g_return_if_fail (tag != NULL);
1073 va_start (args, tag);
1074 gst_tag_list_add_valist (list, mode, tag, args);
1079 * gst_tag_list_add_values:
1080 * @list: list to set tags in
1081 * @mode: the mode to use
1083 * @...: GValues to set
1085 * Sets the GValues for the given tags using the specified mode.
1088 gst_tag_list_add_values (GstTagList * list, GstTagMergeMode mode,
1089 const gchar * tag, ...)
1093 g_return_if_fail (GST_IS_TAG_LIST (list));
1094 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1095 g_return_if_fail (tag != NULL);
1097 va_start (args, tag);
1098 gst_tag_list_add_valist_values (list, mode, tag, args);
1103 * gst_tag_list_add_valist:
1104 * @list: list to set tags in
1105 * @mode: the mode to use
1107 * @var_args: tag / value pairs to set
1109 * Sets the values for the given tags using the specified mode.
1112 gst_tag_list_add_valist (GstTagList * list, GstTagMergeMode mode,
1113 const gchar * tag, va_list var_args)
1116 gchar *error = NULL;
1118 g_return_if_fail (GST_IS_TAG_LIST (list));
1119 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1120 g_return_if_fail (tag != NULL);
1122 if (mode == GST_TAG_MERGE_REPLACE_ALL) {
1123 gst_structure_remove_all_fields (list);
1126 while (tag != NULL) {
1127 GValue value = { 0, };
1129 info = gst_tag_lookup (tag);
1130 if (G_UNLIKELY (info == NULL)) {
1131 g_warning ("unknown tag '%s'", tag);
1134 G_VALUE_COLLECT_INIT (&value, info->type, var_args, 0, &error);
1136 g_warning ("%s: %s", G_STRLOC, error);
1138 /* we purposely leak the value here, it might not be
1139 * in a sane state if an error condition occoured
1143 gst_tag_list_add_value_internal (list, mode, tag, &value, info);
1144 g_value_unset (&value);
1145 tag = va_arg (var_args, gchar *);
1150 * gst_tag_list_add_valist_values:
1151 * @list: list to set tags in
1152 * @mode: the mode to use
1154 * @var_args: tag / GValue pairs to set
1156 * Sets the GValues for the given tags using the specified mode.
1159 gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode,
1160 const gchar * tag, va_list var_args)
1162 g_return_if_fail (GST_IS_TAG_LIST (list));
1163 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1164 g_return_if_fail (tag != NULL);
1166 if (mode == GST_TAG_MERGE_REPLACE_ALL) {
1167 gst_structure_remove_all_fields (list);
1170 while (tag != NULL) {
1173 info = gst_tag_lookup (tag);
1174 if (G_UNLIKELY (info == NULL)) {
1175 g_warning ("unknown tag '%s'", tag);
1178 gst_tag_list_add_value_internal (list, mode, tag, va_arg (var_args,
1180 tag = va_arg (var_args, gchar *);
1185 * gst_tag_list_add_value:
1186 * @list: list to set tags in
1187 * @mode: the mode to use
1189 * @value: GValue for this tag
1191 * Sets the GValue for a given tag using the specified mode.
1196 gst_tag_list_add_value (GstTagList * list, GstTagMergeMode mode,
1197 const gchar * tag, const GValue * value)
1199 g_return_if_fail (GST_IS_TAG_LIST (list));
1200 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1201 g_return_if_fail (tag != NULL);
1203 gst_tag_list_add_value_internal (list, mode, tag, value, NULL);
1207 * gst_tag_list_remove_tag:
1208 * @list: list to remove tag from
1209 * @tag: tag to remove
1211 * Removes the given tag from the taglist.
1214 gst_tag_list_remove_tag (GstTagList * list, const gchar * tag)
1216 g_return_if_fail (GST_IS_TAG_LIST (list));
1217 g_return_if_fail (tag != NULL);
1219 gst_structure_remove_field ((GstStructure *) list, tag);
1224 GstTagForeachFunc func;
1225 const GstTagList *tag_list;
1231 structure_foreach_wrapper (GQuark field_id, const GValue * value,
1234 TagForeachData *data = (TagForeachData *) user_data;
1236 data->func (data->tag_list, g_quark_to_string (field_id), data->data);
1241 * gst_tag_list_foreach:
1242 * @list: list to iterate over
1243 * @func: (scope call): function to be called for each tag
1244 * @user_data: (closure): user specified data
1246 * Calls the given function for each tag inside the tag list. Note that if there
1247 * is no tag, the function won't be called at all.
1250 gst_tag_list_foreach (const GstTagList * list, GstTagForeachFunc func,
1253 TagForeachData data;
1255 g_return_if_fail (GST_IS_TAG_LIST (list));
1256 g_return_if_fail (func != NULL);
1259 data.tag_list = list;
1260 data.data = user_data;
1261 gst_structure_foreach ((GstStructure *) list, structure_foreach_wrapper,
1266 * gst_tag_list_get_value_index:
1267 * @list: a #GstTagList
1268 * @tag: tag to read out
1269 * @index: number of entry to read out
1271 * Gets the value that is at the given index for the given tag in the given
1274 * Returns: (transfer none): The GValue for the specified entry or NULL if the
1275 * tag wasn't available or the tag doesn't have as many entries
1278 gst_tag_list_get_value_index (const GstTagList * list, const gchar * tag,
1281 const GValue *value;
1283 g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
1284 g_return_val_if_fail (tag != NULL, NULL);
1286 value = gst_structure_get_value ((GstStructure *) list, tag);
1290 if (GST_VALUE_HOLDS_LIST (value)) {
1291 if (index >= gst_value_list_get_size (value))
1293 return gst_value_list_get_value (value, index);
1302 * gst_tag_list_copy_value:
1303 * @dest: (out caller-allocates): uninitialized #GValue to copy into
1304 * @list: list to get the tag from
1305 * @tag: tag to read out
1307 * Copies the contents for the given tag into the value,
1308 * merging multiple values into one if multiple values are associated
1310 * You must g_value_unset() the value after use.
1312 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1316 gst_tag_list_copy_value (GValue * dest, const GstTagList * list,
1321 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1322 g_return_val_if_fail (tag != NULL, FALSE);
1323 g_return_val_if_fail (dest != NULL, FALSE);
1324 g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE);
1326 src = gst_structure_get_value ((GstStructure *) list, tag);
1330 if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
1331 GstTagInfo *info = gst_tag_lookup (tag);
1336 /* must be there or lists aren't allowed */
1337 g_assert (info->merge_func);
1338 info->merge_func (dest, src);
1340 g_value_init (dest, G_VALUE_TYPE (src));
1341 g_value_copy (src, dest);
1346 /* FIXME 0.11: this whole merge function business is overdesigned, and the
1347 * _get_foo() API is misleading as well - how many application developers will
1348 * expect gst_tag_list_get_string (list, GST_TAG_ARTIST, &val) might return a
1349 * string with multiple comma-separated artists? _get_foo() should just be
1350 * a convenience wrapper around _get_foo_index (list, tag, 0, &val),
1351 * supplemented by a special _tag_list_get_string_merged() function if needed
1352 * (unless someone can actually think of real use cases where the merge
1353 * function is not 'use first' for non-strings and merge for strings) */
1355 /***** evil macros to get all the gst_tag_list_get_*() functions right *****/
1357 #define TAG_MERGE_FUNCS(name,type,ret) \
1359 gst_tag_list_get_ ## name (const GstTagList *list, const gchar *tag, \
1362 GValue v = { 0, }; \
1364 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); \
1365 g_return_val_if_fail (tag != NULL, FALSE); \
1366 g_return_val_if_fail (value != NULL, FALSE); \
1368 if (!gst_tag_list_copy_value (&v, list, tag)) \
1370 *value = COPY_FUNC (g_value_get_ ## name (&v)); \
1371 g_value_unset (&v); \
1376 gst_tag_list_get_ ## name ## _index (const GstTagList *list, \
1378 guint index, type *value) \
1382 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); \
1383 g_return_val_if_fail (tag != NULL, FALSE); \
1384 g_return_val_if_fail (value != NULL, FALSE); \
1386 if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL) \
1388 *value = COPY_FUNC (g_value_get_ ## name (v)); \
1392 /* FIXME 0.11: maybe get rid of _get_char*(), _get_uchar*(), _get_long*(),
1393 * _get_ulong*() and _get_pointer*()? - they are not really useful/common
1394 * enough to warrant convenience accessor functions */
1396 #define COPY_FUNC /**/
1398 * gst_tag_list_get_char:
1399 * @list: a #GstTagList to get the tag from
1400 * @tag: tag to read out
1401 * @value: (out): location for the result
1403 * Copies the contents for the given tag into the value, merging multiple values
1404 * into one if multiple values are associated with the tag.
1406 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1410 * gst_tag_list_get_char_index:
1411 * @list: a #GstTagList to get the tag from
1412 * @tag: tag to read out
1413 * @index: number of entry to read out
1414 * @value: (out): location for the result
1416 * Gets the value that is at the given index for the given tag in the given
1419 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1422 TAG_MERGE_FUNCS (char, gchar, TRUE);
1424 * gst_tag_list_get_uchar:
1425 * @list: a #GstTagList to get the tag from
1426 * @tag: tag to read out
1427 * @value: (out): location for the result
1429 * Copies the contents for the given tag into the value, merging multiple values
1430 * into one if multiple values are associated with the tag.
1432 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1436 * gst_tag_list_get_uchar_index:
1437 * @list: a #GstTagList to get the tag from
1438 * @tag: tag to read out
1439 * @index: number of entry to read out
1440 * @value: (out): location for the result
1442 * Gets the value that is at the given index for the given tag in the given
1445 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1448 TAG_MERGE_FUNCS (uchar, guchar, TRUE);
1450 * gst_tag_list_get_boolean:
1451 * @list: a #GstTagList to get the tag from
1452 * @tag: tag to read out
1453 * @value: (out): location for the result
1455 * Copies the contents for the given tag into the value, merging multiple values
1456 * into one if multiple values are associated with the tag.
1458 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1462 * gst_tag_list_get_boolean_index:
1463 * @list: a #GstTagList to get the tag from
1464 * @tag: tag to read out
1465 * @index: number of entry to read out
1466 * @value: (out): location for the result
1468 * Gets the value that is at the given index for the given tag in the given
1471 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1474 TAG_MERGE_FUNCS (boolean, gboolean, TRUE);
1476 * gst_tag_list_get_int:
1477 * @list: a #GstTagList to get the tag from
1478 * @tag: tag to read out
1479 * @value: (out): location for the result
1481 * Copies the contents for the given tag into the value, merging multiple values
1482 * into one if multiple values are associated with the tag.
1484 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1488 * gst_tag_list_get_int_index:
1489 * @list: a #GstTagList to get the tag from
1490 * @tag: tag to read out
1491 * @index: number of entry to read out
1492 * @value: (out): location for the result
1494 * Gets the value that is at the given index for the given tag in the given
1497 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1500 TAG_MERGE_FUNCS (int, gint, TRUE);
1502 * gst_tag_list_get_uint:
1503 * @list: a #GstTagList to get the tag from
1504 * @tag: tag to read out
1505 * @value: (out): location for the result
1507 * Copies the contents for the given tag into the value, merging multiple values
1508 * into one if multiple values are associated with the tag.
1510 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1514 * gst_tag_list_get_uint_index:
1515 * @list: a #GstTagList to get the tag from
1516 * @tag: tag to read out
1517 * @index: number of entry to read out
1518 * @value: (out): location for the result
1520 * Gets the value that is at the given index for the given tag in the given
1523 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1526 TAG_MERGE_FUNCS (uint, guint, TRUE);
1528 * gst_tag_list_get_long:
1529 * @list: a #GstTagList to get the tag from
1530 * @tag: tag to read out
1531 * @value: (out): location for the result
1533 * Copies the contents for the given tag into the value, merging multiple values
1534 * into one if multiple values are associated with the tag.
1536 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1540 * gst_tag_list_get_long_index:
1541 * @list: a #GstTagList to get the tag from
1542 * @tag: tag to read out
1543 * @index: number of entry to read out
1544 * @value: (out): location for the result
1546 * Gets the value that is at the given index for the given tag in the given
1549 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1552 TAG_MERGE_FUNCS (long, glong, TRUE);
1554 * gst_tag_list_get_ulong:
1555 * @list: a #GstTagList to get the tag from
1556 * @tag: tag to read out
1557 * @value: (out): location for the result
1559 * Copies the contents for the given tag into the value, merging multiple values
1560 * into one if multiple values are associated with the tag.
1562 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1566 * gst_tag_list_get_ulong_index:
1567 * @list: a #GstTagList to get the tag from
1568 * @tag: tag to read out
1569 * @index: number of entry to read out
1570 * @value: (out): location for the result
1572 * Gets the value that is at the given index for the given tag in the given
1575 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1578 TAG_MERGE_FUNCS (ulong, gulong, TRUE);
1580 * gst_tag_list_get_int64:
1581 * @list: a #GstTagList to get the tag from
1582 * @tag: tag to read out
1583 * @value: (out): location for the result
1585 * Copies the contents for the given tag into the value, merging multiple values
1586 * into one if multiple values are associated with the tag.
1588 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1592 * gst_tag_list_get_int64_index:
1593 * @list: a #GstTagList to get the tag from
1594 * @tag: tag to read out
1595 * @index: number of entry to read out
1596 * @value: (out): location for the result
1598 * Gets the value that is at the given index for the given tag in the given
1601 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1604 TAG_MERGE_FUNCS (int64, gint64, TRUE);
1606 * gst_tag_list_get_uint64:
1607 * @list: a #GstTagList to get the tag from
1608 * @tag: tag to read out
1609 * @value: (out): location for the result
1611 * Copies the contents for the given tag into the value, merging multiple values
1612 * into one if multiple values are associated with the tag.
1614 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1618 * gst_tag_list_get_uint64_index:
1619 * @list: a #GstTagList to get the tag from
1620 * @tag: tag to read out
1621 * @index: number of entry to read out
1622 * @value: (out): location for the result
1624 * Gets the value that is at the given index for the given tag in the given
1627 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1630 TAG_MERGE_FUNCS (uint64, guint64, TRUE);
1632 * gst_tag_list_get_float:
1633 * @list: a #GstTagList to get the tag from
1634 * @tag: tag to read out
1635 * @value: (out): location for the result
1637 * Copies the contents for the given tag into the value, merging multiple values
1638 * into one if multiple values are associated with the tag.
1640 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1644 * gst_tag_list_get_float_index:
1645 * @list: a #GstTagList to get the tag from
1646 * @tag: tag to read out
1647 * @index: number of entry to read out
1648 * @value: (out): location for the result
1650 * Gets the value that is at the given index for the given tag in the given
1653 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1656 TAG_MERGE_FUNCS (float, gfloat, TRUE);
1658 * gst_tag_list_get_double:
1659 * @list: a #GstTagList to get the tag from
1660 * @tag: tag to read out
1661 * @value: (out): location for the result
1663 * Copies the contents for the given tag into the value, merging multiple values
1664 * into one if multiple values are associated with the tag.
1666 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1670 * gst_tag_list_get_double_index:
1671 * @list: a #GstTagList to get the tag from
1672 * @tag: tag to read out
1673 * @index: number of entry to read out
1674 * @value: (out): location for the result
1676 * Gets the value that is at the given index for the given tag in the given
1679 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1682 TAG_MERGE_FUNCS (double, gdouble, TRUE);
1684 * gst_tag_list_get_pointer:
1685 * @list: a #GstTagList to get the tag from
1686 * @tag: tag to read out
1687 * @value: (out) (transfer none): location for the result
1689 * Copies the contents for the given tag into the value, merging multiple values
1690 * into one if multiple values are associated with the tag.
1692 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1696 * gst_tag_list_get_pointer_index:
1697 * @list: a #GstTagList to get the tag from
1698 * @tag: tag to read out
1699 * @index: number of entry to read out
1700 * @value: (out) (transfer none): location for the result
1702 * Gets the value that is at the given index for the given tag in the given
1705 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1708 TAG_MERGE_FUNCS (pointer, gpointer, (*value != NULL));
1710 static inline gchar *
1711 _gst_strdup0 (const gchar * s)
1713 if (s == NULL || *s == '\0')
1716 return g_strdup (s);
1720 #define COPY_FUNC _gst_strdup0
1723 * gst_tag_list_get_string:
1724 * @list: a #GstTagList to get the tag from
1725 * @tag: tag to read out
1726 * @value: (out callee-allocates) (transfer full): location for the result
1728 * Copies the contents for the given tag into the value, possibly merging
1729 * multiple values into one if multiple values are associated with the tag.
1731 * Use gst_tag_list_get_string_index (list, tag, 0, value) if you want
1732 * to retrieve the first string associated with this tag unmodified.
1734 * The resulting string in @value will be in UTF-8 encoding and should be
1735 * freed by the caller using g_free when no longer needed. Since 0.10.24 the
1736 * returned string is also guaranteed to be non-NULL and non-empty.
1738 * Free-function: g_free
1740 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1744 * gst_tag_list_get_string_index:
1745 * @list: a #GstTagList to get the tag from
1746 * @tag: tag to read out
1747 * @index: number of entry to read out
1748 * @value: (out callee-allocates) (transfer full): location for the result
1750 * Gets the value that is at the given index for the given tag in the given
1753 * The resulting string in @value will be in UTF-8 encoding and should be
1754 * freed by the caller using g_free when no longer needed. Since 0.10.24 the
1755 * returned string is also guaranteed to be non-NULL and non-empty.
1757 * Free-function: g_free
1759 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1762 TAG_MERGE_FUNCS (string, gchar *, (*value != NULL));
1765 *FIXME 0.11: Instead of _peek (non-copy) and _get (copy), we could have
1766 * _get (non-copy) and _dup (copy) for strings, seems more
1770 * gst_tag_list_peek_string_index:
1771 * @list: a #GstTagList to get the tag from
1772 * @tag: tag to read out
1773 * @index: number of entry to read out
1774 * @value: (out) (transfer none): location for the result
1776 * Peeks at the value that is at the given index for the given tag in the given
1779 * The resulting string in @value will be in UTF-8 encoding and doesn't need
1780 * to be freed by the caller. The returned string is also guaranteed to
1781 * be non-NULL and non-empty.
1783 * Returns: TRUE, if a value was set, FALSE if the tag didn't exist in the
1787 gst_tag_list_peek_string_index (const GstTagList * list,
1788 const gchar * tag, guint index, const gchar ** value)
1792 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1793 g_return_val_if_fail (tag != NULL, FALSE);
1794 g_return_val_if_fail (value != NULL, FALSE);
1796 if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1798 *value = g_value_get_string (v);
1799 return *value != NULL && **value != '\0';
1803 * gst_tag_list_get_date:
1804 * @list: a #GstTagList to get the tag from
1805 * @tag: tag to read out
1806 * @value: (out callee-allocates) (transfer full): address of a GDate pointer
1807 * variable to store the result into
1809 * Copies the first date for the given tag in the taglist into the variable
1810 * pointed to by @value. Free the date with g_date_free() when it is no longer
1813 * Free-function: g_date_free
1815 * Returns: TRUE, if a date was copied, FALSE if the tag didn't exist in the
1816 * given list or if it was #NULL.
1819 gst_tag_list_get_date (const GstTagList * list, const gchar * tag,
1824 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1825 g_return_val_if_fail (tag != NULL, FALSE);
1826 g_return_val_if_fail (value != NULL, FALSE);
1828 if (!gst_tag_list_copy_value (&v, list, tag))
1830 *value = (GDate *) g_value_dup_boxed (&v);
1832 return (*value != NULL);
1836 * gst_tag_list_get_date_index:
1837 * @list: a #GstTagList to get the tag from
1838 * @tag: tag to read out
1839 * @index: number of entry to read out
1840 * @value: (out callee-allocates) (transfer full): location for the result
1842 * Gets the date that is at the given index for the given tag in the given
1843 * list and copies it into the variable pointed to by @value. Free the date
1844 * with g_date_free() when it is no longer needed.
1846 * Free-function: g_date_free
1848 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1849 * given list or if it was #NULL.
1852 gst_tag_list_get_date_index (const GstTagList * list,
1853 const gchar * tag, guint index, GDate ** value)
1857 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1858 g_return_val_if_fail (tag != NULL, FALSE);
1859 g_return_val_if_fail (value != NULL, FALSE);
1861 if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1863 *value = (GDate *) g_value_dup_boxed (v);
1864 return (*value != NULL);
1868 * gst_tag_list_get_date_time:
1869 * @list: a #GstTagList to get the tag from
1870 * @tag: tag to read out
1871 * @value: (out callee-allocates) (transfer full): address of a #GstDateTime
1872 * pointer variable to store the result into
1874 * Copies the first datetime for the given tag in the taglist into the variable
1875 * pointed to by @value. Unref the date with gst_date_time_unref() when
1876 * it is no longer needed.
1878 * Free-function: gst_date_time_unref
1880 * Returns: TRUE, if a datetime was copied, FALSE if the tag didn't exist in
1881 * thegiven list or if it was #NULL.
1886 gst_tag_list_get_date_time (const GstTagList * list, const gchar * tag,
1887 GstDateTime ** value)
1891 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1892 g_return_val_if_fail (tag != NULL, FALSE);
1893 g_return_val_if_fail (value != NULL, FALSE);
1895 if (!gst_tag_list_copy_value (&v, list, tag))
1898 g_return_val_if_fail (GST_VALUE_HOLDS_DATE_TIME (&v), FALSE);
1900 *value = (GstDateTime *) g_value_dup_boxed (&v);
1902 return (*value != NULL);
1906 * gst_tag_list_get_date_time_index:
1907 * @list: a #GstTagList to get the tag from
1908 * @tag: tag to read out
1909 * @index: number of entry to read out
1910 * @value: (out callee-allocates) (transfer full): location for the result
1912 * Gets the datetime that is at the given index for the given tag in the given
1913 * list and copies it into the variable pointed to by @value. Unref the datetime
1914 * with gst_date_time_unref() when it is no longer needed.
1916 * Free-function: gst_date_time_unref
1918 * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
1919 * given list or if it was #NULL.
1924 gst_tag_list_get_date_time_index (const GstTagList * list,
1925 const gchar * tag, guint index, GstDateTime ** value)
1929 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1930 g_return_val_if_fail (tag != NULL, FALSE);
1931 g_return_val_if_fail (value != NULL, FALSE);
1933 if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
1935 *value = (GstDateTime *) g_value_dup_boxed (v);
1936 return (*value != NULL);
1940 * gst_tag_list_get_buffer:
1941 * @list: a #GstTagList to get the tag from
1942 * @tag: tag to read out
1943 * @value: (out callee-allocates) (transfer full): address of a GstBuffer
1944 * pointer variable to store the result into
1946 * Copies the first buffer for the given tag in the taglist into the variable
1947 * pointed to by @value. Free the buffer with gst_buffer_unref() when it is
1950 * Free-function: gst_buffer_unref
1952 * Returns: TRUE, if a buffer was copied, FALSE if the tag didn't exist in the
1953 * given list or if it was #NULL.
1958 gst_tag_list_get_buffer (const GstTagList * list, const gchar * tag,
1963 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
1964 g_return_val_if_fail (tag != NULL, FALSE);
1965 g_return_val_if_fail (value != NULL, FALSE);
1967 if (!gst_tag_list_copy_value (&v, list, tag))
1969 *value = g_value_dup_boxed (&v);
1971 return (*value != NULL);
1975 * gst_tag_list_get_buffer_index:
1976 * @list: a #GstTagList to get the tag from
1977 * @tag: tag to read out
1978 * @index: number of entry to read out
1979 * @value: (out callee-allocates) (transfer full): address of a GstBuffer
1980 * pointer variable to store the result into
1982 * Gets the buffer that is at the given index for the given tag in the given
1983 * list and copies it into the variable pointed to by @value. Free the buffer
1984 * with gst_buffer_unref() when it is no longer needed.
1986 * Free-function: gst_buffer_unref
1988 * Returns: TRUE, if a buffer was copied, FALSE if the tag didn't exist in the
1989 * given list or if it was #NULL.
1994 gst_tag_list_get_buffer_index (const GstTagList * list,
1995 const gchar * tag, guint index, GstBuffer ** value)
1999 g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
2000 g_return_val_if_fail (tag != NULL, FALSE);
2001 g_return_val_if_fail (value != NULL, FALSE);
2003 if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
2005 *value = g_value_dup_boxed (v);
2006 return (*value != NULL);