docs/random/mimetypes: update docs for audio/x-raw-float. Add "buffer-frames=0 means...
[platform/upstream/gstreamer.git] / gst / gsttag.c
1 /* GStreamer
2  * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
3  *
4  * gsttag.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 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include "gst_private.h"
27 #include "gst-i18n-lib.h"
28 #include "gsttag.h"
29 #include "gstinfo.h"
30 #include "gstvalue.h"
31
32 #include <gobject/gvaluecollector.h>
33 #include <string.h>
34
35 #define GST_TAG_IS_VALID(tag)           (gst_tag_get_info (tag) != NULL)
36
37 typedef struct {
38   GType                 type;           /* type the data is in */
39
40   gchar *               nick;           /* translated name */
41   gchar *               blurb;          /* translated description of type */
42
43   GstTagMergeFunc       merge_func;     /* functions to merge the values */
44   GstTagFlag            flag;           /* type of tag */
45 } GstTagInfo;
46
47 #define TAGLIST "taglist"
48 static GQuark gst_tag_list_quark;
49 static GMutex *__tag_mutex;
50 static GHashTable *__tags;
51 #define TAG_LOCK g_mutex_lock (__tag_mutex)
52 #define TAG_UNLOCK g_mutex_unlock (__tag_mutex)
53
54 void
55 _gst_tag_initialize (void)
56 {
57   gst_tag_list_quark = g_quark_from_static_string (TAGLIST);
58   __tag_mutex = g_mutex_new ();
59   __tags = g_hash_table_new (g_direct_hash, g_direct_equal);
60   gst_tag_register (GST_TAG_TITLE, GST_TAG_FLAG_META,
61                     G_TYPE_STRING,
62                     _("title"),
63                     _("commonly used title"),
64                     gst_tag_merge_strings_with_comma);
65   gst_tag_register (GST_TAG_ARTIST, GST_TAG_FLAG_META,
66                     G_TYPE_STRING,
67                     _("artist"),
68                     _("person(s) responsible for the recording"),
69                     gst_tag_merge_strings_with_comma);
70   gst_tag_register (GST_TAG_ALBUM, GST_TAG_FLAG_META,
71                     G_TYPE_STRING,
72                     _("album"),
73                     _("album containing this data"),
74                     gst_tag_merge_strings_with_comma);
75   gst_tag_register (GST_TAG_DATE, GST_TAG_FLAG_META,
76                     G_TYPE_UINT, /* FIXME: own data type for dates? */
77                     _("date"),
78                     _("date the data was created (in Julian calendar days)"),
79                     NULL);
80   gst_tag_register (GST_TAG_GENRE, GST_TAG_FLAG_META,
81                     G_TYPE_STRING,
82                     _("genre"), 
83                     _("genre this data belongs to"),
84                     gst_tag_merge_strings_with_comma);
85   gst_tag_register (GST_TAG_COMMENT, GST_TAG_FLAG_META,
86                     G_TYPE_STRING,
87                     _("comment"),
88                     _("free text commenting the data"),
89                     gst_tag_merge_strings_with_comma);
90   gst_tag_register (GST_TAG_TRACK_NUMBER, GST_TAG_FLAG_META,
91                     G_TYPE_UINT,
92                     _("track number"),
93                     _("track number inside a collection"),
94                     gst_tag_merge_use_first);
95   gst_tag_register (GST_TAG_TRACK_COUNT, GST_TAG_FLAG_META,
96                     G_TYPE_UINT,
97                     _("track count"),
98                     _("count of tracks inside collection this track belongs to"), 
99                     gst_tag_merge_use_first);
100   gst_tag_register (GST_TAG_LOCATION, GST_TAG_FLAG_META,
101                     G_TYPE_STRING,
102                     _("location"),
103                     _("original location of file as a URI"),
104                     gst_tag_merge_strings_with_comma);
105   gst_tag_register (GST_TAG_DESCRIPTION, GST_TAG_FLAG_META,
106                     G_TYPE_STRING,
107                     _("description"),
108                     _("short text describing the content of the data"),
109                     gst_tag_merge_strings_with_comma);
110   gst_tag_register (GST_TAG_VERSION, GST_TAG_FLAG_META,
111                     G_TYPE_STRING,
112                     _("version"),
113                     _("version of this data"),
114                     NULL);
115   gst_tag_register (GST_TAG_ISRC, GST_TAG_FLAG_META,
116                     G_TYPE_STRING,
117                     _("ISRC"),
118                     _("International Standard Recording Code - see http://www.ifpi.org/isrc/"),
119                     NULL);
120   gst_tag_register (GST_TAG_ORGANIZATION, GST_TAG_FLAG_META,
121                     G_TYPE_STRING,
122                     _("organization"),
123                     _("organization"), /* FIXME */
124                     gst_tag_merge_strings_with_comma);
125   gst_tag_register (GST_TAG_COPYRIGHT, GST_TAG_FLAG_META,
126                     G_TYPE_STRING,
127                     _("copyright"),
128                     _("copyright notice of the data"),
129                     NULL);
130   gst_tag_register (GST_TAG_CONTACT, GST_TAG_FLAG_META,
131                     G_TYPE_STRING,
132                     _("contact"),
133                     _("contact information"),
134                     gst_tag_merge_strings_with_comma);
135   gst_tag_register (GST_TAG_LICENSE,     GST_TAG_FLAG_META,
136                     G_TYPE_STRING,
137                     _("license"),
138                     _("license of data"),
139                     NULL);
140   gst_tag_register (GST_TAG_PERFORMER, GST_TAG_FLAG_META,
141                     G_TYPE_STRING,
142                     _("performer"),
143                     _("person(s) performing"),
144                     gst_tag_merge_strings_with_comma);
145   gst_tag_register (GST_TAG_APPLICATION, GST_TAG_FLAG_META,
146                     G_TYPE_STRING,
147                     _("application"),
148                     _("application that wrote the stream"),
149                     gst_tag_merge_strings_with_comma);
150   gst_tag_register (GST_TAG_DURATION, GST_TAG_FLAG_DECODED,
151                     G_TYPE_UINT64,
152                     _("duration"),
153                     _("length in GStreamer time units (nanoseconds)"),
154                     NULL);
155   gst_tag_register (GST_TAG_CODEC, GST_TAG_FLAG_ENCODED,
156                     G_TYPE_STRING,
157                     _("codec"),
158                     _("codec the data is stored in"),
159                     gst_tag_merge_strings_with_comma);
160   gst_tag_register (GST_TAG_BITRATE, GST_TAG_FLAG_ENCODED,
161                     G_TYPE_UINT,
162                     _("bitrate"),
163                     _("exact or average bitrate in bits/s"),
164                     NULL);
165   gst_tag_register (GST_TAG_NOMINAL_BITRATE, GST_TAG_FLAG_ENCODED,
166                     G_TYPE_UINT,
167                     _("nominal bitrate"),
168                     _("nominal bitrate in bits/s"),
169                     NULL);
170   gst_tag_register (GST_TAG_MINIMUM_BITRATE, GST_TAG_FLAG_ENCODED,
171                     G_TYPE_UINT,
172                     _("minimum bitrate"),
173                     _("minimum bitrate in bits/s"),
174                     NULL);
175   gst_tag_register (GST_TAG_MAXIMUM_BITRATE, GST_TAG_FLAG_ENCODED,
176                     G_TYPE_UINT,
177                     _("maximum bitrate"),
178                     _("maximum bitrate in bits/s"),
179                     NULL);
180   gst_tag_register (GST_TAG_ENCODER_VERSION, GST_TAG_FLAG_ENCODED,
181                     G_TYPE_UINT,
182                     _("encoder version"),
183                     _("version of the encoder used to encode this stream"),
184                     NULL);
185   gst_tag_register (GST_TAG_SERIAL, GST_TAG_FLAG_ENCODED,
186                     G_TYPE_UINT,
187                     _("serial"),
188                     _("serial number of track"),
189                     NULL);
190   gst_tag_register (GST_TAG_TRACK_GAIN, GST_TAG_FLAG_META,
191                     G_TYPE_DOUBLE,
192                     _("replaygain track gain"),
193                     _("track gain in db"),
194                     NULL);
195   gst_tag_register (GST_TAG_TRACK_PEAK, GST_TAG_FLAG_META,
196                     G_TYPE_DOUBLE,
197                     _("replaygain track peak"),
198                     _("peak of the track"),
199                     NULL);
200   gst_tag_register (GST_TAG_ALBUM_GAIN, GST_TAG_FLAG_META,
201                     G_TYPE_DOUBLE,
202                     _("replaygain album gain"),
203                     _("album gain in db"),
204                     NULL);
205   gst_tag_register (GST_TAG_ALBUM_PEAK, GST_TAG_FLAG_META,
206                     G_TYPE_DOUBLE,
207                     _("replaygain album peak"),
208                     _("peak of the album"),
209                     NULL);
210 }
211 /**
212  * gst_tag_merge_use_first:
213  * @dest: uninitialized GValue to store result in
214  * @src: GValue to copy from
215  *
216  * This is a convenience function for the func argument of gst_tag_register(). 
217  * It creates a copy of the first value from the list.
218  */
219 void
220 gst_tag_merge_use_first (GValue *dest, const GValue *src)
221 {
222   const GValue *ret = gst_value_list_get_value (src, 0);
223
224   g_value_init (dest, G_VALUE_TYPE (ret));
225   g_value_copy (ret, dest);
226 }
227 /**
228  * gst_tag_merge_strings_with_comma:
229  * @dest: uninitialized GValue to store result in
230  * @src: GValue to copy from
231  * 
232  * This is a convenience function for the func argument of gst_tag_register().
233  * It concatenates all given strings using a comma. The tag must be registered
234  * as a G_TYPE_STRING or this function will fail.
235  */
236 void
237 gst_tag_merge_strings_with_comma (GValue *dest, const GValue *src)
238 {
239   GString *str;
240   gint i, count;
241
242   count = gst_value_list_get_size (src);
243   str = g_string_new (g_value_get_string (gst_value_list_get_value (src, 0)));
244   for (i = 1; i < count; i++) {
245     /* seperator between two string */
246     str = g_string_append (str, _(", "));
247     str = g_string_append (str, g_value_get_string (gst_value_list_get_value (src, 1)));
248   }
249
250   g_value_init (dest, G_TYPE_STRING);
251   g_value_set_string_take_ownership (dest, str->str);
252   g_string_free (str, FALSE);
253 }
254 static GstTagInfo *
255 gst_tag_lookup (GQuark entry)
256 {
257   GstTagInfo *ret;
258   
259   TAG_LOCK;
260   ret = g_hash_table_lookup (__tags, GUINT_TO_POINTER (entry));
261   TAG_UNLOCK;
262
263   return ret;
264 }
265 /**
266  * gst_tag_register:
267  * @name: the name or identifier string
268  * @flag: a flag describing the type of tag info
269  * @type: the type this data is in
270  * @nick: human-readable name
271  * @blurb: a human-readable description about this tag
272  * @func: function for merging multiple values of this tag
273  *
274  * Registers a new tag type for the use with GStreamer's type system. If a type
275  * with that name is already registered, that one is used.
276  * The old registration may have used a different type however. So don't rely
277  * on your supplied values.
278  * This function takes ownership of all supplied variables.
279  */
280 void
281 gst_tag_register (gchar *name, GstTagFlag flag, GType type,
282                   gchar *nick, gchar *blurb, GstTagMergeFunc func)
283 {
284   GQuark key;
285   GstTagInfo *info;
286
287   g_return_if_fail (name != NULL);
288   g_return_if_fail (nick != NULL);
289   g_return_if_fail (blurb != NULL);
290   g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
291   
292   key = g_quark_from_string (name);
293   info = gst_tag_lookup (key);
294   g_return_if_fail (info == NULL);
295   
296   info = g_new (GstTagInfo, 1);
297   info->flag = flag;
298   info->type = type;
299   info->nick = nick;
300   info->blurb = blurb;
301   info->merge_func = func;
302     
303   TAG_LOCK;
304   g_hash_table_insert (__tags, GUINT_TO_POINTER (key), info);
305   TAG_UNLOCK;
306 }
307 /**
308  * gst_tag_exists:
309  * @tag: name of the tag
310  *
311  * Checks if the given type is already registered.
312  *
313  * Returns: TRUE if the type is already registered
314  */
315 gboolean
316 gst_tag_exists (const gchar *tag)
317 {
318   g_return_val_if_fail (tag != NULL, FALSE);
319   
320   return gst_tag_lookup (g_quark_from_string (tag)) != NULL;
321 }
322 /**
323  * gst_tag_get_type:
324  * @tag: the tag
325  *
326  * Gets the #GType used for this tag.
327  *
328  * Returns: the #GType of this tag
329  */
330 GType
331 gst_tag_get_type (const gchar *tag)
332 {
333   GstTagInfo *info;
334   
335   g_return_val_if_fail (tag != NULL, 0);
336   info = gst_tag_lookup (g_quark_from_string (tag));
337   g_return_val_if_fail (info != NULL, 0);
338   
339   return info->type;
340 }
341 /**
342  * gst_tag_get_nick
343  * @tag: the tag
344  *
345  * Returns the human-readable name of this tag, You must not change or free 
346  * this string.
347  *
348  * Returns: the human-readable name of this tag
349  */
350 const gchar *
351 gst_tag_get_nick (const gchar *tag)
352 {
353   GstTagInfo *info;
354   
355   g_return_val_if_fail (tag != NULL, NULL);
356   info = gst_tag_lookup (g_quark_from_string (tag));
357   g_return_val_if_fail (info != NULL, NULL);
358   
359   return info->nick;
360 }
361 /**
362  * gst_tag_get_description:
363  * @tag: the tag
364  *
365  * Returns the human-readable description of this tag, You must not change or 
366  * free this string.
367  *
368  * Return the human-readable description of this tag
369  */
370 const gchar *
371 gst_tag_get_description (const gchar *tag)
372 {
373   GstTagInfo *info;
374   
375   g_return_val_if_fail (tag != NULL, NULL);
376   info = gst_tag_lookup (g_quark_from_string (tag));
377   g_return_val_if_fail (info != NULL, NULL);
378   
379   return info->blurb;
380 }
381 /**
382  * gst_tag_list_is_fixed:
383  * @tag: tag to check
384  *
385  * Checks if the given tag is fixed. A fixed tag can only contain one value.
386  * Unfixed tags can contain lists of values.
387  *
388  * Returns: TRUE, if the given tag is fixed.
389  */
390 gboolean
391 gst_tag_is_fixed (const gchar *tag)
392 {
393   GstTagInfo *info;
394   
395   g_return_val_if_fail (tag != NULL, FALSE);
396   info = gst_tag_lookup (g_quark_from_string (tag));
397   g_return_val_if_fail (info != NULL, FALSE);
398   
399   return info->merge_func == NULL;
400 }
401 /**
402  * gst_tag_list_new:
403  *
404  * Creates a new empty GstTagList.
405  *
406  * Returns: An empty tag list
407  */
408 GstTagList *
409 gst_tag_list_new (void)
410 {
411   return GST_TAG_LIST (gst_structure_new (TAGLIST, NULL));
412 }
413 /**
414  * gst_is_tag_list:
415  * @p: Object that might be a taglist
416  *
417  * Checks if the given pointer is a taglist.
418  *
419  * Returns: TRUE, if the given pointer is a taglist
420  */
421 gboolean
422 gst_is_tag_list (gconstpointer p)
423 {
424   g_return_val_if_fail (p != NULL, FALSE); 
425
426   return ((GstStructure *) p)->name == gst_tag_list_quark;
427 }
428 typedef struct {
429   GstStructure *        list;
430   GstTagMergeMode       mode;
431 } GstTagCopyData;
432 static void
433 gst_tag_list_add_value_internal (GstStructure *list, GstTagMergeMode mode, GQuark tag, GValue *value)
434 {
435   GstTagInfo *info = gst_tag_lookup (tag);
436   const GValue *value2;
437   
438   g_assert (info != NULL);
439
440   if (info->merge_func && (value2 = gst_structure_id_get_value (list, tag)) != NULL) {
441     GValue dest = { 0, };
442     switch (mode) {
443       case GST_TAG_MERGE_REPLACE_ALL:
444       case GST_TAG_MERGE_REPLACE:
445         gst_structure_id_set_value (list, tag, value);
446         break;
447       case GST_TAG_MERGE_PREPEND:
448         gst_value_list_concat (&dest, value, value2);
449         gst_structure_id_set_value (list, tag, &dest);
450         g_value_unset (&dest);
451         break;
452       case GST_TAG_MERGE_APPEND:
453         gst_value_list_concat (&dest, value2, value);
454         gst_structure_id_set_value (list, tag, &dest);
455         g_value_unset (&dest);
456         break;
457       case GST_TAG_MERGE_KEEP:
458       case GST_TAG_MERGE_KEEP_ALL:
459         break;
460       default:
461         g_assert_not_reached ();
462         break;
463     }
464   } else {
465     switch (mode) {
466       case GST_TAG_MERGE_APPEND:
467       case GST_TAG_MERGE_KEEP:
468         if (gst_structure_id_get_value (list, tag) != NULL)
469           break;
470         /* fall through */
471       case GST_TAG_MERGE_REPLACE_ALL:
472       case GST_TAG_MERGE_REPLACE:
473       case GST_TAG_MERGE_PREPEND:
474         gst_structure_id_set_value (list, tag, value);
475         break;
476       case GST_TAG_MERGE_KEEP_ALL:
477         break;
478       default:
479         g_assert_not_reached ();
480         break;
481     }
482   }
483 }
484 static gboolean
485 gst_tag_list_copy_foreach (GQuark tag, GValue *value, gpointer user_data)
486 {
487   GstTagCopyData *copy = (GstTagCopyData *) user_data;
488
489   gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value);
490
491   return TRUE;
492 }
493 /**
494  * gst_tag_list_insert:
495  * @into: list to merge into
496  * @from: list to merge from
497  * @mode: the mode to use
498  * 
499  * Inserts the tags of the second list into the first list using the given mode.
500  */
501 void
502 gst_tag_list_insert (GstTagList *into, const GstTagList *from, GstTagMergeMode mode)
503 {
504   GstTagCopyData data;
505   
506   g_return_if_fail (GST_IS_TAG_LIST (into));
507   g_return_if_fail (GST_IS_TAG_LIST (from));
508   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
509
510   data.list = (GstStructure *) into;
511   data.mode = mode;
512   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
513     gst_structure_remove_all_fields (data.list);
514   }
515   gst_structure_foreach ((GstStructure *) from, gst_tag_list_copy_foreach, &data);
516 }
517 /**
518  * gst_tag_list_copy:
519  * @list: list to copy
520  *
521  * Copies a given #GstTagList.
522  *
523  * Returns: copy of the given list
524  */
525 GstTagList *
526 gst_tag_list_copy (const GstTagList *list)
527 {
528   g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
529   
530   return GST_TAG_LIST (gst_structure_copy ((GstStructure *) list));
531 }
532 /**
533  * gst_tag_list_merge:
534  * @list1: first list to merge
535  * @list2: second list to merge
536  * @mode: the mode to use
537  * 
538  * Merges the two given lists into a new list. If one of the lists is NULL, a
539  * copy of the other is returned. If both lists are NULL, NULL is returned.
540  *
541  * Returns: the new list
542  */
543 GstTagList *
544 gst_tag_list_merge (const GstTagList *list1, const GstTagList *list2, GstTagMergeMode mode)
545 {
546   g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL);
547   g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL);
548   g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL);
549
550   if (!list1 && !list2) {
551     return NULL;
552   } else if (!list1) {
553     return gst_tag_list_copy (list2);
554   } else if (!list2) {
555     return gst_tag_list_copy (list1);
556   } else {
557     GstTagList *ret;
558
559     ret = gst_tag_list_copy (list1);
560     gst_tag_list_insert (ret, list2, mode);
561     return ret;
562   }
563 }
564 /**
565  * gst_tag_list_free:
566  * @list: the list to free
567  *
568  * Frees the given list and all associated values.
569  */
570 void
571 gst_tag_list_free (GstTagList *list)
572 {
573   g_return_if_fail (GST_IS_TAG_LIST (list));
574   gst_structure_free ((GstStructure *) list);
575 }
576 /**
577  * gst_tag_list_get_tag_size:
578  * @list: a taglist
579  * @tag: the tag to query
580  *
581  * Checks how many value are stored in this tag list for the given tag.
582  *
583  * Returns: The number of tags stored
584  */
585 guint
586 gst_tag_list_get_tag_size (const GstTagList *list, const gchar *tag)
587 {
588   const GValue *value;
589
590   g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
591
592   value = gst_structure_get_value ((GstStructure *) list, tag);
593   if (value == NULL)
594     return 0;
595   if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
596     return 1;
597
598   return gst_value_list_get_size (value);
599 }
600 /**
601  * gst_tag_list_add:
602  * @list: list to set tags in
603  * @mode: the mode to use
604  * @tag: tag
605  * @...: NULL-terminated list of values to set
606  *
607  * Sets the values for the given tags using the specified mode.
608  */
609 void
610 gst_tag_list_add (GstTagList *list, GstTagMergeMode mode, const gchar *tag, ...)
611 {
612   va_list args;
613
614   g_return_if_fail (GST_IS_TAG_LIST (list));
615   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
616   g_return_if_fail (tag != NULL);
617   
618   va_start (args, tag);
619   gst_tag_list_add_valist (list, mode, tag, args);
620   va_end (args);
621 }
622 /**
623  * gst_tag_list_add_values:
624  * @list: list to set tags in
625  * @mode: the mode to use
626  * @tag: tag
627  * @...: GValues to set
628  *
629  * Sets the GValues for the given tags using the specified mode.
630  */
631 void
632 gst_tag_list_add_values (GstTagList *list, GstTagMergeMode mode, const gchar *tag, ...)
633 {
634   va_list args;
635
636   g_return_if_fail (GST_IS_TAG_LIST (list));
637   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
638   g_return_if_fail (tag != NULL);
639   
640   va_start (args, tag);
641   gst_tag_list_add_valist_values (list, mode, tag, args);
642   va_end (args);
643 }
644 /**
645  * gst_tag_list_add_valist:
646  * @list: list to set tags in
647  * @mode: the mode to use
648  * @tag: tag
649  * @var_args: tag / value pairs to set
650  *
651  * Sets the values for the given tags using the specified mode.
652  */
653 void
654 gst_tag_list_add_valist (GstTagList *list, GstTagMergeMode mode, const gchar *tag, va_list var_args)
655 {
656   GstTagInfo *info;
657   GQuark quark;
658   gchar *error = NULL;
659   
660   g_return_if_fail (GST_IS_TAG_LIST (list));
661   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
662   g_return_if_fail (tag != NULL);
663   
664   while (tag != NULL) {
665     GValue value = { 0, };
666     quark = g_quark_from_string (tag);
667     info = gst_tag_lookup (quark);
668     if (info == NULL)
669       g_warning ("no GstTag for %s", tag);
670     g_return_if_fail (info != NULL);
671     g_value_init (&value, info->type);
672     G_VALUE_COLLECT (&value, var_args, 0, &error);
673     if (error) {
674       g_warning ("%s: %s", G_STRLOC, error);
675       g_free (error);
676       /* we purposely leak the value here, it might not be
677        * in a sane state if an error condition occoured
678        */
679       return;
680     }
681     gst_tag_list_add_value_internal (list, mode, quark, &value);
682     g_value_unset (&value);
683     tag = va_arg (var_args, gchar *);
684   }
685 }
686 /**
687  * gst_tag_list_add_valist_values:
688  * @list: list to set tags in
689  * @mode: the mode to use
690  * @tag: tag
691  * @var_args: tag / GValue pairs to set
692  *
693  * Sets the GValues for the given tags using the specified mode.
694  */
695 void
696 gst_tag_list_add_valist_values (GstTagList *list, GstTagMergeMode mode, const gchar *tag, va_list var_args)
697 {
698   GstTagInfo *info;
699   GQuark quark;
700   
701   g_return_if_fail (GST_IS_TAG_LIST (list));
702   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
703   g_return_if_fail (tag != NULL);
704   
705   while (tag != NULL) {
706     quark = g_quark_from_string (tag);
707     info = gst_tag_lookup (quark);
708     g_return_if_fail (info != NULL);
709     gst_tag_list_add_value_internal (list, mode, quark, va_arg (var_args, GValue *));
710     tag = va_arg (var_args, gchar *);
711   }
712 }
713 /**
714  * gst_tag_list_remove_tag:
715  * @list: list to remove tag from
716  * @tag: tag to remove
717  *
718  * Removes the goven tag from the taglist.
719  */
720 void
721 gst_tag_list_remove_tag (GstTagList *list, const gchar *tag)
722 {
723   g_return_if_fail (GST_IS_TAG_LIST (list));
724   g_return_if_fail (tag != NULL);
725
726   gst_structure_remove_field ((GstStructure *) list, tag);
727 }
728 typedef struct {
729   GstTagForeachFunc     func;
730   GstTagList *          tag_list;
731   gpointer              data;
732 } TagForeachData;
733 static int
734 structure_foreach_wrapper (GQuark field_id, 
735         GValue *value, gpointer user_data)
736 {
737   TagForeachData *data = (TagForeachData *) user_data;
738   data->func (data->tag_list, g_quark_to_string (field_id), data->data);
739   return TRUE;
740 }
741 /**
742  * gst_tag_list_foreach:
743  * @list: list to iterate over
744  * @func: function to be called for each tag
745  * @user_data: user specified data
746  *
747  * Calls the given function for each tag inside the tag list. Note that if there
748  * is no tag, the function won't be called at all.
749  */
750 void
751 gst_tag_list_foreach (GstTagList *list, GstTagForeachFunc func, gpointer user_data)
752 {
753   TagForeachData data;
754
755   g_return_if_fail (GST_IS_TAG_LIST (list));
756   g_return_if_fail (func != NULL);
757   
758   data.func = func;
759   data.tag_list = list;
760   data.data = user_data;
761   gst_structure_foreach ((GstStructure *) list, structure_foreach_wrapper, &data);
762 }
763
764 /***** tag events *****/
765
766 /**
767  * gst_event_new_tag:
768  * @list: the tag list to put into the event or NULL for an empty list
769  *
770  * Creates a new tag event with the given list and takes ownership of it.
771  *
772  * Returns: a new tag event
773  */
774 GstEvent *
775 gst_event_new_tag (GstTagList *list)
776 {
777   GstEvent *ret;
778   
779   g_return_val_if_fail (list == NULL || GST_IS_TAG_LIST (list), NULL);
780
781   ret = gst_event_new (GST_EVENT_TAG);
782   if (!list)
783     list = gst_tag_list_new ();
784   ret->event_data.structure.structure = (GstStructure *) list;
785   
786   return ret;
787 }
788 /**
789  * get_event_tag_get_list:
790  * @tag_event: a tagging #GstEvent
791  *
792  * Gets the taglist from a given tagging event.
793  * 
794  * Returns: The #GstTagList of the event
795  */
796 GstTagList *
797 gst_event_tag_get_list (GstEvent *tag_event)
798 {
799   g_return_val_if_fail (GST_IS_EVENT (tag_event), NULL);
800   g_return_val_if_fail (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG, NULL);
801
802   return GST_TAG_LIST (tag_event->event_data.structure.structure);
803 }
804
805 /**
806  * gst_tag_list_get_value_index:
807  * @list: a #GStTagList
808  * @tag: tag to read out
809  * @index: number of entry to read out
810  *
811  * Gets the value that is at the given index for the given tag in the given 
812  * list.
813  * 
814  * Returns: The GValue for the specified entry or NULL if the tag wasn't available
815  *          or the tag doesn't have as many entries
816  */
817 G_CONST_RETURN GValue *
818 gst_tag_list_get_value_index (const GstTagList *list, const gchar *tag, guint index)
819 {
820   const GValue *value;
821
822   g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
823   g_return_val_if_fail (tag != NULL, NULL);
824   
825   value = gst_structure_get_value ((GstStructure *) list, tag);
826   if (value == NULL) return  NULL;
827   
828   if (GST_VALUE_HOLDS_LIST (value)) {
829     if (index >= gst_value_list_get_size (value)) return NULL;
830     return gst_value_list_get_value (value, index);
831   } else {
832     if (index > 0) return NULL;
833     return value;
834   }
835 }
836
837 /**
838  * gst_tag_list_copy_value:
839  * @dest: uninitialized #GValue to copy into
840  * @list: list to get the tag from
841  * @tag: tag to read out
842  *
843  * Copies the contents for the given tag into the value, merging multiple values 
844  * into one if multiple values are associated with the tag.
845  * You must g_value_unset() the value after use.
846  *
847  * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the 
848  *          given list.
849  */
850 gboolean
851 gst_tag_list_copy_value (GValue *dest, const GstTagList *list, const gchar *tag)
852 {
853   const GValue *src;
854   
855   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
856   g_return_val_if_fail (tag != NULL, FALSE);
857   g_return_val_if_fail (dest != NULL, FALSE);
858   g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE);
859   
860   src = gst_structure_get_value ((GstStructure *) list, tag);
861   if (!src) return FALSE;
862   
863   if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {    
864     GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
865     /* must be there or lists aren't allowed */
866     g_assert (info->merge_func);
867     info->merge_func (dest, src);
868   } else {
869     g_value_init (dest, G_VALUE_TYPE (src));
870     g_value_copy (src, dest);
871   }
872   return TRUE;
873 }
874
875 /***** evil macros to get all the gst_tag_list_get_*() functions right *****/
876
877 #define TAG_MERGE_FUNCS(name,type)                                              \
878 gboolean                                                                        \
879 gst_tag_list_get_ ## name (const GstTagList *list, const gchar *tag,            \
880                            type *value)                                         \
881 {                                                                               \
882   GValue v = { 0, };                                                            \
883                                                                                 \
884   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);                         \
885   g_return_val_if_fail (tag != NULL, FALSE);                                    \
886   g_return_val_if_fail (value != NULL, FALSE);                                  \
887                                                                                 \
888   if (!gst_tag_list_copy_value (&v, list, tag))                                 \
889       return FALSE;                                                             \
890   *value = COPY_FUNC (g_value_get_ ## name (&v));                               \
891   g_value_unset (&v);                                                           \
892   return TRUE;                                                                  \
893 }                                                                               \
894                                                                                 \
895 gboolean                                                                        \
896 gst_tag_list_get_ ## name ## _index (const GstTagList *list, const gchar *tag,  \
897                            guint index, type *value)                            \
898 {                                                                               \
899   const GValue *v;                                                              \
900                                                                                 \
901   g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);                         \
902   g_return_val_if_fail (tag != NULL, FALSE);                                    \
903   g_return_val_if_fail (value != NULL, FALSE);                                  \
904                                                                                 \
905   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)            \
906       return FALSE;                                                             \
907   *value = COPY_FUNC (g_value_get_ ## name (v));                                \
908   return TRUE;                                                                  \
909 }
910
911 #define COPY_FUNC /**/
912 TAG_MERGE_FUNCS (char, gchar)
913 TAG_MERGE_FUNCS (uchar, guchar)
914 TAG_MERGE_FUNCS (boolean, gboolean)
915 TAG_MERGE_FUNCS (int, gint)
916 TAG_MERGE_FUNCS (uint, guint)
917 TAG_MERGE_FUNCS (long, glong)
918 TAG_MERGE_FUNCS (ulong, gulong)
919 TAG_MERGE_FUNCS (int64, gint64)
920 TAG_MERGE_FUNCS (uint64, guint64)
921 TAG_MERGE_FUNCS (float, gfloat)
922 TAG_MERGE_FUNCS (double, gdouble)
923 #undef COPY_FUNC
924   
925 #define COPY_FUNC g_strdup
926 TAG_MERGE_FUNCS (string, gchar *)
927
928
929
930