[PATCH 4/8] core: Add filtering by equal key



From: "Juan A. Suarez Romero" <jasuarez igalia com>

It supports filtering by equal operator, as "artist = Madonna".

Contains modifications by Guillaume Emont <gemont igalia com>
---
 src/grl-caps.c                   |   50 ++++++++++++
 src/grl-caps.h                   |    7 ++
 src/grl-operation-options-priv.h |    1 +
 src/grl-operation-options.c      |  164 ++++++++++++++++++++++++++++++++++++++
 src/grl-operation-options.h      |   16 ++++
 src/grl-value-helper.c           |    6 ++
 src/grl-value-helper.h           |    2 +
 7 files changed, 246 insertions(+), 0 deletions(-)

diff --git a/src/grl-caps.c b/src/grl-caps.c
index afbc9e3..4669499 100644
--- a/src/grl-caps.c
+++ b/src/grl-caps.c
@@ -61,6 +61,7 @@ G_DEFINE_TYPE (GrlCaps, grl_caps, G_TYPE_OBJECT);
 struct _GrlCapsPrivate {
   GHashTable *data;
   GrlTypeFilter type_filter;
+  GList *key_filter;
 };
 
 
@@ -75,6 +76,7 @@ static void
 grl_caps_finalize (GrlCaps *self)
 {
   g_hash_table_unref (self->priv->data);
+  g_list_free (self->priv->key_filter);
   G_OBJECT_CLASS (grl_caps_parent_class)->finalize ((GObject *) self);
 }
 
@@ -88,6 +90,7 @@ grl_caps_init (GrlCaps *self)
   /* by default, type filtering is not considered to be supported. The source
    * has to explicitly modify its caps. */
   self->priv->type_filter = GRL_TYPE_FILTER_NONE;
+  self->priv->key_filter = NULL;
 }
 
 static void
@@ -144,6 +147,11 @@ grl_caps_test_option (GrlCaps *caps, const gchar *key, const GValue *value)
     return filter == (filter & supported_filter);
   }
 
+  if (0 == g_strcmp0 (key, GRL_OPERATION_OPTION_KEY_EQUAL_FILTER)) {
+    GrlKeyID metadata_key = g_value_get_grl_key_id (value);
+    return grl_caps_is_key_filter (caps, metadata_key);
+  }
+
   return FALSE;
 }
 
@@ -163,3 +171,45 @@ grl_caps_set_type_filter (GrlCaps *caps, GrlTypeFilter filter)
   caps->priv->type_filter = filter;
 }
 
+/**
+ * grl_caps_get_key_filter:
+ *
+ * Returns: (transfer none) (element-type GrlKeyID):
+ */
+GList *
+grl_caps_get_key_filter (GrlCaps *caps)
+{
+  g_return_val_if_fail (caps, NULL);
+
+  return caps->priv->key_filter;
+}
+
+/**
+ * grl_caps_set_key_filter:
+ * @caps:
+ * @keys: (transfer none) (element-type GrlKeyID):
+ */
+void
+grl_caps_set_key_filter (GrlCaps *caps, GList *keys)
+{
+  g_return_if_fail (caps);
+
+  if (caps->priv->key_filter) {
+    g_list_free (caps->priv->key_filter);
+  }
+
+  caps->priv->key_filter = g_list_copy (keys);
+}
+
+gboolean
+grl_caps_is_key_filter (GrlCaps *caps, GrlKeyID key)
+{
+  g_return_val_if_fail (caps, FALSE);
+
+  if(caps->priv->key_filter) {
+    return g_list_find (caps->priv->key_filter,
+                        GRLKEYID_TO_POINTER(key)) != NULL;
+  }
+
+  return FALSE;
+}
diff --git a/src/grl-caps.h b/src/grl-caps.h
index de1ecef..e3abdfa 100644
--- a/src/grl-caps.h
+++ b/src/grl-caps.h
@@ -29,6 +29,7 @@
 
 #include <glib-object.h>
 #include <grl-definitions.h>
