[gupnp-dlna] Add native sets implementation



commit eace62f28b1d14b17eac0d3f8ad36238089caca5
Author: Krzesimir Nowak <krnowak openismus com>
Date:   Thu Nov 15 15:01:14 2012 +0100

    Add native sets implementation
    
    Tailored for GUPnP-DLNA needs. It will replace the use of GstCaps.
    Called "native" because of lack of better name.

 .../native/sets/gupnp-dlna-native-info-set.c       |  282 ++++++++
 .../native/sets/gupnp-dlna-native-info-set.h       |   93 +++
 .../native/sets/gupnp-dlna-native-info-value.c     |  180 +++++
 .../native/sets/gupnp-dlna-native-info-value.h     |   67 ++
 .../native/sets/gupnp-dlna-native-restriction.c    |  261 ++++++++
 .../native/sets/gupnp-dlna-native-restriction.h    |   77 +++
 .../native/sets/gupnp-dlna-native-sets-private.h   |  139 ++++
 .../native/sets/gupnp-dlna-native-value-list.c     |  337 ++++++++++
 .../native/sets/gupnp-dlna-native-value-list.h     |   50 ++
 .../native/sets/gupnp-dlna-native-value-type.c     |  686 ++++++++++++++++++++
 .../native/sets/gupnp-dlna-native-value-type.h     |   45 ++
 .../native/sets/gupnp-dlna-native-value.c          |  393 +++++++++++
 .../native/sets/gupnp-dlna-native-value.h          |   70 ++
 libgupnp-dlna/profile-backends/native/sets/sets.am |   14 +
 14 files changed, 2694 insertions(+), 0 deletions(-)
