~ubuntu-branches/ubuntu/saucy/gstreamer0.10/saucy

« back to all changes in this revision

Viewing changes to gst/gsttaglist.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2011-12-11 18:52:12 UTC
  • mfrom: (32.1.14 experimental)
  • Revision ID: package-import@ubuntu.com-20111211185212-3k215ps4qtyz2qa5
Tags: 0.10.35.2-1
* New upstream pre-release:
  + debian/control.in:
    - Build-depend on GLib >= 2.24.
  + debian/patches/99_ltmain_as-needed.patch:
    - Refreshed to apply cleanly again.
  + debian/libgstreamer.symbols:
    - Update symbols file with new API.
* debian/rules:
  + Remove all dependency_libs from the .la files (Closes: #633319).
* debian/control.in:
  + Put GI package into section introspection.
* debian/compat,
  debian/control.in,
  debian/gir1.2-gstreamer.install,
  debian/libgstreamer-dev.install,
  debian/libgstreamer.install,
  debian/patches/79_multiarch-backwards-compat.patch,
  debian/patches/80_ia32-hack.patch,
  debian/rules:
  + Transition package to multi-arch (Closes: #647481).
    Patch taken from the Ubuntu package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#endif
36
36
 
37
37
#include "gst_private.h"
 
38
#include "math-compat.h"
38
39
#include "gst-i18n-lib.h"
39
40
#include "gsttaglist.h"
40
41
#include "gstinfo.h"
60
61
 
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 */
63
65
}
64
66
GstTagInfo;
65
67
 
 
68
#if GLIB_CHECK_VERSION (2, 31, 0)
 
69
#define g_value_get_char g_value_get_schar
 
70
#endif
 
71
 
 
72
#if !GLIB_CHECK_VERSION (2, 31, 0)
66
73
static GMutex *__tag_mutex;
67
 
 
68
 
static GHashTable *__tags;
69
 
 
70
74
#define TAG_LOCK g_mutex_lock (__tag_mutex)
71
75
#define TAG_UNLOCK g_mutex_unlock (__tag_mutex)
 
76
#else
 
77
static GMutex __tag_mutex;
 
78
#define TAG_LOCK g_mutex_lock (&__tag_mutex)
 
79
#define TAG_UNLOCK g_mutex_unlock (&__tag_mutex)
 
80
#endif
 
81
 
 
82
/* tags hash table: maps tag name string => GstTagInfo */
 
83
static GHashTable *__tags;
72
84
 
73
85
GType
74
86
gst_tag_list_get_type (void)
91
103
void
92
104
_gst_tag_initialize (void)
93
105
{
 
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);
 
108
#else
 
109
  g_mutex_init (&__tag_mutex);
 
110
#endif
 
111
  __tags = g_hash_table_new (g_str_hash, g_str_equal);
96
112
  gst_tag_register (GST_TAG_TITLE, GST_TAG_FLAG_META,
97
113
      G_TYPE_STRING,
98
114
      _("title"), _("commonly used title"), gst_tag_merge_strings_with_comma);
417
433
}
418
434
 
419
435
static GstTagInfo *
420
 
gst_tag_lookup (GQuark entry)
 
436
gst_tag_lookup (const gchar * tag_name)
421
437
{
422
438
  GstTagInfo *ret;
423
439
 
424
440
  TAG_LOCK;
425
 
  ret = g_hash_table_lookup (__tags, GUINT_TO_POINTER (entry));
 
441
  ret = g_hash_table_lookup (__tags, (gpointer) tag_name);
426
442
  TAG_UNLOCK;
427
443
 
428
444
  return ret;
463
479
gst_tag_register (const gchar * name, GstTagFlag flag, GType type,
464
480
    const gchar * nick, const gchar * blurb, GstTagMergeFunc func)
465
481
{
466
 
  GQuark key;
467
482
  GstTagInfo *info;
 
483
  gchar *name_dup;
468
484
 
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);
473
489
 
474
 
  key = g_quark_from_string (name);
475
 
  info = gst_tag_lookup (key);
 
490
  info = gst_tag_lookup (name);
476
491
 
477
492
  if (info) {
478
493
    g_return_if_fail (info->type == type);
486
501
  info->blurb = g_strdup (blurb);
487
502
  info->merge_func = func;
488
503
 
 
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);
 
508
 
489
509
  TAG_LOCK;
490
 
  g_hash_table_insert (__tags, GUINT_TO_POINTER (key), info);
 
510
  g_hash_table_insert (__tags, (gpointer) name_dup, info);
491
511
  TAG_UNLOCK;
492
512
}
493
513
 