+#include <grl-metadata-key.h>
 
 G_BEGIN_DECLS
 
@@ -87,6 +88,12 @@ GrlTypeFilter grl_caps_get_type_filter (GrlCaps *caps);
 
 void grl_caps_set_type_filter (GrlCaps *caps, GrlTypeFilter filter);
 
+GList *grl_caps_get_key_filter (GrlCaps *caps);
+
+void grl_caps_set_key_filter (GrlCaps *caps, GList *keys);
+
+gboolean grl_caps_is_key_filter (GrlCaps *caps, GrlKeyID key);
+
 G_END_DECLS
 
 #endif /* _GRL_CAPS_H_ */
diff --git a/src/grl-operation-options-priv.h b/src/grl-operation-options-priv.h
index b420bc5..2f5d9c3 100644
--- a/src/grl-operation-options-priv.h
+++ b/src/grl-operation-options-priv.h
@@ -35,6 +35,7 @@
 #define GRL_OPERATION_OPTION_COUNT "count"
 #define GRL_OPERATION_OPTION_FLAGS "flags"
 #define GRL_OPERATION_OPTION_TYPE_FILTER "type-filter"
+#define GRL_OPERATION_OPTION_KEY_EQUAL_FILTER "key-equal-filter"
 
 gboolean grl_operation_options_key_is_set (GrlOperationOptions *options,
                                            const gchar *key);
diff --git a/src/grl-operation-options.c b/src/grl-operation-options.c
index f5632ff..265f20f 100644
--- a/src/grl-operation-options.c
+++ b/src/grl-operation-options.c
@@ -30,6 +30,8 @@
  */
 #include <grl-operation-options.h>
 #include <grl-value-helper.h>
+#include <grl-log.h>
+#include <grl-plugin-registry.h>
 
 #include "grl-operation-options-priv.h"
 #include "grl-type-builtins.h"
@@ -41,6 +43,7 @@ G_DEFINE_TYPE (GrlOperationOptions, grl_operation_options, G_TYPE_OBJECT);
 
 struct _GrlOperationOptionsPrivate {
   GHashTable *data;
+  GHashTable *key_filter;
   GrlCaps *caps;
 };
 
@@ -59,6 +62,7 @@ static void
 grl_operation_options_finalize (GrlOperationOptions *self)
 {
   g_hash_table_unref (self->priv->data);
+  g_hash_table_unref (self->priv->key_filter);
   if (self->priv->caps)
     g_object_unref (self->priv->caps);
   G_OBJECT_CLASS (grl_operation_options_parent_class)->finalize ((GObject *) self);
@@ -70,6 +74,7 @@ grl_operation_options_init (GrlOperationOptions *self)
   self->priv = GRL_OPERATION_OPTIONS_GET_PRIVATE (self);
 
   self->priv->data = grl_g_value_hashtable_new ();
+  self->priv->key_filter = grl_g_value_hashtable_new_direct ();
   self->priv->caps = NULL;
 }
 
@@ -130,6 +135,11 @@ check_and_copy_option (GrlOperationOptions *options,
   return TRUE;
 }
 
+static void
+key_filter_dup (gpointer key_p, GValue *value, GHashTable *destination)
+{
+  g_hash_table_insert (destination, key_p, grl_g_value_dup (value));
+}
 
 /* ========== API ========== */
 