---
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-set.c b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-set.c
new file mode 100644
index 0000000..c7b2bfd
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-set.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+
+#include "gupnp-dlna-native-info-set.h"
+#include "gupnp-dlna-native-info-value.h"
+#include "gupnp-dlna-native-sets-private.h"
+
+struct _GUPnPDLNANativeInfoSet {
+        gchar *mime;
+        GHashTable *entries; /* <gchar *, GUPnPDLNANativeInfoValue *> */
+};
+
+GUPnPDLNANativeInfoSet *
+gupnp_dlna_native_info_set_new (const gchar *mime)
+{
+        GUPnPDLNANativeInfoSet *info_set;
+
+        g_return_val_if_fail (mime != NULL, NULL);
+
+        info_set = g_slice_new (GUPnPDLNANativeInfoSet);
+        info_set->mime = g_strdup (mime);
+        info_set->entries = g_hash_table_new_full
+                           (g_str_hash,
+                            g_str_equal,
+                            g_free,
+                            (GDestroyNotify) gupnp_dlna_native_info_value_free);
+
+        return info_set;
+}
+
+void
+gupnp_dlna_native_info_set_free (GUPnPDLNANativeInfoSet *info_set)
+{
+        if (info_set == NULL)
+                return;
+        g_free (info_set->mime);
+        g_hash_table_unref (info_set->entries);
+        g_slice_free (GUPnPDLNANativeInfoSet, info_set);
+}
+
+static gboolean
+insert_value (GUPnPDLNANativeInfoSet   *info_set,
+              const gchar              *name,
+              GUPnPDLNANativeInfoValue *value)
+{
+        if (value == NULL) {
+                g_debug ("Info set: value '%s' is NULL.", name);
+
+                return FALSE;
+        }
+
+        if (g_hash_table_contains (info_set->entries, name)) {
+                g_debug ("Info set: value '%s' already exists.", name);
+                gupnp_dlna_native_info_value_free (value);
+
+                return FALSE;
+        }
+        g_hash_table_insert (info_set->entries, g_strdup (name), value);
+
+        return TRUE;
+}
+
+gboolean
+gupnp_dlna_native_info_set_add_bool (GUPnPDLNANativeInfoSet *info_set,
+                                     const gchar *name,
+                                     gboolean value)
+{
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+
+        return insert_value (info_set,
+                             name,
+                             gupnp_dlna_native_info_value_new_bool (value));
+}
+
+gboolean
+gupnp_dlna_native_info_set_add_unsupported_bool
+                                        (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar *name)
+{
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+
+        return insert_value
+                         (info_set,
+                          name,
+                          gupnp_dlna_native_info_value_new_unsupported_bool ());
+}
+
+gboolean
+gupnp_dlna_native_info_set_add_fraction (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar *name,
+                                         gint numerator,
+                                         gint denominator)
+{
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+
+        return insert_value (info_set,
+                             name,
+                             gupnp_dlna_native_info_value_new_fraction
+                                        (numerator,
+                                         denominator));
+}
+
+gboolean
+gupnp_dlna_native_info_set_add_unsupported_fraction
+                                        (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar *name)
+{
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+
+        return insert_value
+                     (info_set,
+                      name,
+                      gupnp_dlna_native_info_value_new_unsupported_fraction ());
+}
+
+gboolean
+gupnp_dlna_native_info_set_add_int (GUPnPDLNANativeInfoSet *info_set,
+                                    const gchar *name,
+                                    gint value)
+{
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+
+        return insert_value (info_set,
+                             name,
+                             gupnp_dlna_native_info_value_new_int (value));
+}
+
+gboolean
+gupnp_dlna_native_info_set_add_unsupported_int
+                                        (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar *name)
+{
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+
+        return insert_value
+                          (info_set,
+                           name,
+                           gupnp_dlna_native_info_value_new_unsupported_int ());
+}
+
+gboolean
+gupnp_dlna_native_info_set_add_string (GUPnPDLNANativeInfoSet *info_set,
+                                       const gchar            *name,
+                                       const gchar            *value)
+{
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+        g_return_val_if_fail (value != NULL, FALSE);
+
+        return insert_value (info_set,
+                             name,
+                             gupnp_dlna_native_info_value_new_string (value));
+}
+
+gboolean
+gupnp_dlna_native_info_set_add_unsupported_string
+                                        (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar *name)
+{
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+
+        return insert_value
+                       (info_set,
+                        name,
+                        gupnp_dlna_native_info_value_new_unsupported_string ());
+}
+
+gboolean
+gupnp_dlna_native_info_set_fits_restriction
+                                       (GUPnPDLNANativeInfoSet     *info_set,
+                                        GUPnPDLNANativeRestriction *restriction)
+{
+        GHashTableIter iter;
+        gpointer key;
+        gpointer value;
+        gboolean unsupported_match;
+
+        g_return_val_if_fail (info_set != NULL, FALSE);
+        g_return_val_if_fail (restriction != NULL, FALSE);
+
+        if (g_strcmp0 (info_set->mime,
+                       gupnp_dlna_native_restriction_get_mime (restriction)))
+                return FALSE;
+
+        unsupported_match = FALSE;
+        g_hash_table_iter_init (&iter,
+                                gupnp_dlna_native_restriction_get_entries
+                                        (restriction));
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GUPnPDLNANativeInfoValue *info_value;
+                GUPnPDLNANativeValueList *value_list;
+                gboolean unsupported;
+
+                if (!g_hash_table_lookup_extended (info_set->entries,
+                                                   key,
+                                                   NULL,
+                                                   (gpointer *) &info_value))
+                        return FALSE;
+                value_list = (GUPnPDLNANativeValueList *) value;
+                if (!gupnp_dlna_native_value_list_is_superset (value_list,
+                                                               info_value,
+                                                               &unsupported))
+                        return FALSE;
+                else if (unsupported)
+                        unsupported_match = TRUE;
+        }
+
+        if (unsupported_match)
+                g_warning ("Info set matched restriction, but it has an "
+                           "unsupported value.");
+
+        return TRUE;
+}
+
+static gboolean
+gupnp_dlna_native_info_set_is_empty (GUPnPDLNANativeInfoSet *info_set)
+{
+        g_return_val_if_fail (info_set != NULL, TRUE);
+
+        return (info_set->mime == NULL &&
+                g_hash_table_size (info_set->entries) == 0);
+}
+
+gchar *
+gupnp_dlna_native_info_set_to_string (GUPnPDLNANativeInfoSet *info_set)
+{
+        GString *str;
+        GHashTableIter iter;
+        gpointer key;
+        gpointer value;
+
+        g_return_val_if_fail (info_set != NULL, NULL);
+
+        if (gupnp_dlna_native_info_set_is_empty (info_set))
+                return g_strdup ("EMPTY");
+
+        str = g_string_new (info_set->mime ? info_set->mime : "(null)");
+        g_hash_table_iter_init (&iter, info_set->entries);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                gchar *raw = gupnp_dlna_native_info_value_to_string (value);
+
+                g_string_append_printf (str, ", %s=%s", (gchar *) key, raw);
+                g_free (raw);
+        }
+
+        return g_string_free (str, FALSE);
+}
+
+const gchar *
+gupnp_dlna_native_info_set_get_mime (GUPnPDLNANativeInfoSet *info_set)
+{
+        g_return_val_if_fail (info_set != NULL, NULL);
+
+        return info_set->mime;
+}
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-set.h b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-set.h
new file mode 100644
index 0000000..5b87ce6
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-set.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_INFO_SET_H__
+#define __GUPNP_DLNA_NATIVE_INFO_SET_H__
+
+#include <glib.h>
+
+#include "gupnp-dlna-native-restriction.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GUPnPDLNANativeInfoSet GUPnPDLNANativeInfoSet;
+
+GUPnPDLNANativeInfoSet *
+gupnp_dlna_native_info_set_new (const gchar *mime);
+
+void
+gupnp_dlna_native_info_set_free (GUPnPDLNANativeInfoSet *info_set);
+
+gboolean
+gupnp_dlna_native_info_set_add_bool (GUPnPDLNANativeInfoSet *info_set,
+                                     const gchar            *name,
+                                     gboolean                value);
+
+gboolean
+gupnp_dlna_native_info_set_add_unsupported_bool
+                                        (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar            *name);
+
+gboolean
+gupnp_dlna_native_info_set_add_fraction (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar            *name,
+                                         gint                    numerator,
+                                         gint                    denominator);
+
+gboolean
+gupnp_dlna_native_info_set_add_unsupported_fraction
+                                        (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar            *name);
+
+gboolean
+gupnp_dlna_native_info_set_add_int (GUPnPDLNANativeInfoSet *info_set,
+                                    const gchar            *name,
+                                    gint                    value);
+
+gboolean
+gupnp_dlna_native_info_set_add_unsupported_int
+                                        (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar            *name);
+
+gboolean
+gupnp_dlna_native_info_set_add_string (GUPnPDLNANativeInfoSet *info_set,
+                                       const gchar            *name,
+                                       const gchar            *value);
+
+gboolean
+gupnp_dlna_native_info_set_add_unsupported_string
+                                        (GUPnPDLNANativeInfoSet *info_set,
+                                         const gchar            *name);
+
+gboolean
+gupnp_dlna_native_info_set_fits_restriction
+                                      (GUPnPDLNANativeInfoSet     *info_set,
+                                       GUPnPDLNANativeRestriction *restriction);
+
+gchar *
+gupnp_dlna_native_info_set_to_string (GUPnPDLNANativeInfoSet *info_set);
+
+const gchar *
+gupnp_dlna_native_info_set_get_mime (GUPnPDLNANativeInfoSet *info_set);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_INFO_SET_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-value.c b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-value.c
new file mode 100644
index 0000000..93f6611
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-value.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h> /* for memset */
+#include "gupnp-dlna-native-info-value.h"
+#include "gupnp-dlna-native-value-type.h"
+#include "gupnp-dlna-native-sets-private.h"
+
+/* private */
+struct _GUPnPDLNANativeInfoValue {
+        GUPnPDLNANativeValueType  *type;
+        GUPnPDLNANativeValueUnion  value;
+        gboolean unsupported;
+};
+
+static GUPnPDLNANativeInfoValue *
+value_new (GUPnPDLNANativeValueType *type,
+           gchar *raw)
+{
+        GUPnPDLNANativeInfoValue *info_value =
+                                        g_slice_new (GUPnPDLNANativeInfoValue);
+
+        info_value->type = type;
+        if (!gupnp_dlna_native_value_type_init (type,
+                                                &info_value->value,
+                                                raw)) {
+                g_slice_free (GUPnPDLNANativeInfoValue, info_value);
+                info_value = NULL;
+        }
+        g_free (raw);
+        info_value->unsupported = FALSE;
+
+        return info_value;
+}
+
+static GUPnPDLNANativeInfoValue *
+value_unsupported (GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeInfoValue *info_value =
+                                        g_slice_new (GUPnPDLNANativeInfoValue);
+
+        info_value->type = type;
+        memset (&info_value->value, 0, sizeof (GUPnPDLNANativeValueUnion));
+        info_value->unsupported = TRUE;
+
+        return info_value;
+}
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_bool (gboolean value)
+{
+        return value_new (gupnp_dlna_native_value_type_bool (),
+                          g_strdup (value ? "true" : "false"));
+}
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_unsupported_bool (void)
+{
+        return value_unsupported (gupnp_dlna_native_value_type_bool ());
+}
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_fraction (gint numerator,
+                                           gint denominator)
+{
+        return value_new (gupnp_dlna_native_value_type_fraction (),
+                          g_strdup_printf ("%d/%d",
+                                           numerator,
+                                           denominator));
+}
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_unsupported_fraction (void)
+{
+        return value_unsupported (gupnp_dlna_native_value_type_fraction ());
+}
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_int (gint value)
+{
+        return value_new (gupnp_dlna_native_value_type_int (),
+                          g_strdup_printf ("%d", value));
+}
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_unsupported_int (void)
+{
+        return value_unsupported (gupnp_dlna_native_value_type_int ());
+}
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_string (const gchar *value)
+{
+        return value_new (gupnp_dlna_native_value_type_string (),
+                          g_strdup (value));
+}
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_unsupported_string (void)
+{
+        return value_unsupported (gupnp_dlna_native_value_type_string ());
+}
+
+void
+gupnp_dlna_native_info_value_free (GUPnPDLNANativeInfoValue *info_value)
+{
+        if (info_value == NULL)
+                return;
+
+        if (!info_value->unsupported)
+                gupnp_dlna_native_value_type_clean (info_value->type,
+                                                    &info_value->value);
+        g_slice_free (GUPnPDLNANativeInfoValue, info_value);
+}
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_info_value_get_type (GUPnPDLNANativeInfoValue *info)
+{
+        g_return_val_if_fail (info != NULL, NULL);
+
+        return info->type;
+}
+
+GUPnPDLNANativeValueUnion *
+gupnp_dlna_native_info_value_get_value (GUPnPDLNANativeInfoValue *info)
+{
+        g_return_val_if_fail (info != NULL, NULL);
+
+        if (info->unsupported)
+                return NULL;
+        else
+                return &info->value;
+}
+
+gchar *
+gupnp_dlna_native_info_value_to_string (GUPnPDLNANativeInfoValue *info)
+{
+        const gchar *type;
+        gchar *raw;
+        gchar *str;
+
+        g_return_val_if_fail (info != NULL, NULL);
+
+        type = gupnp_dlna_native_value_type_name (info->type);
+        if (info->unsupported)
+                raw = g_strdup ("<UNSUPPORTED>");
+        else
+                raw = gupnp_dlna_native_value_type_to_string (info->type,
+                                                              &info->value);
+        str = g_strdup_printf ("(%s)%s", type, raw);
+        g_free (raw);
+
+        return str;
+}
+
+gboolean
+gupnp_dlna_native_info_value_is_unsupported (GUPnPDLNANativeInfoValue *info)
+{
+        g_return_val_if_fail (info != NULL, FALSE);
+
+        return info->unsupported;
+}
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-value.h b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-value.h
new file mode 100644
index 0000000..68b897a
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-info-value.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_INFO_VALUE_H__
+#define __GUPNP_DLNA_NATIVE_INFO_VALUE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GUPnPDLNANativeInfoValue GUPnPDLNANativeInfoValue;
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_bool (gboolean value);
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_unsupported_bool (void);
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_fraction (gint numerator,
+                                           gint denominator);
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_unsupported_fraction (void);
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_int (gint value);
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_unsupported_int (void);
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_string (const gchar *value);
+
+GUPnPDLNANativeInfoValue *
+gupnp_dlna_native_info_value_new_unsupported_string (void);
+
+void
+gupnp_dlna_native_info_value_free (GUPnPDLNANativeInfoValue *info_value);
+
+gchar *
+gupnp_dlna_native_info_value_to_string (GUPnPDLNANativeInfoValue *info_value);
+
+gboolean
+gupnp_dlna_native_info_value_is_unsupported (GUPnPDLNANativeInfoValue *info);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_INFO_VALUE_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-restriction.c b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-restriction.c
new file mode 100644
index 0000000..a565b3d
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-restriction.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+
+#include "gupnp-dlna-native-restriction.h"
+#include "gupnp-dlna-native-value-list.h"
+#include "gupnp-dlna-native-sets-private.h"
+
+struct _GUPnPDLNANativeRestriction {
+        gchar *mime;
+        GHashTable *entries; /* <gchar *, GUPnPDLNANativeValueList *> */
+};
+
+GUPnPDLNANativeRestriction *
+gupnp_dlna_native_restriction_new (const gchar *mime)
+{
+        GUPnPDLNANativeRestriction *restriction =
+                                       g_slice_new (GUPnPDLNANativeRestriction);
+
+        restriction->mime = g_strdup (mime);
+        restriction->entries = g_hash_table_new_full
+                           (g_str_hash,
+                            g_str_equal,
+                            g_free,
+                            (GDestroyNotify) gupnp_dlna_native_value_list_free);
+
+        return restriction;
+}
+
+GUPnPDLNANativeRestriction *
+gupnp_dlna_native_restriction_copy (GUPnPDLNANativeRestriction *restriction)
+{
+        GUPnPDLNANativeRestriction *dup;
+        GHashTableIter iter;
+        gpointer key;
+        gpointer value;
+
+        g_return_val_if_fail (restriction != NULL, NULL);
+
+        dup = gupnp_dlna_native_restriction_new (restriction->mime);
+        g_hash_table_iter_init (&iter, restriction->entries);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GUPnPDLNANativeValueList * dup_entry;
+
+                if (key == NULL || value == NULL)
+                        continue;
+                dup_entry = gupnp_dlna_native_value_list_copy (value);
+
+                if (dup_entry == NULL)
+                        continue;
+                g_hash_table_insert (dup->entries, g_strdup (key), dup_entry);
+        }
+
+        return dup;
+}
+
+void
+gupnp_dlna_native_restriction_free (GUPnPDLNANativeRestriction *restriction)
+{
+        if (restriction == NULL)
+                return;
+        g_free (restriction->mime);
+        g_hash_table_unref (restriction->entries);
+        g_slice_free (GUPnPDLNANativeRestriction, restriction);
+}
+
+gboolean
+gupnp_dlna_native_restriction_add_value_list
+                                       (GUPnPDLNANativeRestriction *restriction,
+                                        const gchar                *name,
+                                        GUPnPDLNANativeValueList   *list)
+{
+        g_return_val_if_fail (restriction != NULL, FALSE);
+        g_return_val_if_fail (name != NULL, FALSE);
+        g_return_val_if_fail (list != NULL, FALSE);
+
+        if (gupnp_dlna_native_value_list_is_empty (list))
+                return FALSE;
+        if (g_hash_table_contains (restriction->entries, name))
+                return FALSE;
+        gupnp_dlna_native_value_list_sort_items (list);
+        g_hash_table_insert (restriction->entries, g_strdup (name), list);
+
+        return TRUE;
+}
+
+static gboolean
+check_merge_possibility (GUPnPDLNANativeRestriction *restriction,
+                         GUPnPDLNANativeRestriction *merged)
+{
+        GHashTableIter iter;
+        gpointer mrg_name_ptr;
+        gpointer mrg_value_list_ptr;
+
+        g_hash_table_iter_init (&iter, merged->entries);
+        while (g_hash_table_iter_next (&iter,
+                                       &mrg_name_ptr,
+                                       &mrg_value_list_ptr)) {
+                gpointer value_list_ptr;
+
+                if (g_hash_table_lookup_extended (restriction->entries,
+                                                  mrg_name_ptr,
+                                                  NULL,
+                                                  &value_list_ptr)) {
+                        GUPnPDLNANativeValueList *value_list =
+                                    (GUPnPDLNANativeValueList *) value_list_ptr;
+                        GUPnPDLNANativeValueList *mrg_value_list =
+                                (GUPnPDLNANativeValueList *) mrg_value_list_ptr;
+
+                        if (!gupnp_dlna_native_value_list_mergeable
+                                        (value_list,
+                                         mrg_value_list))
+                                return FALSE;
+                }
+        }
+
+        return TRUE;
+}
+
+gboolean
+gupnp_dlna_native_restriction_merge
+                        (GUPnPDLNANativeRestriction                *restriction,
+                         GUPnPDLNANativeRestriction                *merged,
+                         GUPnPDLNANativeRestrictionMergeResolution  resolution)
+{
+        GHashTableIter iter;
+        gpointer mrg_name_ptr;
+        gpointer mrg_value_list_ptr;
+        gboolean change_mime;
+
+        g_return_val_if_fail (restriction != NULL, FALSE);
+        g_return_val_if_fail (merged != NULL, FALSE);
+
+        switch (resolution) {
+        case GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_FROM_TARGET:
+                change_mime = (restriction->mime == NULL);
+
+                break;
+        case GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_FROM_SOURCE:
+                change_mime = (merged->mime != NULL);
+
+                break;
+        case GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_NONE:
+                change_mime = (restriction->mime == NULL &&
+                               merged->mime != NULL);
+
+                break;
+        default:
+                change_mime = FALSE;
+                g_critical ("Unknown conflict resolution: %d", resolution);
+        }
+        if (change_mime) {
+                g_free (restriction->mime);
+                restriction->mime = merged->mime;
+                merged->mime = NULL;
+        }
+
+        if (resolution == GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_NONE &&
+            !check_merge_possibility (restriction, merged))
+                return FALSE;
+
+        g_hash_table_iter_init (&iter, merged->entries);
+        while (g_hash_table_iter_next (&iter,
+                                       &mrg_name_ptr,
+                                       &mrg_value_list_ptr)) {
+                gpointer value_list_ptr;
+
+                if (g_hash_table_lookup_extended (restriction->entries,
+                                                  mrg_name_ptr,
+                                                  NULL,
+                                                  &value_list_ptr)) {
+                        GUPnPDLNANativeValueList *value_list =
+                                    (GUPnPDLNANativeValueList *) value_list_ptr;
+                        GUPnPDLNANativeValueList *mrg_value_list =
+                                (GUPnPDLNANativeValueList *) mrg_value_list_ptr;
+
+                        gupnp_dlna_native_value_list_merge (value_list,
+                                                            mrg_value_list,
+                                                            resolution);
+                } else {
+                        g_hash_table_iter_steal (&iter);
+                        g_hash_table_insert (restriction->entries,
+                                             mrg_name_ptr,
+                                             mrg_value_list_ptr);
+                }
+        }
+        gupnp_dlna_native_restriction_free (merged);
+
+        return TRUE;
+}
+
+gboolean
+gupnp_dlna_native_restriction_is_empty (GUPnPDLNANativeRestriction *restriction)
+{
+        g_return_val_if_fail (restriction != NULL, TRUE);
+
+        return (restriction->mime == NULL &&
+                g_hash_table_size (restriction->entries) == 0);
+}
+
+gchar *
+gupnp_dlna_native_restriction_to_string
+                                       (GUPnPDLNANativeRestriction *restriction)
+{
+        GString *str;
+        GHashTableIter iter;
+        gpointer key;
+        gpointer value;
+
+        g_return_val_if_fail (restriction != NULL, NULL);
+
+        if (gupnp_dlna_native_restriction_is_empty (restriction))
+                return g_strdup ("EMPTY");
+
+        str = g_string_new (restriction->mime ? restriction->mime : "(null)");
+        g_hash_table_iter_init (&iter, restriction->entries);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                gchar *raw = gupnp_dlna_native_value_list_to_string (value);
+
+                g_string_append_printf (str, ", %s=%s", (gchar *) key, raw);
+                g_free (raw);
+        }
+
+        return g_string_free (str, FALSE);
+}
+
+const gchar *
+gupnp_dlna_native_restriction_get_mime (GUPnPDLNANativeRestriction *restriction)
+{
+        g_return_val_if_fail (restriction != NULL, NULL);
+
+        return restriction->mime;
+}
+
+GHashTable *
+gupnp_dlna_native_restriction_get_entries
+                                       (GUPnPDLNANativeRestriction *restriction)
+{
+        g_return_val_if_fail (restriction != NULL, NULL);
+
+        return restriction->entries;
+}
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-restriction.h b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-restriction.h
new file mode 100644
index 0000000..63bdeca
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-restriction.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_RESTRICTION_H__
+#define __GUPNP_DLNA_NATIVE_RESTRICTION_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include "gupnp-dlna-native-value-list.h"
+
+G_BEGIN_DECLS
+
+typedef enum {
+        GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_FROM_TARGET,
+        GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_FROM_SOURCE,
+        GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_NONE
+} GUPnPDLNANativeRestrictionMergeResolution;
+
+typedef struct _GUPnPDLNANativeRestriction GUPnPDLNANativeRestriction;
+
+#define GUPNP_DLNA_NATIVE_RESTRICTION(x) \
+        ((GUPnPDLNANativeRestriction *) x)
+
+GUPnPDLNANativeRestriction *
+gupnp_dlna_native_restriction_new (const gchar *mime);
+
+GUPnPDLNANativeRestriction *
+gupnp_dlna_native_restriction_copy (GUPnPDLNANativeRestriction *restriction);
+
+void
+gupnp_dlna_native_restriction_free (GUPnPDLNANativeRestriction *restriction);
+
+gboolean
+gupnp_dlna_native_restriction_add_value_list
+                                       (GUPnPDLNANativeRestriction *restriction,
+                                        const gchar                *name,
+                                        GUPnPDLNANativeValueList   *list);
+
+gboolean
+gupnp_dlna_native_restriction_merge
+                        (GUPnPDLNANativeRestriction                *restriction,
+                         GUPnPDLNANativeRestriction                *merged,
+                         GUPnPDLNANativeRestrictionMergeResolution  override);
+
+gboolean
+gupnp_dlna_native_restriction_is_empty
+                                      (GUPnPDLNANativeRestriction *restriction);
+
+gchar *
+gupnp_dlna_native_restriction_to_string
+                                      (GUPnPDLNANativeRestriction *restriction);
+
+const gchar *
+gupnp_dlna_native_restriction_get_mime
+                                      (GUPnPDLNANativeRestriction *restriction);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_RESTRICTION_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-sets-private.h b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-sets-private.h
new file mode 100644
index 0000000..f45f9bd
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-sets-private.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_SETS_PRIVATE_H__
+#define __GUPNP_DLNA_NATIVE_SETS_PRIVATE_H__
+
+#include <glib.h>
+#include "gupnp-dlna-native-value-type.h"
+#include "gupnp-dlna-native-value-list.h"
+#include "gupnp-dlna-native-info-value.h"
+#include "gupnp-dlna-native-restriction.h"
+
+G_BEGIN_DECLS
+
+/* private */
+typedef union _GUPnPDLNANativeValueUnion GUPnPDLNANativeValueUnion;
+typedef struct _GUPnPDLNANativeFraction GUPnPDLNANativeFraction;
+
+struct _GUPnPDLNANativeFraction {
+        gint numerator;
+        gint denominator;
+};
+
+union _GUPnPDLNANativeValueUnion {
+        gboolean bool_value;
+        GUPnPDLNANativeFraction fraction_value;
+        gint int_value;
+        gchar *string_value;
+};
+
+/* ValueType */
+gboolean
+gupnp_dlna_native_value_type_init (GUPnPDLNANativeValueType  *type,
+                                   GUPnPDLNANativeValueUnion *value,
+                                   const gchar               *raw);
+
+gboolean
+gupnp_dlna_native_value_type_copy (GUPnPDLNANativeValueType  *type,
+                                   GUPnPDLNANativeValueUnion *from,
+                                   GUPnPDLNANativeValueUnion *to);
+
+void
+gupnp_dlna_native_value_type_clean (GUPnPDLNANativeValueType  *type,
+                                    GUPnPDLNANativeValueUnion *value_union);
+
+gboolean
+gupnp_dlna_native_value_type_is_equal (GUPnPDLNANativeValueType  *type,
+                                       GUPnPDLNANativeValueUnion *first,
+                                       GUPnPDLNANativeValueUnion *second);
+
+gboolean
+gupnp_dlna_native_value_type_is_in_range (GUPnPDLNANativeValueType  *type,
+                                          GUPnPDLNANativeValueUnion *min,
+                                          GUPnPDLNANativeValueUnion *max,
+                                          GUPnPDLNANativeValueUnion *value);
+
+const gchar *
+gupnp_dlna_native_value_type_name (GUPnPDLNANativeValueType *type);
+
+gboolean
+gupnp_dlna_native_value_type_verify_range (GUPnPDLNANativeValueType  *type,
+                                           GUPnPDLNANativeValueUnion *min,
+                                           GUPnPDLNANativeValueUnion *max);
+
+gchar *
+gupnp_dlna_native_value_type_to_string (GUPnPDLNANativeValueType  *type,
+                                        GUPnPDLNANativeValueUnion *value);
+
+gint
+gupnp_dlna_native_value_type_compare (GUPnPDLNANativeValueType  *type,
+                                      GUPnPDLNANativeValueUnion *a,
+                                      GUPnPDLNANativeValueUnion *b);
+
+/* ValueList */
+GUPnPDLNANativeValueList *
+gupnp_dlna_native_value_list_copy (GUPnPDLNANativeValueList *list);
+
+gboolean
+gupnp_dlna_native_value_list_is_superset
+                                        (GUPnPDLNANativeValueList *list,
+                                         GUPnPDLNANativeInfoValue *value,
+                                         gboolean                 *unsupported);
+
+void
+gupnp_dlna_native_value_list_merge
+                     (GUPnPDLNANativeValueList                  *value_list,
+                      GUPnPDLNANativeValueList                  *mrg_value_list,
+                      GUPnPDLNANativeRestrictionMergeResolution  resolution);
+
+gboolean
+gupnp_dlna_native_value_list_is_empty (GUPnPDLNANativeValueList *value_list);
+
+GList *
+gupnp_dlna_native_value_list_get_list (GUPnPDLNANativeValueList *value_list);
+
+gboolean
+gupnp_dlna_native_value_list_mergeable
+                                     (GUPnPDLNANativeValueList *value_list,
+                                      GUPnPDLNANativeValueList *mrg_value_list);
+
+gchar *
+gupnp_dlna_native_value_list_to_string (GUPnPDLNANativeValueList *value_list);
+
+void
+gupnp_dlna_native_value_list_sort_items (GUPnPDLNANativeValueList *value_list);
+
+/* InfoValue */
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_info_value_get_type (GUPnPDLNANativeInfoValue *info);
+
+GUPnPDLNANativeValueUnion *
+gupnp_dlna_native_info_value_get_value (GUPnPDLNANativeInfoValue *info);
+
+/* Restriction */
+GHashTable *
+gupnp_dlna_native_restriction_get_entries
+                                      (GUPnPDLNANativeRestriction *restriction);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_SETS_PRIVATE_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-list.c b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-list.c
new file mode 100644
index 0000000..aa412c1
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-list.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "gupnp-dlna-native-value-list.h"
+#include "gupnp-dlna-native-value.h"
+#include "gupnp-dlna-native-sets-private.h"
+
+struct _GUPnPDLNANativeValueList {
+        GUPnPDLNANativeValueType *type;
+        GList                    *values; /* <GUPnPDLNANativeValue *> */
+        gboolean                  sorted;
+};
+
+GUPnPDLNANativeValueList *
+gupnp_dlna_native_value_list_new (GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeValueList *list;
+
+        g_return_val_if_fail (type != NULL, NULL);
+
+        list = g_slice_new (GUPnPDLNANativeValueList);
+        list->type = type;
+        list->values = NULL;
+        list->sorted = FALSE;
+
+        return list;
+}
+
+static void
+free_value (GUPnPDLNANativeValue     *value,
+            GUPnPDLNANativeValueType *type)
+{
+        gupnp_dlna_native_value_free (value, type);
+}
+
+static void
+free_value_list (GUPnPDLNANativeValueList *list)
+{
+        if (list->values) {
+                g_list_foreach (list->values,
+                                (GFunc) free_value,
+                                list->type);
+                g_list_free (list->values);
+                list->values = NULL;
+        }
+}
+
+void
+gupnp_dlna_native_value_list_free (GUPnPDLNANativeValueList *list)
+{
+        if (!list)
+                return;
+
+        free_value_list (list);
+        g_slice_free (GUPnPDLNANativeValueList, list);
+}
+
+static gint
+value_compare (GUPnPDLNANativeValue     *a,
+               GUPnPDLNANativeValue     *b,
+               GUPnPDLNANativeValueType *type)
+{
+        return gupnp_dlna_native_value_compare (a, b, type);
+}
+
+static gboolean
+insert_value (GUPnPDLNANativeValueList *list,
+              GUPnPDLNANativeValue *value)
+{
+        if (value) {
+                if (list->sorted)
+                        list->values = g_list_insert_sorted_with_data
+                                        (list->values,
+                                         value,
+                                         (GCompareDataFunc) value_compare,
+                                         list->type);
+                else
+                        list->values = g_list_prepend (list->values, value);
+                return TRUE;
+        }
+
+        return FALSE;
+}
+
+gboolean
+gupnp_dlna_native_value_list_add_single (GUPnPDLNANativeValueList *list,
+                                         const gchar *single)
+{
+        GUPnPDLNANativeValue *value;
+
+        g_return_val_if_fail (list != NULL, FALSE);
+        g_return_val_if_fail (single != NULL, FALSE);
+
+        value = gupnp_dlna_native_value_new_single (list->type, single);
+
+        return insert_value (list, value);
+}
+
+gboolean
+gupnp_dlna_native_value_list_add_range (GUPnPDLNANativeValueList *list,
+                                        const gchar *min,
+                                        const gchar *max)
+{
+        GUPnPDLNANativeValue *range;
+
+        g_return_val_if_fail (list != NULL, FALSE);
+        g_return_val_if_fail (min != NULL, FALSE);
+        g_return_val_if_fail (max != NULL, FALSE);
+
+        range = gupnp_dlna_native_value_new_ranged (list->type, min, max);
+
+        if (range) {
+                list->values = g_list_prepend (list->values, range);
+                return TRUE;
+        }
+
+        return FALSE;
+}
+
+/* private */
+GUPnPDLNANativeValueList *
+gupnp_dlna_native_value_list_copy (GUPnPDLNANativeValueList *list)
+{
+        GUPnPDLNANativeValueList *dup;
+
+        if (list) {
+                GList *iter;
+
+                dup = gupnp_dlna_native_value_list_new (list->type);
+                for (iter = list->values; iter != NULL; iter = iter->next) {
+                        GUPnPDLNANativeValue *base =
+                                        (GUPnPDLNANativeValue *) iter->data;
+                        GUPnPDLNANativeValue *copy;
+
+                        if (base == NULL)
+                                continue;
+
+                        copy = gupnp_dlna_native_value_copy (base, list->type);
+                        if (copy != NULL)
+                                dup->values = g_list_prepend (dup->values,
+                                                              copy);
+                }
+                dup->values = g_list_reverse (dup->values);
+        } else {
+                dup = NULL;
+        }
+
+        return dup;
+}
+
+gboolean
+gupnp_dlna_native_value_list_is_superset (GUPnPDLNANativeValueList *list,
+                                          GUPnPDLNANativeInfoValue *value,
+                                          gboolean                 *unsupported)
+{
+        GList *iter;
+
+        g_return_val_if_fail (list != NULL, FALSE);
+        g_return_val_if_fail (value != NULL, FALSE);
+        g_return_val_if_fail (unsupported != NULL, FALSE);
+
+        if (list->type != gupnp_dlna_native_info_value_get_type (value))
+                return FALSE;
+
+        if (gupnp_dlna_native_info_value_is_unsupported (value)) {
+                *unsupported = TRUE;
+
+                return TRUE;
+        }
+
+        for (iter = list->values; iter != NULL; iter = iter->next) {
+                GUPnPDLNANativeValue *base =
+                                            (GUPnPDLNANativeValue *) iter->data;
+
+                if (gupnp_dlna_native_value_is_superset (base, value)) {
+                        *unsupported = FALSE;
+
+                        return TRUE;
+                }
+        }
+
+        return FALSE;
+}
+
+gboolean
+gupnp_dlna_native_value_list_mergeable
+                                      (GUPnPDLNANativeValueList *value_list,
+                                       GUPnPDLNANativeValueList *mrg_value_list)
+{
+        if (value_list->type != mrg_value_list->type) {
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+void
+gupnp_dlna_native_value_list_merge
+                     (GUPnPDLNANativeValueList                  *value_list,
+                      GUPnPDLNANativeValueList                  *mrg_value_list,
+                      GUPnPDLNANativeRestrictionMergeResolution  resolution)
+{
+        g_return_if_fail (value_list != NULL);
+        g_return_if_fail (mrg_value_list != NULL);
+
+        switch (resolution) {
+        case GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_FROM_TARGET:
+                /* do nothing */
+                break;
+        case GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_FROM_SOURCE:
+                free_value_list (value_list);
+                value_list->values = mrg_value_list->values;
+                value_list->type = mrg_value_list->type;
+                mrg_value_list->values = NULL;
+        case GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_NONE:
+                if (!gupnp_dlna_native_value_list_mergeable (value_list,
+                                                             mrg_value_list)) {
+                        g_critical ("Tried to merge values of type '%s' into "
+                                    "values of type '%s'.",
+                                    gupnp_dlna_native_value_type_name
+                                        (mrg_value_list->type),
+                                    gupnp_dlna_native_value_type_name
+                                        (value_list->type));
+
+                        return;
+                }
+                value_list->values = g_list_concat (value_list->values,
+                                                    mrg_value_list->values);
+                mrg_value_list->values = NULL;
+
+                break;
+        default:
+                g_critical ("Unknown conflict resolution: %d", resolution);
+        }
+}
+
+gboolean
+gupnp_dlna_native_value_list_is_empty (GUPnPDLNANativeValueList *value_list)
+{
+        g_return_val_if_fail (value_list != NULL, TRUE);
+
+        return (value_list->values == NULL);
+}
+
+GList *
+gupnp_dlna_native_value_list_get_list (GUPnPDLNANativeValueList *value_list)
+{
+        g_return_val_if_fail (value_list != NULL, NULL);
+
+        return value_list->values;
+}
+
+static gchar *
+list_to_string (GUPnPDLNANativeValueList *value_list)
+{
+        GList *iter;
+        GPtrArray* strings = g_ptr_array_new_with_free_func (g_free);
+        gchar *str;
+
+        for (iter = value_list->values; iter != NULL; iter = iter->next) {
+                GUPnPDLNANativeValue *value =
+                                            (GUPnPDLNANativeValue *) iter->data;
+
+                g_ptr_array_add (strings,
+                                 gupnp_dlna_native_value_to_string
+                                        (value,
+                                         value_list->type));
+        }
+        g_ptr_array_add (strings, NULL);
+
+        str = g_strjoinv (", ", (gchar **) strings->pdata);
+        g_ptr_array_unref (strings);
+
+        return str;
+}
+
+gchar *
+gupnp_dlna_native_value_list_to_string (GUPnPDLNANativeValueList *value_list)
+{
+        GString *str;
+        gchar *val_str;
+
+        g_return_val_if_fail (value_list != NULL, NULL);
+
+        if (value_list->values == NULL)
+                return g_strdup ("");
+
+        str = g_string_new (NULL);
+        g_string_append_printf (str,
+                                "(%s)",
+                                gupnp_dlna_native_value_type_name
+                                        (value_list->type));
+        if (value_list->values->next != NULL) {
+                g_string_append (str, "{ ");
+                val_str = list_to_string (value_list);
+                g_string_append (str, val_str);
+                g_string_append (str, " }");
+        } else {
+                val_str = list_to_string (value_list);
+                g_string_append (str, val_str);
+        }
+        g_free (val_str);
+
+        return g_string_free (str, FALSE);
+}
+
+void
+gupnp_dlna_native_value_list_sort_items (GUPnPDLNANativeValueList *value_list)
+{
+        g_return_if_fail (value_list != NULL);
+
+        if (!value_list->sorted) {
+                value_list->values = g_list_sort_with_data
+                                        (value_list->values,
+                                         (GCompareDataFunc) value_compare,
+                                         value_list->type);
+                value_list->sorted = TRUE;
+        }
+}
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-list.h b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-list.h
new file mode 100644
index 0000000..8922375
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-list.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_VALUE_LIST_H__
+#define __GUPNP_DLNA_NATIVE_VALUE_LIST_H__
+
+#include <glib.h>
+
+#include "gupnp-dlna-native-value-type.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GUPnPDLNANativeValueList GUPnPDLNANativeValueList;
+
+GUPnPDLNANativeValueList *
+gupnp_dlna_native_value_list_new (GUPnPDLNANativeValueType *type);
+
+void
+gupnp_dlna_native_value_list_free (GUPnPDLNANativeValueList *list);
+
+gboolean
+gupnp_dlna_native_value_list_add_range (GUPnPDLNANativeValueList *list,
+                                        const gchar *min,
+                                        const gchar *max);
+
+gboolean
+gupnp_dlna_native_value_list_add_single (GUPnPDLNANativeValueList *list,
+                                         const gchar *single);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_VALUE_LIST_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-type.c b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-type.c
new file mode 100644
index 0000000..62842db
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-type.c
@@ -0,0 +1,686 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include "gupnp-dlna-native-value-type.h"
+#include "gupnp-dlna-native-sets-private.h"
+
+struct _GUPnPDLNANativeValueType {
+        gboolean
+        (* init) (GUPnPDLNANativeValueType  *type,
+                  GUPnPDLNANativeValueUnion *value,
+                  const gchar               *raw);
+
+        gboolean
+        (* copy) (GUPnPDLNANativeValueType  *type,
+                  GUPnPDLNANativeValueUnion *from,
+                  GUPnPDLNANativeValueUnion *to);
+
+        void
+        (* clean) (GUPnPDLNANativeValueType  *type,
+                   GUPnPDLNANativeValueUnion *value_union);
+
+        gboolean
+        (* is_equal) (GUPnPDLNANativeValueType  *type,
+                      GUPnPDLNANativeValueUnion *first,
+                      GUPnPDLNANativeValueUnion *second);
+
+        gboolean
+        (* is_in_range) (GUPnPDLNANativeValueType  *type,
+                         GUPnPDLNANativeValueUnion *min,
+                         GUPnPDLNANativeValueUnion *max,
+                         GUPnPDLNANativeValueUnion *value);
+
+        const gchar *
+        (* name) (GUPnPDLNANativeValueType *type);
+
+        gboolean
+        (* verify_range) (GUPnPDLNANativeValueType  *type,
+                          GUPnPDLNANativeValueUnion *min,
+                          GUPnPDLNANativeValueUnion *max);
+
+        gchar *
+        (* to_string) (GUPnPDLNANativeValueType  *type,
+                       GUPnPDLNANativeValueUnion *value);
+
+        gint
+        (* compare) (GUPnPDLNANativeValueType  *type,
+                     GUPnPDLNANativeValueUnion *a,
+                     GUPnPDLNANativeValueUnion *b);
+};
+
+/* utils */
+static gboolean
+get_int (const gchar *raw,
+         gint        *store)
+{
+        char *end;
+        long num;
+
+        g_return_val_if_fail (store != NULL, FALSE);
+
+        end = NULL;
+        num = strtol (raw, &end, 10);
+        if (*end != '\0')
+                return FALSE;
+        *store = (gint) num;
+
+        return TRUE;
+}
+
+/* TODO: replace it with better implementation */
+static void
+equalize_denominators (GUPnPDLNANativeFraction *first,
+                       GUPnPDLNANativeFraction *second)
+{
+        gint common;
+
+        if (first->denominator == second->denominator)
+                return;
+
+        common = first->denominator * second->denominator;
+        first->numerator *= second->denominator;
+        second->numerator *= first->denominator;
+        first->denominator = common;
+        second->denominator = common;
+}
+
+static gboolean
+fraction_equal (GUPnPDLNANativeFraction first,
+                GUPnPDLNANativeFraction second)
+{
+        equalize_denominators (&first, &second);
+
+        return first.numerator == second.numerator;
+}
+
+static gboolean
+fraction_in_range (GUPnPDLNANativeFraction min,
+                   GUPnPDLNANativeFraction max,
+                   GUPnPDLNANativeFraction value)
+{
+        GUPnPDLNANativeFraction value_dup = value;
+
+        equalize_denominators (&min, &value);
+        if (min.numerator > value.numerator)
+                return FALSE;
+        equalize_denominators (&max, &value_dup);
+        if (max.numerator < value_dup.numerator)
+                return FALSE;
+
+        return TRUE;
+}
+
+static gint
+int_comparison (gint a,
+                gint b)
+{
+        if (a > b)
+                return 1;
+        else if (a < b)
+                return -1;
+
+        return 0;
+}
+
+static gint
+fraction_comparison (GUPnPDLNANativeFraction a,
+                     GUPnPDLNANativeFraction b)
+{
+        equalize_denominators (&a, &b);
+
+        return int_comparison (a.numerator, b.numerator);
+}
+
+static gboolean
+fraction_range_valid (GUPnPDLNANativeFraction min,
+                      GUPnPDLNANativeFraction max)
+{
+        equalize_denominators (&min, &max);
+
+        return (min.numerator <= max.numerator);
+}
+
+/* bool */
+static gboolean
+bool_init (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+           GUPnPDLNANativeValueUnion *value,
+           const gchar               *raw)
+{
+        if (!g_strcmp0 (raw, "true"))
+                value->bool_value = TRUE;
+        else if (!g_strcmp0 (raw, "false"))
+                value->bool_value = FALSE;
+        else
+                return FALSE;
+
+        return TRUE;
+}
+
+static gboolean
+bool_copy (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+           GUPnPDLNANativeValueUnion *from,
+           GUPnPDLNANativeValueUnion *to)
+{
+        to->bool_value = from->bool_value;
+
+        return TRUE;
+}
+
+static void
+bool_clean (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+            GUPnPDLNANativeValueUnion *value_union G_GNUC_UNUSED)
+{
+
+}
+
+static gboolean
+bool_is_equal (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+               GUPnPDLNANativeValueUnion *first,
+               GUPnPDLNANativeValueUnion *second)
+{
+        return !!first->bool_value == !!second->bool_value;
+}
+
+static gboolean
+bool_is_in_range (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                  GUPnPDLNANativeValueUnion *min G_GNUC_UNUSED,
+                  GUPnPDLNANativeValueUnion *max G_GNUC_UNUSED,
+                  GUPnPDLNANativeValueUnion *value G_GNUC_UNUSED)
+{
+        /* boolean range? */
+        return FALSE;
+}
+
+static const gchar *
+bool_name (GUPnPDLNANativeValueType *type G_GNUC_UNUSED)
+{
+        return "boolean";
+}
+
+static gboolean
+bool_verify_range (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                   GUPnPDLNANativeValueUnion *min G_GNUC_UNUSED,
+                   GUPnPDLNANativeValueUnion *max G_GNUC_UNUSED)
+{
+        return FALSE;
+}
+
+static gchar *
+bool_to_string (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                GUPnPDLNANativeValueUnion *value)
+{
+        return g_strdup (value->bool_value ? "true" : "false");
+}
+
+gint
+bool_compare (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+              GUPnPDLNANativeValueUnion *a,
+              GUPnPDLNANativeValueUnion *b)
+{
+        if ((a->bool_value && b->bool_value) ||
+            (!a->bool_value && !b->bool_value))
+                return 0;
+        else if (a->bool_value)
+                return 1;
+        else
+                return -1;
+}
+
+static GUPnPDLNANativeValueType bool_type_impl = {
+        bool_init,
+        bool_copy,
+        bool_clean,
+        bool_is_equal,
+        bool_is_in_range,
+        bool_name,
+        bool_verify_range,
+        bool_to_string,
+        bool_compare
+};
+
+/* fraction */
+static gboolean
+fraction_init (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+               GUPnPDLNANativeValueUnion *value,
+               const gchar               *raw)
+{
+        gchar **tokens = g_strsplit (raw, "/", 2);
+        gboolean result = FALSE;
+        gint numerator;
+        gint denominator;
+
+        if (g_strv_length (tokens) != 2)
+                goto out;
+
+        if (!get_int (tokens[0], &numerator) ||
+            !get_int (tokens[1], &denominator))
+                goto out;
+
+        if (!denominator)
+                goto out;
+
+        value->fraction_value.numerator = numerator;
+        value->fraction_value.denominator = denominator;
+        result = TRUE;
+ out:
+        g_strfreev (tokens);
+
+        return result;
+}
+
+static gboolean
+fraction_copy (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+               GUPnPDLNANativeValueUnion *from,
+               GUPnPDLNANativeValueUnion *to)
+{
+        to->fraction_value = from->fraction_value;
+
+        return TRUE;
+}
+
+static void
+fraction_clean (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                GUPnPDLNANativeValueUnion *value_union G_GNUC_UNUSED)
+{
+
+}
+
+static gboolean
+fraction_is_equal (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                   GUPnPDLNANativeValueUnion *first,
+                   GUPnPDLNANativeValueUnion *second)
+{
+        return fraction_equal (first->fraction_value,
+                               second->fraction_value);
+}
+
+static gboolean
+fraction_is_in_range (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                      GUPnPDLNANativeValueUnion *min,
+                      GUPnPDLNANativeValueUnion *max,
+                      GUPnPDLNANativeValueUnion *value)
+{
+        /* fraction range? */
+        return fraction_in_range (min->fraction_value,
+                                  max->fraction_value,
+                                  value->fraction_value);
+}
+
+static const gchar *
+fraction_name (GUPnPDLNANativeValueType *type G_GNUC_UNUSED)
+{
+        return "fraction";
+}
+
+static gboolean
+fraction_verify_range (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                       GUPnPDLNANativeValueUnion *min,
+                       GUPnPDLNANativeValueUnion *max)
+{
+        return fraction_range_valid (min->fraction_value, max->fraction_value);
+}
+
+static gchar *
+fraction_to_string (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                    GUPnPDLNANativeValueUnion *value)
+{
+        return g_strdup_printf ("%d/%d",
+                                value->fraction_value.numerator,
+                                value->fraction_value.denominator);
+}
+
+gint
+fraction_compare (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                  GUPnPDLNANativeValueUnion *a,
+                  GUPnPDLNANativeValueUnion *b)
+{
+        return fraction_comparison (a->fraction_value, b->fraction_value);
+}
+
+static GUPnPDLNANativeValueType fraction_type_impl = {
+        fraction_init,
+        fraction_copy,
+        fraction_clean,
+        fraction_is_equal,
+        fraction_is_in_range,
+        fraction_name,
+        fraction_verify_range,
+        fraction_to_string,
+        fraction_compare
+};
+
+/* int */
+static gboolean
+int_init (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+          GUPnPDLNANativeValueUnion *value,
+          const gchar               *raw)
+{
+        gint num;
+
+        if (get_int (raw, &num)) {
+                value->int_value = num;
+                return TRUE;
+        }
+
+        return FALSE;
+}
+
+static gboolean
+int_copy (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+          GUPnPDLNANativeValueUnion *from,
+          GUPnPDLNANativeValueUnion *to)
+{
+        to->int_value = from->int_value;
+
+        return TRUE;
+}
+
+static void
+int_clean (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+           GUPnPDLNANativeValueUnion *value_union G_GNUC_UNUSED)
+{
+
+}
+
+static gboolean
+int_is_equal (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+              GUPnPDLNANativeValueUnion *first,
+              GUPnPDLNANativeValueUnion *second)
+{
+        return first->int_value == second->int_value;
+}
+
+static gboolean
+int_is_in_range (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                 GUPnPDLNANativeValueUnion *min,
+                 GUPnPDLNANativeValueUnion *max,
+                 GUPnPDLNANativeValueUnion *value)
+{
+        return (min->int_value <= value->int_value &&
+                max->int_value >= value->int_value);
+}
+
+static const gchar *
+int_name (GUPnPDLNANativeValueType *type G_GNUC_UNUSED)
+{
+        return "int";
+}
+
+static gboolean
+int_verify_range (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                  GUPnPDLNANativeValueUnion *min,
+                  GUPnPDLNANativeValueUnion *max)
+{
+        return (min->int_value <= max->int_value);
+}
+
+static gchar *
+int_to_string (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+               GUPnPDLNANativeValueUnion *value)
+{
+        return g_strdup_printf ("%d", value->int_value);
+}
+
+gint
+int_compare (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+             GUPnPDLNANativeValueUnion *a,
+             GUPnPDLNANativeValueUnion *b)
+{
+        return int_comparison (a->int_value, b->int_value);
+}
+
+static GUPnPDLNANativeValueType int_type_impl = {
+        int_init,
+        int_copy,
+        int_clean,
+        int_is_equal,
+        int_is_in_range,
+        int_name,
+        int_verify_range,
+        int_to_string,
+        int_compare
+};
+
+/* string */
+static gboolean
+string_init (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+             GUPnPDLNANativeValueUnion *value,
+             const gchar               *raw)
+{
+        value->string_value = g_strdup (raw);
+
+        return TRUE;
+}
+
+static gboolean
+string_copy (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+             GUPnPDLNANativeValueUnion *from,
+             GUPnPDLNANativeValueUnion *to)
+{
+        to->string_value = g_strdup (from->string_value);
+
+        return TRUE;
+}
+
+static void
+string_clean (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+              GUPnPDLNANativeValueUnion *value_union)
+{
+        g_free (value_union->string_value);
+}
+
+static gboolean
+string_is_equal (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                 GUPnPDLNANativeValueUnion *first,
+                 GUPnPDLNANativeValueUnion *second)
+{
+        return !g_strcmp0 (first->string_value, second->string_value);
+}
+
+static gboolean
+string_is_in_range (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                    GUPnPDLNANativeValueUnion *min,
+                    GUPnPDLNANativeValueUnion *max,
+                    GUPnPDLNANativeValueUnion *value)
+{
+        /* string range? */
+        return (!g_strcmp0 (min->string_value,
+                            value->string_value) ||
+                !g_strcmp0 (max->string_value,
+                            value->string_value));
+}
+
+static const gchar *
+string_name (GUPnPDLNANativeValueType *type G_GNUC_UNUSED)
+{
+        return "string";
+}
+
+static gboolean
+string_verify_range (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                     GUPnPDLNANativeValueUnion *min G_GNUC_UNUSED,
+                     GUPnPDLNANativeValueUnion *max G_GNUC_UNUSED)
+{
+        return FALSE;
+}
+
+static gchar *
+string_to_string (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                  GUPnPDLNANativeValueUnion *value)
+{
+        return g_strdup (value->string_value);
+}
+
+gint
+string_compare (GUPnPDLNANativeValueType  *type G_GNUC_UNUSED,
+                GUPnPDLNANativeValueUnion *a,
+                GUPnPDLNANativeValueUnion *b)
+{
+        return g_strcmp0 (a->string_value, b->string_value);
+}
+
+static GUPnPDLNANativeValueType string_type_impl = {
+        string_init,
+        string_copy,
+        string_clean,
+        string_is_equal,
+        string_is_in_range,
+        string_name,
+        string_verify_range,
+        string_to_string,
+        string_compare
+};
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_value_type_bool (void)
+{
+        return &bool_type_impl;
+}
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_value_type_fraction (void)
+{
+        return &fraction_type_impl;
+}
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_value_type_int (void)
+{
+        return &int_type_impl;
+}
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_value_type_string (void)
+{
+        return &string_type_impl;
+}
+
+gboolean
+gupnp_dlna_native_value_type_init (GUPnPDLNANativeValueType  *type,
+                                   GUPnPDLNANativeValueUnion *value,
+                                   const gchar               *raw)
+{
+        g_return_val_if_fail (type != NULL, FALSE);
+        g_return_val_if_fail (value != NULL, FALSE);
+        g_return_val_if_fail (raw != NULL, FALSE);
+        g_return_val_if_fail (type->init != NULL, FALSE);
+
+        return type->init (type, value, raw);
+}
+
+gboolean
+gupnp_dlna_native_value_type_copy (GUPnPDLNANativeValueType  *type,
+                                   GUPnPDLNANativeValueUnion *from,
+                                   GUPnPDLNANativeValueUnion *to)
+{
+        g_return_val_if_fail (type != NULL, FALSE);
+        g_return_val_if_fail (from != NULL, FALSE);
+        g_return_val_if_fail (to != NULL, FALSE);
+        g_return_val_if_fail (type->copy != NULL, FALSE);
+
+        return type->copy (type, from, to);
+}
+
+void
+gupnp_dlna_native_value_type_clean (GUPnPDLNANativeValueType  *type,
+                                    GUPnPDLNANativeValueUnion *value)
+{
+        g_return_if_fail (type != NULL);
+        g_return_if_fail (value != NULL);
+        g_return_if_fail (type->clean != NULL);
+
+        type->clean (type, value);
+}
+
+gboolean
+gupnp_dlna_native_value_type_is_equal (GUPnPDLNANativeValueType  *type,
+                                       GUPnPDLNANativeValueUnion *first,
+                                       GUPnPDLNANativeValueUnion *second)
+{
+        g_return_val_if_fail (type != NULL, FALSE);
+        g_return_val_if_fail (first != NULL, FALSE);
+        g_return_val_if_fail (second != NULL, FALSE);
+        g_return_val_if_fail (type->is_equal != NULL, FALSE);
+
+        return type->is_equal (type, first, second);
+}
+
+gboolean
+gupnp_dlna_native_value_type_is_in_range (GUPnPDLNANativeValueType  *type,
+                                          GUPnPDLNANativeValueUnion *min,
+                                          GUPnPDLNANativeValueUnion *max,
+                                          GUPnPDLNANativeValueUnion *value)
+{
+        g_return_val_if_fail (type != NULL, FALSE);
+        g_return_val_if_fail (min != NULL, FALSE);
+        g_return_val_if_fail (max != NULL, FALSE);
+        g_return_val_if_fail (value != NULL, FALSE);
+        g_return_val_if_fail (type->is_in_range != NULL, FALSE);
+
+        return type->is_in_range (type, min, max, value);
+}
+
+const gchar *
+gupnp_dlna_native_value_type_name (GUPnPDLNANativeValueType *type)
+{
+        g_return_val_if_fail (type != NULL, NULL);
+        g_return_val_if_fail (type->name != NULL, NULL);
+
+        return type->name (type);
+}
+
+gboolean
+gupnp_dlna_native_value_type_verify_range (GUPnPDLNANativeValueType  *type,
+                                           GUPnPDLNANativeValueUnion *min,
+                                           GUPnPDLNANativeValueUnion *max)
+{
+        g_return_val_if_fail (type != NULL, FALSE);
+        g_return_val_if_fail (min != NULL, FALSE);
+        g_return_val_if_fail (max != NULL, FALSE);
+        g_return_val_if_fail (type->verify_range != NULL, FALSE);
+
+        return type->verify_range (type, min, max);
+}
+
+gchar *
+gupnp_dlna_native_value_type_to_string (GUPnPDLNANativeValueType  *type,
+                                        GUPnPDLNANativeValueUnion *value)
+{
+        g_return_val_if_fail (type != NULL, NULL);
+        g_return_val_if_fail (value != NULL, NULL);
+        g_return_val_if_fail (type->to_string != NULL, NULL);
+
+        return type->to_string (type, value);
+}
+
+gint
+gupnp_dlna_native_value_type_compare (GUPnPDLNANativeValueType  *type,
+                                      GUPnPDLNANativeValueUnion *a,
+                                      GUPnPDLNANativeValueUnion *b)
+{
+        g_return_val_if_fail (type != NULL, 0);
+        g_return_val_if_fail (a != NULL, 0);
+        g_return_val_if_fail (b != NULL, 0);
+        g_return_val_if_fail (type->compare != NULL, 0);
+
+        return type->compare (type, a, b);
+}
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-type.h b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-type.h
new file mode 100644
index 0000000..23de547
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value-type.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_VALUE_TYPE_H__
+#define __GUPNP_DLNA_NATIVE_VALUE_TYPE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GUPnPDLNANativeValueType GUPnPDLNANativeValueType;
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_value_type_bool (void);
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_value_type_fraction (void);
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_value_type_int (void);
+
+GUPnPDLNANativeValueType *
+gupnp_dlna_native_value_type_string (void);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_VALUE_TYPE_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value.c b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value.c
new file mode 100644
index 0000000..a9a3d44
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "gupnp-dlna-native-value.h"
+#include "gupnp-dlna-native-sets-private.h"
+
+struct _GUPnPDLNANativeValueVTable {
+        gboolean
+        (* is_superset) (GUPnPDLNANativeValue     *base,
+                         GUPnPDLNANativeInfoValue *info);
+
+        GUPnPDLNANativeValue *
+        (* copy) (GUPnPDLNANativeValue     *base,
+                  GUPnPDLNANativeValueType *type);
+
+        void
+        (* free) (GUPnPDLNANativeValue     *base,
+                  GUPnPDLNANativeValueType *type);
+
+        gchar *
+        (* to_string) (GUPnPDLNANativeValue     *base,
+                       GUPnPDLNANativeValueType *type);
+
+        GUPnPDLNANativeValueUnion *
+        (* get_sort_value) (GUPnPDLNANativeValue *base);
+};
+
+/* single */
+typedef struct _GUPnPDLNANativeValueSingle GUPnPDLNANativeValueSingle;
+
+struct _GUPnPDLNANativeValueSingle {
+        GUPnPDLNANativeValue      base;
+        GUPnPDLNANativeValueUnion value;
+};
+
+static gboolean
+single_is_superset (GUPnPDLNANativeValue     *base,
+                    GUPnPDLNANativeInfoValue *info);
+
+static GUPnPDLNANativeValue *
+single_copy (GUPnPDLNANativeValue     *base,
+             GUPnPDLNANativeValueType *type);
+
+static void
+single_free (GUPnPDLNANativeValue     *base,
+             GUPnPDLNANativeValueType *type);
+
+static gchar *
+single_to_string (GUPnPDLNANativeValue     *base,
+                  GUPnPDLNANativeValueType *type);
+
+static GUPnPDLNANativeValueUnion *
+single_get_sort_value (GUPnPDLNANativeValue *base);
+
+static GUPnPDLNANativeValueVTable single_vtable = {
+        single_is_superset,
+        single_copy,
+        single_free,
+        single_to_string,
+        single_get_sort_value
+};
+
+static gboolean
+single_is_superset (GUPnPDLNANativeValue     *base,
+                    GUPnPDLNANativeInfoValue *info)
+{
+        GUPnPDLNANativeValueSingle *value = (GUPnPDLNANativeValueSingle *) base;
+        GUPnPDLNANativeValueType *info_type =
+                                   gupnp_dlna_native_info_value_get_type (info);
+        GUPnPDLNANativeValueUnion *info_value =
+                                  gupnp_dlna_native_info_value_get_value (info);
+
+        return gupnp_dlna_native_value_type_is_equal (info_type,
+                                                      &value->value,
+                                                      info_value);
+}
+
+static GUPnPDLNANativeValue *
+single_copy (GUPnPDLNANativeValue     *base,
+             GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeValueSingle *value = (GUPnPDLNANativeValueSingle *) base;
+        GUPnPDLNANativeValueSingle *dup =
+                                       g_slice_new (GUPnPDLNANativeValueSingle);
+
+        dup->base.vtable = &single_vtable;
+        if (!gupnp_dlna_native_value_type_copy (type,
+                                                &value->value,
+                                                &dup->value)) {
+                g_slice_free (GUPnPDLNANativeValueSingle, dup);
+                dup = NULL;
+        }
+
+        return (GUPnPDLNANativeValue *) dup;
+}
+
+static void
+single_free (GUPnPDLNANativeValue     *base,
+             GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeValueSingle *value = (GUPnPDLNANativeValueSingle *) base;
+
+        gupnp_dlna_native_value_type_clean (type, &value->value);
+        g_slice_free (GUPnPDLNANativeValueSingle, value);
+}
+
+static gchar *
+single_to_string (GUPnPDLNANativeValue     *base,
+                  GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeValueSingle *value = (GUPnPDLNANativeValueSingle *) base;
+
+        return gupnp_dlna_native_value_type_to_string (type,
+                                                       &value->value);
+}
+
+static GUPnPDLNANativeValueUnion *
+single_get_sort_value (GUPnPDLNANativeValue *base)
+{
+        GUPnPDLNANativeValueSingle *value = (GUPnPDLNANativeValueSingle *) base;
+
+        return &value->value;
+}
+
+/* range */
+typedef struct _GUPnPDLNANativeValueRange GUPnPDLNANativeValueRange;
+
+struct _GUPnPDLNANativeValueRange {
+        GUPnPDLNANativeValue base;
+        GUPnPDLNANativeValueUnion min;
+        GUPnPDLNANativeValueUnion max;
+};
+
+static gboolean
+range_is_superset (GUPnPDLNANativeValue     *base,
+                   GUPnPDLNANativeInfoValue *info);
+
+static GUPnPDLNANativeValue *
+range_copy (GUPnPDLNANativeValue     *base,
+            GUPnPDLNANativeValueType *type);
+
+static void
+range_free (GUPnPDLNANativeValue     *base,
+            GUPnPDLNANativeValueType *type);
+
+static gchar *
+range_to_string (GUPnPDLNANativeValue     *base,
+                 GUPnPDLNANativeValueType *type);
+
+static GUPnPDLNANativeValueUnion *
+range_get_sort_value (GUPnPDLNANativeValue *base);
+
+static GUPnPDLNANativeValueVTable range_vtable = {
+        range_is_superset,
+        range_copy,
+        range_free,
+        range_to_string,
+        range_get_sort_value
+};
+
+static gboolean
+range_is_superset (GUPnPDLNANativeValue     *base,
+                   GUPnPDLNANativeInfoValue *info)
+{
+        GUPnPDLNANativeValueRange *range = (GUPnPDLNANativeValueRange *) base;
+        GUPnPDLNANativeValueType *info_type =
+                                   gupnp_dlna_native_info_value_get_type (info);
+        GUPnPDLNANativeValueUnion *info_value =
+                                  gupnp_dlna_native_info_value_get_value (info);
+
+        return gupnp_dlna_native_value_type_is_in_range (info_type,
+                                                         &range->min,
+                                                         &range->max,
+                                                         info_value);
+}
+
+static GUPnPDLNANativeValue *
+range_copy (GUPnPDLNANativeValue     *base,
+            GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeValueRange *range = (GUPnPDLNANativeValueRange *) base;
+        GUPnPDLNANativeValueRange *dup =
+                                        g_slice_new (GUPnPDLNANativeValueRange);
+
+        dup->base.vtable = &range_vtable;
+        if (!gupnp_dlna_native_value_type_copy (type,
+                                                &range->min,
+                                                &dup->min)) {
+                g_slice_free (GUPnPDLNANativeValueRange, dup);
+                dup = NULL;
+        }
+        if (dup &&
+            !gupnp_dlna_native_value_type_copy (type,
+                                                &range->max,
+                                                &dup->max)) {
+                gupnp_dlna_native_value_type_clean (type,
+                                                    &dup->min);
+                g_slice_free (GUPnPDLNANativeValueRange, dup);
+                dup = NULL;
+        }
+
+        return (GUPnPDLNANativeValue *) dup;
+}
+
+static void
+range_free (GUPnPDLNANativeValue     *base,
+            GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeValueRange *range = (GUPnPDLNANativeValueRange *) base;
+
+        gupnp_dlna_native_value_type_clean (type, &range->min);
+        gupnp_dlna_native_value_type_clean (type, &range->max);
+        g_slice_free (GUPnPDLNANativeValueRange, range);
+}
+
+static gchar *
+range_to_string (GUPnPDLNANativeValue     *base,
+                 GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeValueRange *range = (GUPnPDLNANativeValueRange *) base;
+        gchar *str;
+        gchar *min = gupnp_dlna_native_value_type_to_string (type,
+                                                             &range->min);
+        gchar *max = gupnp_dlna_native_value_type_to_string (type,
+                                                             &range->max);
+
+        str = g_strdup_printf ("[ %s, %s ]", min, max);
+        g_free (min);
+        g_free (max);
+
+        return str;
+}
+
+static GUPnPDLNANativeValueUnion *
+range_get_sort_value (GUPnPDLNANativeValue *base)
+{
+        GUPnPDLNANativeValueRange *range = (GUPnPDLNANativeValueRange *) base;
+
+        return &range->min;
+}
+
+GUPnPDLNANativeValue *
+gupnp_dlna_native_value_new_single (GUPnPDLNANativeValueType *type,
+                                    const gchar              *raw)
+{
+        GUPnPDLNANativeValueSingle *value;
+
+        g_return_val_if_fail (type != NULL, NULL);
+        g_return_val_if_fail (raw != NULL, NULL);
+
+        value = g_slice_new (GUPnPDLNANativeValueSingle);
+        value->base.vtable = &single_vtable;
+        if (!gupnp_dlna_native_value_type_init (type, &value->value, raw)) {
+                g_slice_free (GUPnPDLNANativeValueSingle, value);
+                value = NULL;
+        }
+
+        return (GUPnPDLNANativeValue *) value;
+}
+
+GUPnPDLNANativeValue *
+gupnp_dlna_native_value_new_ranged (GUPnPDLNANativeValueType *type,
+                                    const gchar              *min,
+                                    const gchar              *max)
+{
+        GUPnPDLNANativeValueRange *range;
+
+        g_return_val_if_fail (type != NULL, NULL);
+        g_return_val_if_fail (min != NULL, NULL);
+        g_return_val_if_fail (max != NULL, NULL);
+
+        range = g_slice_new (GUPnPDLNANativeValueRange);
+        range->base.vtable = &range_vtable;
+        if (!gupnp_dlna_native_value_type_init (type, &range->min, min)) {
+                g_slice_free (GUPnPDLNANativeValueRange, range);
+                range = NULL;
+        }
+        if (range &&
+            !gupnp_dlna_native_value_type_init (type, &range->max, max)) {
+                gupnp_dlna_native_value_type_clean (type, &range->min);
+                g_slice_free (GUPnPDLNANativeValueRange, range);
+                range = NULL;
+        }
+        if (range &&
+            !gupnp_dlna_native_value_type_verify_range (type,
+                                                        &range->min,
+                                                        &range->max)) {
+                gupnp_dlna_native_value_type_clean (type, &range->min);
+                gupnp_dlna_native_value_type_clean (type, &range->max);
+                g_slice_free (GUPnPDLNANativeValueRange, range);
+                range = NULL;
+        }
+
+        return (GUPnPDLNANativeValue *) range;
+}
+
+gboolean
+gupnp_dlna_native_value_is_superset (GUPnPDLNANativeValue     *base,
+                                     GUPnPDLNANativeInfoValue *single)
+{
+        g_return_val_if_fail (base != NULL, FALSE);
+        g_return_val_if_fail (single != NULL, FALSE);
+        g_return_val_if_fail (base->vtable != NULL, FALSE);
+        g_return_val_if_fail (base->vtable->is_superset != NULL, FALSE);
+
+        return base->vtable->is_superset (base, single);
+}
+
+GUPnPDLNANativeValue *
+gupnp_dlna_native_value_copy (GUPnPDLNANativeValue     *base,
+                              GUPnPDLNANativeValueType *type)
+{
+        g_return_val_if_fail (base != NULL, NULL);
+        g_return_val_if_fail (type != NULL, NULL);
+        g_return_val_if_fail (base->vtable != NULL, NULL);
+        g_return_val_if_fail (base->vtable->copy != NULL, NULL);
+
+        return base->vtable->copy (base, type);
+}
+
+void
+gupnp_dlna_native_value_free (GUPnPDLNANativeValue     *base,
+                              GUPnPDLNANativeValueType *type)
+{
+        if (base == NULL)
+                return;
+
+        g_return_if_fail (type != NULL);
+        g_return_if_fail (base->vtable != NULL);
+        g_return_if_fail (base->vtable->free != NULL);
+
+        base->vtable->free (base, type);
+}
+
+gchar *
+gupnp_dlna_native_value_to_string (GUPnPDLNANativeValue     *base,
+                                   GUPnPDLNANativeValueType *type)
+{
+        g_return_val_if_fail (base != NULL, NULL);
+        g_return_val_if_fail (type != NULL, NULL);
+        g_return_val_if_fail (base->vtable != NULL, NULL);
+        g_return_val_if_fail (base->vtable->to_string != NULL, NULL);
+
+        return base->vtable->to_string (base, type);
+}
+
+static GUPnPDLNANativeValueUnion *
+gupnp_dlna_native_value_get_sort_value (GUPnPDLNANativeValue *base)
+{
+        g_return_val_if_fail (base->vtable != NULL, NULL);
+        g_return_val_if_fail (base->vtable->get_sort_value != NULL, NULL);
+
+        return base->vtable->get_sort_value (base);
+}
+
+gint
+gupnp_dlna_native_value_compare (GUPnPDLNANativeValue     *base,
+                                 GUPnPDLNANativeValue     *other,
+                                 GUPnPDLNANativeValueType *type)
+{
+        GUPnPDLNANativeValueUnion *base_union;
+        GUPnPDLNANativeValueUnion *other_union;
+
+        g_return_val_if_fail (base != NULL, 0);
+        g_return_val_if_fail (other != NULL, 0);
+        g_return_val_if_fail (type != NULL, 0);
+
+        base_union = gupnp_dlna_native_value_get_sort_value (base);
+        other_union = gupnp_dlna_native_value_get_sort_value (other);
+
+        return gupnp_dlna_native_value_type_compare (type,
+                                                     base_union,
+                                                     other_union);
+
+}
diff --git a/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value.h b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value.h
new file mode 100644
index 0000000..0c722d7
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/gupnp-dlna-native-value.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_VALUE_H__
+#define __GUPNP_DLNA_NATIVE_VALUE_H__
+
+#include <glib.h>
+#include "gupnp-dlna-native-info-value.h"
+#include "gupnp-dlna-native-value-type.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GUPnPDLNANativeValue GUPnPDLNANativeValue;
+typedef struct _GUPnPDLNANativeValueVTable GUPnPDLNANativeValueVTable;
+
+struct _GUPnPDLNANativeValue {
+        GUPnPDLNANativeValueVTable *vtable;
+};
+
+GUPnPDLNANativeValue *
+gupnp_dlna_native_value_new_single (GUPnPDLNANativeValueType *type,
+                                    const gchar              *single);
+
+GUPnPDLNANativeValue *
+gupnp_dlna_native_value_new_ranged (GUPnPDLNANativeValueType *type,
+                                    const gchar              *min,
+                                    const gchar              *max);
+
+gboolean
+gupnp_dlna_native_value_is_superset (GUPnPDLNANativeValue     *base,
+                                     GUPnPDLNANativeInfoValue *single);
+
+GUPnPDLNANativeValue *
+gupnp_dlna_native_value_copy (GUPnPDLNANativeValue     *base,
+                              GUPnPDLNANativeValueType *type);
+
+void
+gupnp_dlna_native_value_free (GUPnPDLNANativeValue     *base,
+                              GUPnPDLNANativeValueType *type);
+
+gchar *
+gupnp_dlna_native_value_to_string (GUPnPDLNANativeValue     *base,
+                                   GUPnPDLNANativeValueType *type);
+
+gint
+gupnp_dlna_native_value_compare (GUPnPDLNANativeValue     *base,
+                                 GUPnPDLNANativeValue     *other,
+                                 GUPnPDLNANativeValueType *type);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_VALUE_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/sets/sets.am b/libgupnp-dlna/profile-backends/native/sets/sets.am
new file mode 100644
index 0000000..816be70
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/sets/sets.am
@@ -0,0 +1,14 @@
+sets_sources = \
+	profile-backends/native/sets/gupnp-dlna-native-info-set.c \
+	profile-backends/native/sets/gupnp-dlna-native-info-set.h \
+	profile-backends/native/sets/gupnp-dlna-native-info-value.c \
+	profile-backends/native/sets/gupnp-dlna-native-info-value.h \
+	profile-backends/native/sets/gupnp-dlna-native-restriction.c \
+	profile-backends/native/sets/gupnp-dlna-native-restriction.h \
+	profile-backends/native/sets/gupnp-dlna-native-sets-private.h \
+	profile-backends/native/sets/gupnp-dlna-native-value.c \
+	profile-backends/native/sets/gupnp-dlna-native-value.h \
+	profile-backends/native/sets/gupnp-dlna-native-value-list.c \
+	profile-backends/native/sets/gupnp-dlna-native-value-list.h \
+	profile-backends/native/sets/gupnp-dlna-native-value-type.c \
+	profile-backends/native/sets/gupnp-dlna-native-value-type.h



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