504
524
{
505
525
  g_return_val_if_fail (tag != NULL, FALSE);
506
526
 
507
 
  return gst_tag_lookup (g_quark_from_string (tag)) != NULL;
 
527
  return gst_tag_lookup (tag) != NULL;
508
528
}
509
529
 
510
530
/**
521
541
  GstTagInfo *info;
522
542
 
523
543
  g_return_val_if_fail (tag != NULL, 0);
524
 
  info = gst_tag_lookup (g_quark_from_string (tag));
 
544
  info = gst_tag_lookup (tag);
525
545
  g_return_val_if_fail (info != NULL, 0);
526
546
 
527
547
  return info->type;
542
562
  GstTagInfo *info;
543
563
 
544
564
  g_return_val_if_fail (tag != NULL, NULL);
545
 
  info = gst_tag_lookup (g_quark_from_string (tag));
 
565
  info = gst_tag_lookup (tag);
546
566
  g_return_val_if_fail (info != NULL, NULL);
547
567
 
548
568
  return info->nick;
563
583
  GstTagInfo *info;
564
584
 
565
585
  g_return_val_if_fail (tag != NULL, NULL);
566
 
  info = gst_tag_lookup (g_quark_from_string (tag));
 
586
  info = gst_tag_lookup (tag);
567
587
  g_return_val_if_fail (info != NULL, NULL);
568
588
 
569
589
  return info->blurb;
583
603
  GstTagInfo *info;
584
604
 
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);
588
608
 
589
609
  return info->flag;
604
624
  GstTagInfo *info;
605
625
 
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);
609
629
 
610
630
  return info->merge_func == NULL;
691
711
}
692
712
 
693
713
/**
 
714
 * gst_tag_list_to_string:
 
715
 * @list: a #GstTagList
 
716
 *
 
717
 * Serializes a tag list to a string.
 
718
 *
 
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.
 
721
 *
 
722
 * Since: 0.10.36
 
723
 */
 
724
gchar *
 
725
gst_tag_list_to_string (const GstTagList * list)
 
726
{
 
727
  g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
 
728
 
 
729
  return gst_structure_to_string (GST_STRUCTURE (list));
 
730
}
 
731
 
 
732
/**
 
733
 * gst_tag_list_new_from_string:
 
734
 * @str: a string created with gst_tag_list_to_string()
 
735
 *
 
736
 * Deserializes a tag list.
 
737
 *
 
738
 * Returns: a new #GstTagList, or NULL in case of an error.
 
739
 *
 
740
 * Since: 0.10.36
 
741
 */
 
742
GstTagList *
 
743
gst_tag_list_new_from_string (const gchar * str)
 
744
{
 
745
  g_return_val_if_fail (str != NULL, NULL);
 
746
  g_return_val_if_fail (g_str_has_prefix (str, "taglist"), NULL);
 
747
 
 
748
  return GST_TAG_LIST (gst_structure_from_string (str, NULL));
 
749
}
 
750
 
 
751
/**
694
752
 * gst_tag_list_is_empty:
695
753
 * @list: A #GstTagList.
696
754
 *
709
767
  return (gst_structure_n_fields ((GstStructure *) list) == 0);
710
768
}
711
769
 
 
770
static gboolean
 
771
gst_tag_list_fields_equal (const GValue * value1, const GValue * value2)
 
772
{
 
773
  gdouble d1, d2;
 
774
 
 
775
  if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL)
 
776
    return TRUE;
 
777
 
 
778
  /* fields not equal: add some tolerance for doubles, otherwise bail out */
 
779
  if (!G_VALUE_HOLDS_DOUBLE (value1) || !G_VALUE_HOLDS_DOUBLE (value2))
 
780
    return FALSE;
 
781
 
 
782
  d1 = g_value_get_double (value1);
 
783
  d2 = g_value_get_double (value2);
 
784
 
 
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);
 
789
}
 
790
 
 
791
/**
 
792
 * gst_tag_list_is_equal:
 
793
 * @list1: a #GstTagList.
 
794
 * @list2: a #GstTagList.
 
795
 *
 
796
 * Checks if the two given taglists are equal.
 
797
 *
 
798
 * Returns: TRUE if the taglists are equal, otherwise FALSE
 
799
 *
 
800
 * Since: 0.10.36
 
801
 */
 
802
gboolean
 
803
gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2)
 