@@ -178,6 +188,9 @@ grl_operation_options_obey_caps (GrlOperationOptions *options,
                                  GrlOperationOptions **unsupported_options)
 {
   gboolean ret = TRUE;
+  GHashTableIter table_iter;
+  gpointer key_ptr;
+  GValue *value;
 
   if (supported_options) {
     *supported_options = grl_operation_options_new (caps);
@@ -197,6 +210,26 @@ grl_operation_options_obey_caps (GrlOperationOptions *options,
                                 supported_options,
                                 unsupported_options);
 
+  /* Check filter-by-equal-key */
+  g_hash_table_iter_init (&table_iter, options->priv->key_filter);
+  while (g_hash_table_iter_next (&table_iter, &key_ptr, (gpointer *)&value)) {
+    GrlKeyID key_id = GRLPOINTER_TO_KEYID (key_ptr);
+    if (grl_caps_is_key_filter (caps, key_id)) {
+      if (supported_options) {
+        g_hash_table_insert ((*supported_options)->priv->key_filter,
+                             key_ptr,
+                             grl_g_value_dup (value));
+      }
+    } else {
+      ret = FALSE;
+      if (unsupported_options) {
+        g_hash_table_insert ((*unsupported_options)->priv->key_filter,
+                             key_ptr,
+                             grl_g_value_dup (value));
+      }
+    }
+  }
+
   return ret;
 }
 
@@ -217,6 +250,10 @@ grl_operation_options_copy (GrlOperationOptions *options)
   copy_option (options, copy, GRL_OPERATION_OPTION_FLAGS);
   copy_option (options, copy, GRL_OPERATION_OPTION_TYPE_FILTER);
 
+  g_hash_table_foreach (options->priv->key_filter,
+                        (GHFunc) key_filter_dup,
+                        copy->priv->key_filter);
+
   return copy;
 }
 
@@ -431,3 +468,130 @@ grl_operation_options_get_type_filter (GrlOperationOptions *options)
 
   return TYPE_FILTER_DEFAULT;
 }
+
+gboolean
+grl_operation_options_set_key_filter_value (GrlOperationOptions *options,
+                                            GrlKeyID key,
+                                            GValue *value)
+{
+  gboolean ret;
+  GrlPluginRegistry *registry;
+  GType key_type;
+
+  registry = grl_plugin_registry_get_default ();
+  key_type = grl_plugin_registry_lookup_metadata_key_type (registry, key);
+
+  if (G_VALUE_TYPE (value) != key_type)
+    return FALSE;
+
+  ret = (options->priv->caps == NULL) ||
+    grl_caps_is_key_filter (options->priv->caps, key);
+
+  if (ret) {
+    if (value) {
+      g_hash_table_insert (options->priv->key_filter,
+                           GRLKEYID_TO_POINTER (key),
+                           grl_g_value_dup (value));
+    } else {
+      g_hash_table_remove (options->priv->key_filter,
+                           GRLKEYID_TO_POINTER (key));
+    }
+  }
+
+  return ret;
+}
+
+gboolean
+grl_operation_options_set_key_filters (GrlOperationOptions *options,
+                                       ...)
+{
+  GType key_type;
+  GValue value = { 0 };
+  GrlKeyID next_key;
+  gboolean skip;
+  gboolean success = TRUE;
+  va_list args;
+
+  va_start (args, options);
+  next_key = va_arg (args, GrlKeyID);
+  while (next_key) {
+    key_type = GRL_METADATA_KEY_GET_TYPE (next_key);
+    g_value_init (&value, key_type);
+    skip = FALSE;
+    if (key_type == G_TYPE_STRING) {
+      g_value_set_string (&value, va_arg (args, gchar *));
+    } else if (key_type == G_TYPE_INT) {
+      g_value_set_int (&value, va_arg (args, gint));
+    } else {
+      GRL_WARNING ("Unexpected key type when setting up the filter");
+      success = FALSE;
+      skip = TRUE;
+    }
+
+    if (!skip) {
+      success &= grl_operation_options_set_key_filter_value (options,
+                                                             next_key,
+                                                             &value);
+    }
+
+    g_value_unset (&value);
+    next_key = va_arg (args, GrlKeyID);
+  }
+
+  va_end (args);
+
+  return success;
+}
+
+/**
+ * grl_operation_options_set_key_filter_dictionary:
+ * @options:
+ * @filters: (transfer none) (element-type GrlKeyID GValue):
+ *
+ *
+ * Rename to: grl_operation_options_set_key_filters
+ */
+gboolean
+grl_operation_options_set_key_filter_dictionary (GrlOperationOptions *options,
+                                                 GHashTable *filters)
+{
+  GHashTableIter iter;
+  gpointer _key, _value;
+  gboolean ret = TRUE;
+
+  g_hash_table_iter_init (&iter, filters);
+  while (g_hash_table_iter_next (&iter, &_key, &_value)) {
+    GrlKeyID key = GRLPOINTER_TO_KEYID (_key);
+    GValue *value = (GValue *)_value;
+    ret &=
+        grl_operation_options_set_key_filter_value (options, key, value);
+  }
+
+  return ret;
+}
+
+/**
+ * grl_operation_options_get_key_filter:
+ * @options:
+ * @key:
+ *
+ * Returns: (transfer none): the filter
+ */
+GValue *
+grl_operation_options_get_key_filter (GrlOperationOptions *options,
+                                      GrlKeyID key)
+{
+  return g_hash_table_lookup (options->priv->key_filter,
+                              GRLKEYID_TO_POINTER (key));
+}
+
+/**
+ * grl_operation_options_get_key_filter_list:
+ *
+ * Returns: (transfer container) (element-type GrlKeyID):
+ */
+GList *
+grl_operation_options_get_key_filter_list (GrlOperationOptions *options)
+{
+  return g_hash_table_get_keys (options->priv->key_filter);
+}
diff --git a/src/grl-operation-options.h b/src/grl-operation-options.h
index 0cf992f..5682ca1 100644
--- a/src/grl-operation-options.h
+++ b/src/grl-operation-options.h
@@ -25,6 +25,7 @@
 #endif
 
 #include <grl-caps.h>
