61
62
GstTagMergeFunc merge_func; /* functions to merge the values */
62
63
GstTagFlag flag; /* type of tag */
64
GQuark name_quark; /* quark for the name */
68
#if GLIB_CHECK_VERSION (2, 31, 0)
69
#define g_value_get_char g_value_get_schar
72
#if !GLIB_CHECK_VERSION (2, 31, 0)
66
73
static GMutex *__tag_mutex;
68
static GHashTable *__tags;
70
74
#define TAG_LOCK g_mutex_lock (__tag_mutex)
71
75
#define TAG_UNLOCK g_mutex_unlock (__tag_mutex)
77
static GMutex __tag_mutex;
78
#define TAG_LOCK g_mutex_lock (&__tag_mutex)
79
#define TAG_UNLOCK g_mutex_unlock (&__tag_mutex)
82
/* tags hash table: maps tag name string => GstTagInfo */
83
static GHashTable *__tags;
74
86
gst_tag_list_get_type (void)
92
104
_gst_tag_initialize (void)
106
#if !GLIB_CHECK_VERSION (2, 31, 0)
94
107
__tag_mutex = g_mutex_new ();
95
__tags = g_hash_table_new (g_direct_hash, g_direct_equal);
109
g_mutex_init (&__tag_mutex);
111
__tags = g_hash_table_new (g_str_hash, g_str_equal);
96
112
gst_tag_register (GST_TAG_TITLE, GST_TAG_FLAG_META,
98
114
_("title"), _("commonly used title"), gst_tag_merge_strings_with_comma);
419
435
static GstTagInfo *
420
gst_tag_lookup (GQuark entry)
436
gst_tag_lookup (const gchar * tag_name)
425
ret = g_hash_table_lookup (__tags, GUINT_TO_POINTER (entry));
441
ret = g_hash_table_lookup (__tags, (gpointer) tag_name);
463
479
gst_tag_register (const gchar * name, GstTagFlag flag, GType type,
464
480
const gchar * nick, const gchar * blurb, GstTagMergeFunc func)
467
482
GstTagInfo *info;
469
485
g_return_if_fail (name != NULL);
470
486
g_return_if_fail (nick != NULL);
471
487
g_return_if_fail (blurb != NULL);
472
488
g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
474
key = g_quark_from_string (name);
475
info = gst_tag_lookup (key);
490
info = gst_tag_lookup (name);
478
493
g_return_if_fail (info->type == type);
486
501
info->blurb = g_strdup (blurb);
487
502
info->merge_func = func;
504
/* we make a copy for the hash table anyway, which will stay around, so
505
* can use that for the quark table too */
506
name_dup = g_strdup (name);
507
info->name_quark = g_quark_from_static_string (name_dup);
490
g_hash_table_insert (__tags, GUINT_TO_POINTER (key), info);
510
g_hash_table_insert (__tags, (gpointer) name_dup, info);
583
603
GstTagInfo *info;
585
605
g_return_val_if_fail (tag != NULL, GST_TAG_FLAG_UNDEFINED);
586
info = gst_tag_lookup (g_quark_from_string (tag));
606
info = gst_tag_lookup (tag);
587
607
g_return_val_if_fail (info != NULL, GST_TAG_FLAG_UNDEFINED);
589
609
return info->flag;
604
624
GstTagInfo *info;
606
626
g_return_val_if_fail (tag != NULL, FALSE);
607
info = gst_tag_lookup (g_quark_from_string (tag));
627
info = gst_tag_lookup (tag);
608
628
g_return_val_if_fail (info != NULL, FALSE);
610
630
return info->merge_func == NULL;
714
* gst_tag_list_to_string:
715
* @list: a #GstTagList
717
* Serializes a tag list to a string.
719
* Returns: a newly-allocated string, or NULL in case of an error. The
720
* string must be freed with g_free() when no longer needed.
725
gst_tag_list_to_string (const GstTagList * list)
727
g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
729
return gst_structure_to_string (GST_STRUCTURE (list));
733
* gst_tag_list_new_from_string:
734
* @str: a string created with gst_tag_list_to_string()
736
* Deserializes a tag list.
738
* Returns: a new #GstTagList, or NULL in case of an error.
743
gst_tag_list_new_from_string (const gchar * str)
745
g_return_val_if_fail (str != NULL, NULL);
746
g_return_val_if_fail (g_str_has_prefix (str, "taglist"), NULL);
748
return GST_TAG_LIST (gst_structure_from_string (str, NULL));
694
752
* gst_tag_list_is_empty:
695
753
* @list: A #GstTagList.
709
767
return (gst_structure_n_fields ((GstStructure *) list) == 0);
771
gst_tag_list_fields_equal (const GValue * value1, const GValue * value2)
775
if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL)
778
/* fields not equal: add some tolerance for doubles, otherwise bail out */
779
if (!G_VALUE_HOLDS_DOUBLE (value1) || !G_VALUE_HOLDS_DOUBLE (value2))
782
d1 = g_value_get_double (value1);
783
d2 = g_value_get_double (value2);
785
/* This will only work for 'normal' values and values around 0,
786
* which should be good enough for our purposes here
787
* FIXME: maybe add this to gst_value_compare_double() ? */
788
return (fabs (d1 - d2) < 0.0000001);
792
* gst_tag_list_is_equal:
793
* @list1: a #GstTagList.
794
* @list2: a #GstTagList.
796
* Checks if the two given taglists are equal.
798
* Returns: TRUE if the taglists are equal, otherwise FALSE
803
gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2)
805
const GstStructure *s1, *s2;
806
gint num_fields1, num_fields2, i;
808
g_return_val_if_fail (GST_IS_TAG_LIST (list1), FALSE);
809
g_return_val_if_fail (GST_IS_TAG_LIST (list2), FALSE);
811
/* we don't just use gst_structure_is_equal() here so we can add some
812
* tolerance for doubles, though maybe we should just add that to
813
* gst_value_compare_double() as well? */
814
s1 = (const GstStructure *) list1;
815
s2 = (const GstStructure *) list2;
817
num_fields1 = gst_structure_n_fields (s1);
818
num_fields2 = gst_structure_n_fields (s2);
820
if (num_fields1 != num_fields2)
823
for (i = 0; i < num_fields1; i++) {
824
const GValue *value1, *value2;
825
const gchar *tag_name;
827
tag_name = gst_structure_nth_field_name (s1, i);
828
value1 = gst_structure_get_value (s1, tag_name);
829
value2 = gst_structure_get_value (s2, tag_name);
834
if (!gst_tag_list_fields_equal (value1, value2))
713
842
* gst_is_tag_list:
714
843
* @p: Object that might be a taglist
738
867
gst_tag_list_add_value_internal (GstStructure * list, GstTagMergeMode mode,
739
GQuark tag, const GValue * value, GstTagInfo * info)
868
const gchar * tag, const GValue * value, GstTagInfo * info)
741
870
const GValue *value2;
743
873
if (info == NULL) {
744
874
info = gst_tag_lookup (tag);
745
875
if (G_UNLIKELY (info == NULL)) {
746
g_warning ("unknown tag '%s'", g_quark_to_string (tag));
876
g_warning ("unknown tag '%s'", tag);
881
tag_quark = info->name_quark;
751
883
if (info->merge_func
752
&& (value2 = gst_structure_id_get_value (list, tag)) != NULL) {
884
&& (value2 = gst_structure_id_get_value (list, tag_quark)) != NULL) {
753
885
GValue dest = { 0, };
756
888
case GST_TAG_MERGE_REPLACE_ALL:
757
889
case GST_TAG_MERGE_REPLACE:
758
gst_structure_id_set_value (list, tag, value);
890
gst_structure_id_set_value (list, tag_quark, value);
760
892
case GST_TAG_MERGE_PREPEND:
761
893
gst_value_list_merge (&dest, value, value2);
762
gst_structure_id_set_value (list, tag, &dest);
894
gst_structure_id_set_value (list, tag_quark, &dest);
763
895
g_value_unset (&dest);
765
897
case GST_TAG_MERGE_APPEND:
766
898
gst_value_list_merge (&dest, value2, value);
767
gst_structure_id_set_value (list, tag, &dest);
899
gst_structure_id_set_value (list, tag_quark, &dest);
768
900
g_value_unset (&dest);
770
902
case GST_TAG_MERGE_KEEP:
779
911
case GST_TAG_MERGE_APPEND:
780
912
case GST_TAG_MERGE_KEEP:
781
if (gst_structure_id_get_value (list, tag) != NULL)
913
if (gst_structure_id_get_value (list, tag_quark) != NULL)
783
915
/* fall through */
784
916
case GST_TAG_MERGE_REPLACE_ALL:
785
917
case GST_TAG_MERGE_REPLACE:
786
918
case GST_TAG_MERGE_PREPEND:
787
gst_structure_id_set_value (list, tag, value);
919
gst_structure_id_set_value (list, tag_quark, value);
789
921
case GST_TAG_MERGE_KEEP_ALL:
799
gst_tag_list_copy_foreach (GQuark tag, const GValue * value, gpointer user_data)
931
gst_tag_list_copy_foreach (GQuark tag_quark, const GValue * value,
801
934
GstTagCopyData *copy = (GstTagCopyData *) user_data;
937
tag = g_quark_to_string (tag_quark);
803
938
gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value, NULL);
1005
1139
while (tag != NULL) {
1006
1140
GValue value = { 0, };
1008
quark = g_quark_from_string (tag);
1009
info = gst_tag_lookup (quark);
1142
info = gst_tag_lookup (tag);
1010
1143
if (G_UNLIKELY (info == NULL)) {
1011
1144
g_warning ("unknown tag '%s'", tag);
1014
#if GLIB_CHECK_VERSION(2,23,3)
1015
1147
G_VALUE_COLLECT_INIT (&value, info->type, var_args, 0, &error);
1017
g_value_init (&value, info->type);
1018
G_VALUE_COLLECT (&value, var_args, 0, &error);
1021
1149
g_warning ("%s: %s", G_STRLOC, error);
1022
1150
g_free (error);
1028
gst_tag_list_add_value_internal (list, mode, quark, &value, info);
1156
gst_tag_list_add_value_internal (list, mode, tag, &value, info);
1029
1157
g_value_unset (&value);
1030
1158
tag = va_arg (var_args, gchar *);
1044
1172
gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode,
1045
1173
const gchar * tag, va_list var_args)
1049
1175
g_return_if_fail (GST_IS_TAG_LIST (list));
1050
1176
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1051
1177
g_return_if_fail (tag != NULL);
1057
1183
while (tag != NULL) {
1058
quark = g_quark_from_string (tag);
1059
g_return_if_fail (gst_tag_lookup (quark) != NULL);
1060
gst_tag_list_add_value_internal (list, mode, quark, va_arg (var_args,
1186
info = gst_tag_lookup (tag);
1187
if (G_UNLIKELY (info == NULL)) {
1188
g_warning ("unknown tag '%s'", tag);
1191
gst_tag_list_add_value_internal (list, mode, tag, va_arg (var_args,
1062
1193
tag = va_arg (var_args, gchar *);
1082
1213
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1083
1214
g_return_if_fail (tag != NULL);
1085
gst_tag_list_add_value_internal (list, mode, g_quark_from_string (tag),
1216
gst_tag_list_add_value_internal (list, mode, tag, value, NULL);