804
{
 
805
  const GstStructure *s1, *s2;
 
806
  gint num_fields1, num_fields2, i;
 
807
 
 
808
  g_return_val_if_fail (GST_IS_TAG_LIST (list1), FALSE);
 
809
  g_return_val_if_fail (GST_IS_TAG_LIST (list2), FALSE);
 
810
 
 
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;
 
816
 
 
817
  num_fields1 = gst_structure_n_fields (s1);
 
818
  num_fields2 = gst_structure_n_fields (s2);
 
819
 
 
820
  if (num_fields1 != num_fields2)
 
821
    return FALSE;
 
822
 
 
823
  for (i = 0; i < num_fields1; i++) {
 
824
    const GValue *value1, *value2;
 
825
    const gchar *tag_name;
 
826
 
 
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);
 
830
 
 
831
    if (value2 == NULL)
 
832
      return FALSE;
 
833
 
 
834
    if (!gst_tag_list_fields_equal (value1, value2))
 
835
      return FALSE;
 
836
  }
 
837
 
 
838
  return TRUE;
 
839
}
 
840
 
712
841
/**
713
842
 * gst_is_tag_list:
714
843
 * @p: Object that might be a taglist
736
865
 
737
866
static void
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)
740
869
{
741
870
  const GValue *value2;
 
871
  GQuark tag_quark;
742
872
 
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);
747
877
      return;
748
878
    }
749
879
  }
750
880
 
 
881
  tag_quark = info->name_quark;
 
882
 
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, };
754
886
 
755
887
    switch (mode) {
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);
759
891
        break;
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);
764
896
        break;
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);
769
901
        break;
770
902
      case GST_TAG_MERGE_KEEP:
778
910
    switch (mode) {
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)
782
914
          break;
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);
788
920
        break;
789
921
      case GST_TAG_MERGE_KEEP_ALL:
790
922
        break;
796
928
}
797
929
 
798
930
static gboolean
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,
 
932
    gpointer user_data)
800
933
{
801
934
  GstTagCopyData *copy = (GstTagCopyData *) user_data;
 
935
  const gchar *tag;
802
936
 
 
937
  tag = g_quark_to_string (tag_quark);
803
938
  gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value, NULL);
804
939
 
805
940
  return TRUE;
991
1126
    const gchar * tag, va_list var_args)
992
1127
{
993
1128
  GstTagInfo *info;
994
 
  GQuark quark;
995
1129
  gchar *error = NULL;
996
1130
 
997
1131
  g_return_if_fail (GST_IS_TAG_LIST (list));
1005
1139
  while (tag != NULL) {
1006
1140
    GValue value = { 0, };
1007
1141
 
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);
1012
1145
      return;
1013
1146
    }
1014
 
#if GLIB_CHECK_VERSION(2,23,3)
1015
1147
    G_VALUE_COLLECT_INIT (&value, info->type, var_args, 0, &error);
1016
 
#else
1017
 
    g_value_init (&value, info->type);
1018
 
    G_VALUE_COLLECT (&value, var_args, 0, &error);
1019
 
#endif
1020
1148
    if (error) {
1021
1149
      g_warning ("%s: %s", G_STRLOC, error);
1022
1150
      g_free (error);
1025
1153
       */
1026
1154
      return;
1027
1155
    }
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 *);
1031
1159
  }
1044
1172
gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode,
1045
1173
    const gchar * tag, va_list var_args)
1046
1174
{
1047
 
  GQuark quark;
1048
 
 
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);
1055
1181
  }
1056
1182
 
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,
1061
 
            GValue *), NULL);
 
1184
    GstTagInfo *info;
 
1185
 
 
1186
    info = gst_tag_lookup (tag);
 
1187
    if (G_UNLIKELY (info == NULL)) {
 
1188
      g_warning ("unknown tag '%s'", tag);
 
1189
      return;
 
1190
    }
 
1191
    gst_tag_list_add_value_internal (list, mode, tag, va_arg (var_args,
 
1192
            GValue *), info);
1062
1193
    tag = va_arg (var_args, gchar *);
1063
1194
  }
1064
1195
}
1082
1213
  g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
1083
1214
  g_return_if_fail (tag != NULL);
1084
1215
 
1085
 
  gst_tag_list_add_value_internal (list, mode, g_quark_from_string (tag),
1086
 
      value, NULL);
 
1216
  gst_tag_list_add_value_internal (list, mode, tag, value, NULL);
1087
1217
}
1088
1218
 
1089
1219
/**
1211
1341
    return FALSE;
1212
1342
 
1213
1343
  if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
1214
 
    GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
 
1344
    GstTagInfo *info = gst_tag_lookup (tag);
1215
1345
 
1216
1346
    if (!info)
1217
1347
      return FALSE;