+#include <grl-metadata-key.h>
 
 #if !defined (_GRL_OPERATION_OPTIONS_H_)
 #define _GRL_OPERATION_OPTIONS_H_
@@ -101,6 +102,21 @@ gboolean grl_operation_options_set_type_filter (GrlOperationOptions *options,
 
 GrlTypeFilter grl_operation_options_get_type_filter (GrlOperationOptions *options);
 
+gboolean grl_operation_options_set_key_filter_value (GrlOperationOptions *options,
+                                                     GrlKeyID key,
+                                                     GValue *value);
+
+gboolean grl_operation_options_set_key_filters (GrlOperationOptions *options,
+                                                ...) G_GNUC_NULL_TERMINATED;
+
+gboolean grl_operation_options_set_key_filter_dictionary (GrlOperationOptions *options,
+                                                          GHashTable *filters);
+
+GValue *grl_operation_options_get_key_filter (GrlOperationOptions *options,
+                                              GrlKeyID key);
+
+GList *grl_operation_options_get_key_filter_list (GrlOperationOptions *options);
+
 G_END_DECLS
 
 #endif /* _GRL_OPERATION_OPTIONS_H_ */
diff --git a/src/grl-value-helper.c b/src/grl-value-helper.c
index 572d6c8..74fe7cb 100644
--- a/src/grl-value-helper.c
+++ b/src/grl-value-helper.c
@@ -67,6 +67,12 @@ grl_g_value_hashtable_new (void)
   return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)grl_g_value_free);
 }
 
+GHashTable *
+grl_g_value_hashtable_new_direct (void)
+{
+  return g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)grl_g_value_free);
+}
+
 /**
  * grl_g_value_dup: (skip):
  */
diff --git a/src/grl-value-helper.h b/src/grl-value-helper.h
index 6079822..bda9069 100644
--- a/src/grl-value-helper.h
+++ b/src/grl-value-helper.h
@@ -37,6 +37,8 @@ void grl_g_value_free (GValue *value);
 
 GHashTable *grl_g_value_hashtable_new (void);
 
+GHashTable *grl_g_value_hashtable_new_direct (void);
+
 GValue *grl_g_value_dup (const GValue *value);
 
 G_END_DECLS
-- 
1.7.5.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]