[gupnp-dlna/wip/new-api: 4/15] Replace old implementation of profile guessing with new one



commit f954a8e4a452fa25a2af3a68066df0aa17b76b1a
Author: Krzesimir Nowak <krnowak openismus com>
Date:   Thu Nov 15 15:10:34 2012 +0100

    Replace old implementation of profile guessing with new one
    
    The new implementation does not expose GStreamer in its API. Nor it
    does it for metadata discovery API. The only functionality here is
    profile guessing.

 libgupnp-dlna/gupnp-dlna-discoverer.c           |  443 ----------
 libgupnp-dlna/gupnp-dlna-discoverer.h           |  116 ---
 libgupnp-dlna/gupnp-dlna-field-value.c          |   69 ++
 libgupnp-dlna/gupnp-dlna-field-value.h          |   57 ++
 libgupnp-dlna/gupnp-dlna-information.c          |  265 ------
 libgupnp-dlna/gupnp-dlna-information.h          |   80 --
 libgupnp-dlna/gupnp-dlna-marshal.list           |    2 -
 libgupnp-dlna/gupnp-dlna-metadata-backend.c     |  100 +++
 libgupnp-dlna/gupnp-dlna-metadata-backend.h     |   35 +
 libgupnp-dlna/gupnp-dlna-profile-backend.c      |   37 +
 libgupnp-dlna/gupnp-dlna-profile-backend.h      |   40 +
 libgupnp-dlna/gupnp-dlna-profile-guesser-impl.c |  100 +++
 libgupnp-dlna/gupnp-dlna-profile-guesser-impl.h |   99 +++
 libgupnp-dlna/gupnp-dlna-profile-guesser.c      |  476 ++++++++++
 libgupnp-dlna/gupnp-dlna-profile-guesser.h      |  121 +++
 libgupnp-dlna/gupnp-dlna-profile-loader.c       | 1060 +++++++++++++++++++++++
 libgupnp-dlna/gupnp-dlna-profile-loader.h       |  132 +++
 libgupnp-dlna/gupnp-dlna-profile-private.h      |   44 -
 libgupnp-dlna/gupnp-dlna-profile.c              |  299 ++-----
 libgupnp-dlna/gupnp-dlna-profile.h              |   53 +-
 libgupnp-dlna/gupnp-dlna-profiles.c             |  545 ------------
 libgupnp-dlna/profile-loading.c                 |  921 --------------------
 libgupnp-dlna/profile-loading.h                 |   56 --
 23 files changed, 2433 insertions(+), 2717 deletions(-)
---
diff --git a/libgupnp-dlna/gupnp-dlna-field-value.c b/libgupnp-dlna/gupnp-dlna-field-value.c
new file mode 100644
index 0000000..c5fe8ca
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-field-value.c
@@ -0,0 +1,69 @@
+/*
+ * 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-field-value.h"
+
+GUPnPDLNAFieldValue *
+gupnp_dlna_field_value_new_single (gchar *single)
+{
+        GUPnPDLNAFieldValue *value = g_slice_new (GUPnPDLNAFieldValue);
+
+        value->type = GUPNP_DLNA_FIELD_VALUE_TYPE_SINGLE;
+        value->value.single = g_strdup (single);
+
+        return value;
+}
+
+GUPnPDLNAFieldValue *
+gupnp_dlna_field_value_new_range (gchar *min,
+                                  gchar *max)
+{
+        GUPnPDLNAFieldValue *value = g_slice_new (GUPnPDLNAFieldValue);
+
+        value->type = GUPNP_DLNA_FIELD_VALUE_TYPE_RANGE;
+        value->value.range.min = g_strdup (min);
+        value->value.range.max = g_strdup (max);
+
+        return value;
+}
+
+void
+gupnp_dlna_field_value_free (GUPnPDLNAFieldValue *value)
+{
+        if (!value)
+                return;
+
+        switch (value->type) {
+        case GUPNP_DLNA_FIELD_VALUE_TYPE_SINGLE:
+                g_free (value->value.single);
+
+                break;
+        case GUPNP_DLNA_FIELD_VALUE_TYPE_RANGE:
+                g_free (value->value.range.min);
+                g_free (value->value.range.max);
+
+                break;
+        default:
+                g_warning ("Unknown field value type.");
+        }
+
+        g_slice_free (GUPnPDLNAFieldValue, value);
+}
diff --git a/libgupnp-dlna/gupnp-dlna-field-value.h b/libgupnp-dlna/gupnp-dlna-field-value.h
new file mode 100644
index 0000000..7066d75
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-field-value.h
@@ -0,0 +1,57 @@
+/*
+ * 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_FIELD_VALUE_H__
+#define __GUPNP_DLNA_FIELD_VALUE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+        GUPNP_DLNA_FIELD_VALUE_TYPE_RANGE,
+        GUPNP_DLNA_FIELD_VALUE_TYPE_SINGLE
+} GUPnPDLNAFieldValueType;
+
+typedef struct {
+        GUPnPDLNAFieldValueType type;
+        union {
+                struct {
+                        gchar *min;
+                        gchar *max;
+                } range;
+                gchar *single;
+        } value;
+} GUPnPDLNAFieldValue;
+
+GUPnPDLNAFieldValue *
+gupnp_dlna_field_value_new_single (gchar *single);
+
+GUPnPDLNAFieldValue *
+gupnp_dlna_field_value_new_range (gchar *min,
+                                  gchar *max);
+
+void
+gupnp_dlna_field_value_free (GUPnPDLNAFieldValue *value);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_FIELD_VALUE_H__ */
diff --git a/libgupnp-dlna/gupnp-dlna-metadata-backend.c b/libgupnp-dlna/gupnp-dlna-metadata-backend.c
new file mode 100644
index 0000000..89f1b61
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-metadata-backend.c
@@ -0,0 +1,100 @@
+/*
+ * 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 <gmodule.h>
+#include "gupnp-dlna-metadata-backend.h"
+
+#define GET_DEFAULT_EXTRACTOR_SYMBOL "gupnp_dlna_get_default_extractor"
+
+struct {
+        GModule *module;
+        GUPnPDLNAMetadataExtractor * (* get_default_extractor) (void);
+} metadata_backend;
+
+static gboolean
+load_metadata_backend (void)
+{
+        static gsize backend_chosen = 0;
+
+        if (g_once_init_enter (&backend_chosen)) {
+                const gchar *backend = g_getenv ("GUPNP_DLNA_METADATA_BACKEND");
+                const gchar *backend_dir =
+                                   g_getenv ("GUPNP_DLNA_METADATA_BACKEND_DIR");
+                GModule *module;
+                gchar *module_path;
+                gpointer get_default_extractor = NULL;
+                gsize loaded = 0;
+
+                if (!backend)
+                        backend = GUPNP_DLNA_DEFAULT_METADATA_BACKEND;
+                if (!backend_dir)
+                        backend_dir = GUPNP_DLNA_DEFAULT_METADATA_BACKEND_DIR;
+                module_path = g_module_build_path (backend_dir, backend);
+                module = g_module_open (module_path, G_MODULE_BIND_MASK);
+
+                if (!module) {
+                        g_warning ("Could not load open metadata backend '%s'.",
+                                   module_path);
+
+                        goto fail;
+                }
+                if (!g_module_symbol (module,
+                                      GET_DEFAULT_EXTRACTOR_SYMBOL,
+                                      &get_default_extractor)) {
+                        g_warning ("Could not find '"
+                                   GET_DEFAULT_EXTRACTOR_SYMBOL
+                                   "' symbol in '%s'.",
+                                   module_path);
+
+                        goto fail;
+                }
+                if (!get_default_extractor) {
+                        g_warning ("'"
+                                   GET_DEFAULT_EXTRACTOR_SYMBOL
+                                   "' symbol in '%s' is invalid.",
+                                   module_path);
+
+                        goto fail;
+                }
+                g_module_make_resident (module);
+                metadata_backend.module = module;
+                metadata_backend.get_default_extractor = get_default_extractor;
+                module = NULL;
+                loaded = 1;
+        fail:
+                g_free (module_path);
+                if (module)
+                        g_module_close (module);
+                g_once_init_leave (&backend_chosen, loaded);
+        }
+
+        return (backend_chosen != 0);
+}
+
+GUPnPDLNAMetadataExtractor *
+gupnp_dlna_metadata_backend_get_extractor (void)
+{
+        gboolean metadata_backend_loaded = load_metadata_backend ();
+
+        g_return_val_if_fail (metadata_backend_loaded == TRUE, NULL);
+
+        return metadata_backend.get_default_extractor ();
+}
diff --git a/libgupnp-dlna/gupnp-dlna-metadata-backend.h b/libgupnp-dlna/gupnp-dlna-metadata-backend.h
new file mode 100644
index 0000000..79690d0
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-metadata-backend.h
@@ -0,0 +1,35 @@
+/*
+ * 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_METADATA_BACKEND__
+#define __GUPNP_DLNA_METADATA_BACKEND__
+
+#include <glib.h>
+#include "gupnp-dlna-metadata-extractor.h"
+
+G_BEGIN_DECLS
+
+GUPnPDLNAMetadataExtractor *
+gupnp_dlna_metadata_backend_get_extractor (void);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_METADATA_BACKEND__ */
diff --git a/libgupnp-dlna/gupnp-dlna-profile-backend.c b/libgupnp-dlna/gupnp-dlna-profile-backend.c
new file mode 100644
index 0000000..1667ea3
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-profile-backend.c
@@ -0,0 +1,37 @@
+/*
+ * 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-profile-backend.h"
+#include "gupnp-dlna-native-profile-backend.h"
+
+GUPnPDLNAProfileLoader *
+gupnp_dlna_profile_backend_get_loader (gboolean relaxed_mode,
+                                       gboolean extended_mode)
+{
+        return gupnp_dlna_native_profile_backend_get_loader (relaxed_mode,
+                                                             extended_mode);
+}
+
+GUPnPDLNAProfileGuesserImpl *
+gupnp_dlna_profile_backend_get_guesser_impl (void)
+{
+        return gupnp_dlna_native_profile_backend_get_guesser_impl ();
+}
diff --git a/libgupnp-dlna/gupnp-dlna-profile-backend.h b/libgupnp-dlna/gupnp-dlna-profile-backend.h
new file mode 100644
index 0000000..f2f4e2b
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-profile-backend.h
@@ -0,0 +1,40 @@
+/*
+ * 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_PROFILE_BACKEND_H__
+#define __GUPNP_DLNA_PROFILE_BACKEND_H__
+
+#include <glib.h>
+#include "gupnp-dlna-profile-loader.h"
+#include "gupnp-dlna-profile-guesser-impl.h"
+
+G_BEGIN_DECLS
+
+GUPnPDLNAProfileLoader *
+gupnp_dlna_profile_backend_get_loader (gboolean relaxed_mode,
+                                       gboolean extended_mode);
+
+GUPnPDLNAProfileGuesserImpl *
+gupnp_dlna_profile_backend_get_guesser_impl (void);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_PROFILE_BACKEND_H__ */
diff --git a/libgupnp-dlna/gupnp-dlna-profile-guesser-impl.c b/libgupnp-dlna/gupnp-dlna-profile-guesser-impl.c
new file mode 100644
index 0000000..785b457
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-profile-guesser-impl.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Arun Raghavan <arun raghavan collabora co uk>
+ *          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-profile-guesser-impl.h"
+
+G_DEFINE_ABSTRACT_TYPE (GUPnPDLNAProfileGuesserImpl,
+                        gupnp_dlna_profile_guesser_impl,
+                        G_TYPE_OBJECT)
+
+struct _GUPnPDLNAProfileGuesserImplPrivate {
+        gpointer placeholder;
+};
+
+static void
+gupnp_dlna_profile_guesser_impl_class_init
+                          (GUPnPDLNAProfileGuesserImplClass *guesser_impl_class)
+{
+        g_type_class_add_private (guesser_impl_class,
+                                  sizeof (GUPnPDLNAProfileGuesserImplPrivate));
+}
+
+static void
+gupnp_dlna_profile_guesser_impl_init (GUPnPDLNAProfileGuesserImpl *self)
+{
+        GUPnPDLNAProfileGuesserImplPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE
+                                        (self,
+                                         GUPNP_TYPE_DLNA_PROFILE_GUESSER_IMPL,
+                                         GUPnPDLNAProfileGuesserImplPrivate);
+
+        self->priv = priv;
+}
+
+GUPnPDLNAProfile *
+gupnp_dlna_profile_guesser_impl_guess_profile
+                                     (GUPnPDLNAProfileGuesserImpl *guesser_impl,
+                                      GUPnPDLNAInformation        *info,
+                                      GList                       *profiles)
+{
+        GUPnPDLNAVideoInformation *video_info =
+                            gupnp_dlna_information_get_video_information (info);
+        GUPnPDLNAAudioInformation *audio_info =
+                            gupnp_dlna_information_get_audio_information (info);
+        GUPnPDLNAImageInformation *image_info =
+                            gupnp_dlna_information_get_image_information (info);
+        GUPnPDLNAProfile *profile = NULL;
+        GUPnPDLNAProfileGuesserImplClass *guesser_impl_class =
+                       GUPNP_DLNA_PROFILE_GUESSER_IMPL_GET_CLASS (guesser_impl);
+
+        g_return_val_if_fail
+                 (GUPNP_IS_DLNA_PROFILE_GUESSER_IMPL_CLASS (guesser_impl_class),
+                  NULL);
+
+        if (image_info) {
+                g_return_val_if_fail
+                               (guesser_impl_class->guess_image_profile != NULL,
+                                NULL);
+
+                profile = guesser_impl_class->guess_image_profile (guesser_impl,
+                                                                   info,
+                                                                   profiles);
+        } else if (video_info) {
+                g_return_val_if_fail
+                               (guesser_impl_class->guess_video_profile != NULL,
+                                NULL);
+
+                profile = guesser_impl_class->guess_video_profile (guesser_impl,
+                                                                   info,
+                                                                   profiles);
+        } else if (audio_info) {
+                g_return_val_if_fail
+                               (guesser_impl_class->guess_audio_profile != NULL,
+                                NULL);
+
+                profile = guesser_impl_class->guess_audio_profile (guesser_impl,
+                                                                   info,
+                                                                   profiles);
+        }
+
+        return profile;
+}
diff --git a/libgupnp-dlna/gupnp-dlna-profile-guesser-impl.h b/libgupnp-dlna/gupnp-dlna-profile-guesser-impl.h
new file mode 100644
index 0000000..c355d3c
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-profile-guesser-impl.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * Authors: Arun Raghavan <arun raghavan collabora co uk>
+ *          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_PROFILE_GUESSER_IMPL_H__
+#define __GUPNP_DLNA_PROFILE_GUESSER_IMPL_H__
+
+#include <glib-object.h>
+#include "gupnp-dlna-profile.h"
+#include "gupnp-dlna-information.h"
+
+G_BEGIN_DECLS
+
+#define GUPNP_TYPE_DLNA_PROFILE_GUESSER_IMPL \
+        (gupnp_dlna_profile_guesser_impl_get_type())
+
+#define GUPNP_DLNA_PROFILE_GUESSER_IMPL(obj) \
+        (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                                     GUPNP_TYPE_DLNA_PROFILE_GUESSER_IMPL, \
+                                     GUPnPDLNAProfileGuesserImpl))
+
+#define GUPNP_DLNA_PROFILE_GUESSER_IMPL_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_CAST ((klass), \
+                                  GUPNP_TYPE_DLNA_PROFILE_GUESSER_IMPL, \
+                                  GUPnPDLNAProfileGuesserImplClass))
+
+#define GUPNP_IS_DLNA_PROFILE_GUESSER_IMPL(obj) \
+        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                                     GUPNP_TYPE_DLNA_PROFILE_GUESSER_IMPL))
+
+#define GUPNP_IS_DLNA_PROFILE_GUESSER_IMPL_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+                                  GUPNP_TYPE_DLNA_PROFILE_GUESSER_IMPL))
+
+#define GUPNP_DLNA_PROFILE_GUESSER_IMPL_GET_CLASS(obj) \
+        (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                                    GUPNP_TYPE_DLNA_PROFILE_GUESSER_IMPL, \
+                                    GUPnPDLNAProfileGuesserImplClass))
+
+typedef struct _GUPnPDLNAProfileGuesserImplPrivate
+                GUPnPDLNAProfileGuesserImplPrivate;
+
+typedef struct {
+        GObject parent;
+
+        GUPnPDLNAProfileGuesserImplPrivate *priv;
+} GUPnPDLNAProfileGuesserImpl;
+
+typedef struct {
+        GObjectClass parent_class;
+
+        /* virtuals */
+        GUPnPDLNAProfile *
+        (* guess_image_profile) (GUPnPDLNAProfileGuesserImpl *guesser_impl,
+                                 GUPnPDLNAInformation        *info,
+                                 GList                       *profiles);
+
+        GUPnPDLNAProfile *
+        (* guess_video_profile) (GUPnPDLNAProfileGuesserImpl *guesser_impl,
+                                 GUPnPDLNAInformation        *info,
+                                 GList                       *profiles);
+
+        GUPnPDLNAProfile *
+        (* guess_audio_profile) (GUPnPDLNAProfileGuesserImpl *guesser_impl,
+                                 GUPnPDLNAInformation        *info,
+                                 GList                       *profiles);
+} GUPnPDLNAProfileGuesserImplClass;
+
+GType
+gupnp_dlna_profile_guesser_impl_get_type (void) G_GNUC_CONST;
+
+GUPnPDLNAProfile *
+gupnp_dlna_profile_guesser_impl_guess_profile
+                                     (GUPnPDLNAProfileGuesserImpl *guesser_impl,
+                                      GUPnPDLNAInformation        *info,
+                                      GList                       *profiles);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_PROFILE_GUESSER_IMPL_H__ */
diff --git a/libgupnp-dlna/gupnp-dlna-profile-guesser.c b/libgupnp-dlna/gupnp-dlna-profile-guesser.c
new file mode 100644
index 0000000..ecb6d81
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-profile-guesser.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Arun Raghavan <arun raghavan collabora co uk>
+ *          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-profile-guesser.h"
+#include "gupnp-dlna-profile-guesser-impl.h"
+#include "gupnp-dlna-profile-loader.h"
+#include "gupnp-dlna-profile-backend.h"
+#include "gupnp-dlna-metadata-extractor.h"
+#include "gupnp-dlna-metadata-backend.h"
+
+/**
+ * SECTION:gupnp-dlna-profile-guesser
+ * @short_description: Utility API for discovering DLNA profile for
+ * given media.
+ *
+ * The API provides synchronous and asynchronous guessing of DLNA
+ * profile. The asynchronous mode requires a running #GMainLoop in the
+ * default #GMainContext.
+ */
+enum {
+        DONE,
+        SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST];
+
+G_DEFINE_TYPE (GUPnPDLNAProfileGuesser,
+               gupnp_dlna_profile_guesser,
+               G_TYPE_OBJECT)
+
+struct _GUPnPDLNAProfileGuesserPrivate {
+        gboolean relaxed_mode;
+        gboolean extended_mode;
+};
+
+enum {
+        PROP_0,
+        PROP_DLNA_RELAXED_MODE,
+        PROP_DLNA_EXTENDED_MODE,
+};
+
+static GList *profiles_list[2][2];
+
+static void
+gupnp_dlna_profile_guesser_set_property (GObject      *object,
+                                         guint         property_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec)
+{
+        GUPnPDLNAProfileGuesser *self = GUPNP_DLNA_PROFILE_GUESSER (object);
+        GUPnPDLNAProfileGuesserPrivate *priv = self->priv;
+
+        switch (property_id) {
+        case PROP_DLNA_RELAXED_MODE:
+                priv->relaxed_mode = g_value_get_boolean (value);
+                break;
+
+        case PROP_DLNA_EXTENDED_MODE:
+                priv->extended_mode = g_value_get_boolean (value);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+                                                   property_id,
+                                                   pspec);
+                break;
+        }
+}
+
+static void
+gupnp_dlna_profile_guesser_get_property (GObject    *object,
+                                         guint       property_id,
+                                         GValue     *value,
+                                         GParamSpec *pspec)
+{
+        GUPnPDLNAProfileGuesser *self = GUPNP_DLNA_PROFILE_GUESSER (object);
+        GUPnPDLNAProfileGuesserPrivate *priv = self->priv;
+
+        switch (property_id) {
+        case PROP_DLNA_RELAXED_MODE:
+                g_value_set_boolean (value, priv->relaxed_mode);
+                break;
+
+        case PROP_DLNA_EXTENDED_MODE:
+                g_value_set_boolean (value, priv->extended_mode);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+                                                   property_id,
+                                                   pspec);
+                break;
+        }
+}
+
+static void
+gupnp_dlna_profile_guesser_class_init
+                                   (GUPnPDLNAProfileGuesserClass *guesser_class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (guesser_class);
+        GParamSpec *pspec;
+        guint iter;
+
+        object_class->get_property = gupnp_dlna_profile_guesser_get_property;
+        object_class->set_property = gupnp_dlna_profile_guesser_set_property;
+
+        /**
+         * GUPnPDLNAProfileGuesser:relaxed-mode:
+         *
+         * Whether profile matching should not be strictly compliant
+         * with the DLNA specification.
+         */
+        pspec = g_param_spec_boolean ("relaxed-mode",
+                                      "Relaxed mode property",
+                                      "Indicates that profile matching should"
+                                      "be strictly compliant with the DLNA "
+                                      "specification",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT_ONLY);
+        g_object_class_install_property (object_class,
+                                         PROP_DLNA_RELAXED_MODE,
+                                         pspec);
+
+        /**
+         * GUPnPDLNAProfileGuesser:extended-mode:
+         * @extended: setting true will enable extended profile support
+         *
+         * Whether profile matching should be done also against DLNA
+         * profiles not being a part of DLNA specification.
+         */
+        pspec = g_param_spec_boolean ("extended-mode",
+                                      "Extended mode property",
+                                      "Indicates support for profiles that are "
+                                      "not part of the DLNA specification",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT_ONLY);
+        g_object_class_install_property (object_class,
+                                         PROP_DLNA_EXTENDED_MODE,
+                                         pspec);
+
+        /**
+         * GUPnPDLNAProfileGuesser::done:
+         * @profile_guesser: The #GUPnPDLNAProfileGuesser.
+         * @uri: URI for which profile was guessed.
+         * @dlna: The results as #GUPnPDLNAProfile.
+         * @error: Contains details of the error if discovery failed,
+         * else is %NULL.
+         *
+         * Will be emitted when guessing DLNA profile for a URI has finished.
+         */
+        signals[DONE] =
+                g_signal_new ("done",
+                              G_TYPE_FROM_CLASS (guesser_class),
+                              G_SIGNAL_RUN_LAST,
+                              0,
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_generic,
+                              G_TYPE_NONE,
+                              3,
+                              G_TYPE_STRING,
+                              GUPNP_TYPE_DLNA_PROFILE,
+                              G_TYPE_ERROR);
+
+        /* Load DLNA profiles from disk */
+        for (iter = 0; iter < 4; ++iter) {
+                gboolean relaxed = (iter > 1); /* F,F,T,T */
+                gboolean extended = ((iter) % 2 != 0); /* F,T,F,T */
+                guint rel_index = (relaxed ? 1 : 0);
+                guint ext_index = (extended ? 1 : 0);
+                GUPnPDLNAProfileLoader *loader =
+                      gupnp_dlna_profile_loader_get_default (relaxed, extended);
+
+                profiles_list[rel_index][ext_index] =
+                               gupnp_dlna_profile_loader_get_from_disk (loader);
+                g_object_unref (loader);
+        }
+
+        g_type_class_add_private (guesser_class,
+                                  sizeof (GUPnPDLNAProfileGuesserPrivate));
+}
+
+static void
+gupnp_dlna_profile_guesser_init (GUPnPDLNAProfileGuesser *self)
+{
+        GUPnPDLNAProfileGuesserPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE
+                                        (self,
+                                         GUPNP_TYPE_DLNA_PROFILE_GUESSER,
+                                         GUPnPDLNAProfileGuesserPrivate);
+
+        priv->relaxed_mode = FALSE;
+        priv->extended_mode = FALSE;
+        self->priv = priv;
+}
+
+/**
+ * gupnp_dlna_profile_guesser_new:
+ * @relaxed_mode: %TRUE to enable relaxed mode support. %FALSE otherwise.
+ * @extended_mode: %TRUE to enable extended mode support. %FALSE otherwise.
+ *
+ * Creates a new guesser that will use specific DLNA profiles for
+ * matching - i.e. which profiles will be used depends on
+ * @relaxed_mode and @extended_mode.
+ *
+ * Returns: A new #GUPnPDLNAProfileGuesser object.
+ */
+GUPnPDLNAProfileGuesser *
+gupnp_dlna_profile_guesser_new (gboolean relaxed_mode,
+                                gboolean extended_mode)
+{
+        return GUPNP_DLNA_PROFILE_GUESSER (g_object_new
+                                           (GUPNP_TYPE_DLNA_PROFILE_GUESSER,
+                                            "relaxed-mode", relaxed_mode,
+                                            "extended-mode", extended_mode,
+                                            NULL));
+}
+
+static gboolean
+unref_extractor_in_idle (GUPnPDLNAMetadataExtractor *extractor)
+{
+        if (extractor)
+                g_object_unref (extractor);
+
+        return FALSE;
+}
+
+static GUPnPDLNAProfile *
+guess_profile (GUPnPDLNAProfileGuesser *guesser,
+               GUPnPDLNAInformation    *info)
+{
+        GUPnPDLNAProfileGuesserImpl *guesser_impl =
+                                 gupnp_dlna_profile_backend_get_guesser_impl ();
+        GList *profiles = gupnp_dlna_profile_guesser_list_profiles (guesser);
+
+        return gupnp_dlna_profile_guesser_impl_guess_profile (guesser_impl,
+                                                              info,
+                                                              profiles);
+}
+
+static void
+gupnp_dlna_discovered_cb (GUPnPDLNAProfileGuesser *guesser,
+                          GUPnPDLNAInformation    *info,
+                          GError                  *error,
+                          gpointer                 user_data)
+{
+        GUPnPDLNAProfile *profile = NULL;
+        GUPnPDLNAMetadataExtractor *extractor =
+                                      GUPNP_DLNA_METADATA_EXTRACTOR (user_data);
+        const gchar *uri = NULL;
+
+        if (!error) {
+                profile = guess_profile (guesser, info);
+        }
+        if (info)
+                uri = gupnp_dlna_information_get_uri (info);
+        g_signal_emit (guesser, signals[DONE], 0, uri, profile, error);
+
+        g_idle_add ((GSourceFunc) unref_extractor_in_idle, extractor);
+}
+
+/**
+ * gupnp_dlna_profile_guesser_guess_profile_async:
+ * @guesser: #GUPnPDLNAProfileGuesser object to use for guessing.
+ * @uri: URI of media.
+ * @timeout_in_ms: Timeout of guessing in miliseconds.
+ * @error: #GError object or %NULL.
+ *
+ * Asynchronously guesses DLNA profile for given @uri. When guessing
+ * is done, ::done signal is emitted on @guesser.
+ *
+ * Returns: %TRUE if @uri was successfully queued, %FALSE otherwise.
+ */
+gboolean
+gupnp_dlna_profile_guesser_guess_profile_async
+                                       (GUPnPDLNAProfileGuesser  *guesser,
+                                        const gchar              *uri,
+                                        guint                     timeout_in_ms,
+                                        GError                  **error)
+{
+        GUPnPDLNAMetadataExtractor *extractor =
+                                   gupnp_dlna_metadata_backend_get_extractor ();
+        gboolean queued;
+        GError *extractor_error = NULL;
+        guint id =
+                g_signal_connect_swapped (extractor,
+                                          "done",
+                                          G_CALLBACK (gupnp_dlna_discovered_cb),
+                                          guesser);
+
+        queued = gupnp_dlna_metadata_extractor_extract_async (extractor,
+                                                              uri,
+                                                              timeout_in_ms,
+                                                              &extractor_error);
+        if (extractor_error) {
+                g_propagate_error (error, extractor_error);
+                g_signal_handler_disconnect (extractor, id);
+                g_object_unref (extractor);
+        }
+
+        return queued;
+}
+
+/* Synchronous API */
+
+/**
+ * gupnp_dlna_profile_guesser_guess_profile_sync:
+ * @guesser: #GUPnPDLNAProfileGuesser object to use for guessing.
+ * @uri: URI of media.
+ * @timeout_in_ms: Timeout of guessing in miliseconds.
+ * @error: #GError object or %NULL.
+ *
+ * Synchronously guesses DLNA profile for given @uri.
+ *
+ * Returns: (transfer none): DLNA profile if any had matched, %NULL otherwise.
+ */
+GUPnPDLNAProfile *
+gupnp_dlna_profile_guesser_guess_profile_sync
+                                       (GUPnPDLNAProfileGuesser  *guesser,
+                                        const gchar              *uri,
+                                        guint                     timeout_in_ms,
+                                        GError                  **error)
+{
+        GError *extraction_error = NULL;
+        GUPnPDLNAMetadataExtractor *extractor =
+                                   gupnp_dlna_metadata_backend_get_extractor ();
+        GUPnPDLNAInformation *info =
+                 gupnp_dlna_metadata_extractor_extract_sync (extractor,
+                                                             uri,
+                                                             timeout_in_ms,
+                                                             &extraction_error);
+        GUPnPDLNAProfile *profile = NULL;
+
+        if (extraction_error)
+                g_propagate_error (error,
+                                   extraction_error);
+        else
+                profile = guess_profile (guesser, info);
+
+        if (info)
+                g_object_unref (info);
+        if (extractor)
+                g_object_unref (extractor);
+
+        return profile;
+}
+
+/**
+ * gupnp_dlna_profile_guesser_get_profile:
+ * @guesser: The #GUPnPDLNAProfileGuesser object.
+ * @name: The name of the DLNA profile to be retrieved.
+ *
+ * Lookups for #GUPnPDLNAProfile with given @name.
+ *
+ * Returns: (transfer none): A #GUPnPDLNAProfile object on success,
+ * %NULL otherwise.
+ **/
+GUPnPDLNAProfile *
+gupnp_dlna_profile_guesser_get_profile (GUPnPDLNAProfileGuesser *guesser,
+                                        const gchar             *name)
+{
+        // TODO: use a GHashTable for this.
+        GList *iter;
+        GUPnPDLNAProfileGuesserPrivate *priv;
+
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_GUESSER (guesser), NULL);
+
+        priv = guesser->priv;
+
+        for (iter = profiles_list[priv->relaxed_mode][priv->extended_mode];
+             iter;
+             iter = iter->next) {
+                GUPnPDLNAProfile *profile = GUPNP_DLNA_PROFILE (iter->data);
+
+                if (!g_strcmp0 (gupnp_dlna_profile_get_name (profile), name)) {
+                        return profile;
+                }
+        }
+
+        return NULL;
+}
+
+/**
+ * gupnp_dlna_profile_guesser_list_profiles:
+ * @guesser: The #GUPnPDLNAProfileGuesser whose profile list is required.
+ *
+ * Gets a list of the all DLNA profiles supported by @guesser.
+ *
+ * Returns: (transfer none) (element-type GUPnPDLNAProfile): A #GList
+ * of #GUPnPDLNAProfile on success, %NULL otherwise.
+ **/
+GList *
+gupnp_dlna_profile_guesser_list_profiles (GUPnPDLNAProfileGuesser *guesser)
+{
+        GUPnPDLNAProfileGuesserPrivate *priv;
+
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_GUESSER (guesser), NULL);
+
+        priv = guesser->priv;
+
+        return profiles_list[priv->relaxed_mode][priv->extended_mode];
+}
+
+/**
+ * gupnp_dlna_profile_guesser_get_relaxed_mode:
+ * @guesser: The #GUPnPDLNAProfileGuesser object.
+ *
+ * Returns: %TRUE if @guesser is in relaxed mode, %FALSE otherwise.
+ */
+gboolean
+gupnp_dlna_profile_guesser_get_relaxed_mode (GUPnPDLNAProfileGuesser *guesser)
+{
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_GUESSER (guesser), FALSE);
+
+        return guesser->priv->relaxed_mode;
+}
+
+/**
+ * gupnp_dlna_profile_guesser_get_extended_mode:
+ * @guesser: The #GUPnPDLNAProfileGuesser object.
+ *
+ * Returns: %TRUE if @guesser is in extended mode, %FALSE otherwise.
+ */
+gboolean
+gupnp_dlna_profile_guesser_get_extended_mode (GUPnPDLNAProfileGuesser *guesser)
+{
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_GUESSER (guesser), FALSE);
+
+        return guesser->priv->extended_mode;
+}
+
+/**
+ * gupnp_dlna_profile_guesser_cleanup:
+ *
+ * Cleans up the DLNA profiles. Provided to remove Valgrind noise. Not
+ * thread-safe. Do not call it if there is even a slightest chance
+ * that profile guessing will be performed during process
+ * lifetime. The profiles are not reloaded after cleanup.
+ */
+void
+gupnp_dlna_profile_guesser_cleanup (void)
+{
+        guint iter;
+
+        for (iter = 0; iter < 4; ++iter) {
+                gboolean relaxed = (iter > 1); /* F,F,T,T */
+                gboolean extended = ((iter) % 2 != 0); /* F,T,F,T */
+                guint rel_index = (relaxed ? 1 : 0);
+                guint ext_index = (extended ? 1 : 0);
+
+                g_list_free_full (profiles_list[rel_index][ext_index],
+                                  g_object_unref);
+                profiles_list[rel_index][ext_index] = NULL;
+        }
+}
diff --git a/libgupnp-dlna/gupnp-dlna-profile-guesser.h b/libgupnp-dlna/gupnp-dlna-profile-guesser.h
new file mode 100644
index 0000000..53d3af6
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-profile-guesser.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * Authors: Arun Raghavan <arun raghavan collabora co uk>
+ *          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_PROFILE_GUESSER_H__
+#define __GUPNP_DLNA_PROFILE_GUESSER_H__
+
+#include <glib-object.h>
+#include "gupnp-dlna-profile.h"
+
+G_BEGIN_DECLS
+
+#define GUPNP_TYPE_DLNA_PROFILE_GUESSER (gupnp_dlna_profile_guesser_get_type())
+
+#define GUPNP_DLNA_PROFILE_GUESSER(obj) \
+        (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                                     GUPNP_TYPE_DLNA_PROFILE_GUESSER, \
+                                     GUPnPDLNAProfileGuesser))
+
+#define GUPNP_DLNA_PROFILE_GUESSER_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_CAST ((klass), \
+                                  GUPNP_TYPE_DLNA_PROFILE_GUESSER, \
+                                  GUPnPDLNAProfileGuesserClass))
+
+#define GUPNP_IS_DLNA_PROFILE_GUESSER(obj) \
+        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                                     GUPNP_TYPE_DLNA_PROFILE_GUESSER))
+
+#define GUPNP_IS_DLNA_PROFILE_GUESSER_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+                                  GUPNP_TYPE_DLNA_PROFILE_GUESSER))
+
+#define GUPNP_DLNA_PROFILE_GUESSER_GET_CLASS(obj) \
+        (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                                    GUPNP_TYPE_DLNA_PROFILE_GUESSER, \
+                                    GUPnPDLNAProfileGuesserClass))
+
+typedef struct _GUPnPDLNAProfileGuesserPrivate GUPnPDLNAProfileGuesserPrivate;
+
+/**
+ * GUPnPDLNAProfileGuesser:
+ *
+ * The top-level object used to for DLNA profile guessing.
+ */
+typedef struct {
+        GObject parent;
+
+        GUPnPDLNAProfileGuesserPrivate *priv;
+} GUPnPDLNAProfileGuesser;
+
+/**
+ * GUPnPDLNAProfileGuesserClass:
+ * @parent_class: A #GObjectClass - parent of this class.
+ */
+typedef struct {
+        GObjectClass parent_class;
+} GUPnPDLNAProfileGuesserClass;
+
+GType
+gupnp_dlna_profile_guesser_get_type (void) G_GNUC_CONST;
+
+GUPnPDLNAProfileGuesser *
+gupnp_dlna_profile_guesser_new (gboolean relaxed_mode,
+                                gboolean extended_mode);
+
+/* Asynchronous API */
+gboolean
+gupnp_dlna_profile_guesser_guess_profile_async
+                                       (GUPnPDLNAProfileGuesser  *guesser,
+                                        const gchar              *uri,
+                                        guint                     timeout_in_ms,
+                                        GError                  **error);
+
+/* Synchronous API */
+GUPnPDLNAProfile *
+gupnp_dlna_profile_guesser_guess_profile_sync
+                                       (GUPnPDLNAProfileGuesser  *guesser,
+                                        const gchar              *uri,
+                                        guint                     timeout_in_ms,
+                                        GError                  **error);
+
+/* Get a GUPnPDLNAProfile by name */
+GUPnPDLNAProfile *
+gupnp_dlna_profile_guesser_get_profile (GUPnPDLNAProfileGuesser *guesser,
+                                        const gchar             *name);
+
+/* API to list all available profiles */
+GList *
+gupnp_dlna_profile_guesser_list_profiles (GUPnPDLNAProfileGuesser *guesser);
+
+gboolean
+gupnp_dlna_profile_guesser_get_relaxed_mode (GUPnPDLNAProfileGuesser *guesser);
+
+gboolean
+gupnp_dlna_profile_guesser_get_extended_mode (GUPnPDLNAProfileGuesser *guesser);
+
+void
+gupnp_dlna_profile_guesser_cleanup (void);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_PROFILE_GUESSER_H__ */
diff --git a/libgupnp-dlna/gupnp-dlna-profile-loader.c b/libgupnp-dlna/gupnp-dlna-profile-loader.c
new file mode 100644
index 0000000..e20a523
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-profile-loader.c
@@ -0,0 +1,1060 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Arun Raghavan <arun raghavan collabora co uk>
+ *          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/gstdio.h>
+#include <libxml/xmlreader.h>
+#include <libxml/relaxng.h>
+#include "gupnp-dlna-profile-loader.h"
+#include "gupnp-dlna-profile-backend.h"
+
+G_DEFINE_ABSTRACT_TYPE (GUPnPDLNAProfileLoader,
+                        gupnp_dlna_profile_loader,
+                        G_TYPE_OBJECT)
+
+#define DLNA_DATA_DIR DATA_DIR G_DIR_SEPARATOR_S "dlna-profiles"
+#define NODE_TYPE_ELEMENT_START 1
+#define NODE_TYPE_TEXT 3
+#define NODE_TYPE_ELEMENT_END 15
+
+enum {
+        PROP_0,
+
+        PROP_RELAXED_MODE,
+        PROP_EXTENDED_MODE
+};
+
+struct _GUPnPDLNAProfileLoaderPrivate {
+        GHashTable *restrictions;
+        GHashTable *profile_ids;
+        GHashTable *files_hash;
+        gboolean    relaxed_mode;
+        gboolean    extended_mode;
+};
+
+static void
+gupnp_dlna_profile_loader_run_pre_field (GUPnPDLNAProfileLoader *loader)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->pre_field != NULL);
+
+        loader_class->pre_field (loader);
+}
+
+static void
+gupnp_dlna_profile_loader_run_post_field (GUPnPDLNAProfileLoader *loader,
+                                          gchar                  *name,
+                                          gchar                  *type,
+                                          GList                  *values)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->post_field != NULL);
+
+        loader_class->post_field (loader,
+                                  name,
+                                  type,
+                                  values);
+}
+
+static void
+gupnp_dlna_profile_loader_run_pre_parent (GUPnPDLNAProfileLoader *loader)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->pre_parent != NULL);
+
+        loader_class->pre_parent (loader);
+}
+
+static void
+gupnp_dlna_profile_loader_run_post_parent (GUPnPDLNAProfileLoader *loader,
+                                           gchar *parent)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->post_parent != NULL);
+
+        loader_class->post_parent (loader, parent);
+}
+
+static void
+gupnp_dlna_profile_loader_run_pre_restriction (GUPnPDLNAProfileLoader *loader)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->pre_restriction != NULL);
+
+        loader_class->pre_restriction (loader);
+}
+
+static void
+gupnp_dlna_profile_loader_run_post_restriction
+                                      (GUPnPDLNAProfileLoader *loader,
+                                       gchar                  *restriction_type,
+                                       gchar                  *id,
+                                       gchar                  *name)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->post_restriction != NULL);
+
+        loader_class->post_restriction (loader,
+                                        restriction_type,
+                                        id,
+                                        name);
+}
+
+static void
+gupnp_dlna_profile_loader_run_pre_restrictions (GUPnPDLNAProfileLoader *loader)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->pre_restrictions != NULL);
+
+        loader_class->pre_restrictions (loader);
+}
+
+static void
+gupnp_dlna_profile_loader_run_post_restrictions (GUPnPDLNAProfileLoader *loader)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->post_restrictions != NULL);
+
+        loader_class->post_restrictions (loader);
+}
+
+static void
+gupnp_dlna_profile_loader_run_pre_dlna_profile (GUPnPDLNAProfileLoader *loader)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->pre_dlna_profile != NULL);
+
+        loader_class->pre_dlna_profile (loader);
+}
+
+static GUPnPDLNAProfile *
+gupnp_dlna_profile_loader_run_create_profile (GUPnPDLNAProfileLoader *loader,
+                                              GUPnPDLNAProfile       *base,
+                                              gchar                  *name,
+                                              gchar                  *mime,
+                                              gboolean                extended)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader), NULL);
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class),
+                              NULL);
+        g_return_val_if_fail (loader_class->create_profile != NULL, NULL);
+
+        return loader_class->create_profile (loader,
+                                             base,
+                                             name,
+                                             mime,
+                                             extended);
+}
+
+static void
+gupnp_dlna_profile_loader_run_post_dlna_profile (GUPnPDLNAProfileLoader *loader)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader));
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class));
+        g_return_if_fail (loader_class->post_dlna_profile != NULL);
+
+        loader_class->post_dlna_profile (loader);
+}
+
+static GList *
+gupnp_dlna_profile_loader_run_cleanup (GUPnPDLNAProfileLoader *loader,
+                                       GList *profiles)
+{
+        GUPnPDLNAProfileLoaderClass *loader_class;
+
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader), NULL);
+
+        loader_class = GUPNP_DLNA_PROFILE_LOADER_GET_CLASS (loader);
+
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER_CLASS (loader_class),
+                              NULL);
+        g_return_val_if_fail (loader_class->cleanup != NULL, NULL);
+
+        return loader_class->cleanup (loader,
+                                      profiles);
+}
+
+static void
+gupnp_dlna_profile_loader_get_property (GObject    *object,
+                                        guint       prop_id,
+                                        GValue     *value,
+                                        GParamSpec *pspec)
+{
+        GUPnPDLNAProfileLoader *loader = GUPNP_DLNA_PROFILE_LOADER (object);
+        GUPnPDLNAProfileLoaderPrivate *priv = loader->priv;
+
+        switch (prop_id) {
+        case PROP_RELAXED_MODE:
+                g_value_set_boolean (value, priv->relaxed_mode);
+                break;
+
+        case PROP_EXTENDED_MODE:
+                g_value_set_boolean (value, priv->extended_mode);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gupnp_dlna_profile_loader_set_property (GObject      *object,
+                                        guint         prop_id,
+                                        const GValue *value,
+                                        GParamSpec   *pspec)
+{
+        GUPnPDLNAProfileLoader *loader = GUPNP_DLNA_PROFILE_LOADER (object);
+        GUPnPDLNAProfileLoaderPrivate *priv = loader->priv;
+
+        switch (prop_id) {
+        case PROP_RELAXED_MODE:
+                priv->relaxed_mode = g_value_get_boolean (value);
+                break;
+
+        case PROP_EXTENDED_MODE:
+                priv->extended_mode = g_value_get_boolean (value);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gupnp_dlna_profile_loader_dispose (GObject *object)
+{
+        GUPnPDLNAProfileLoader *loader = GUPNP_DLNA_PROFILE_LOADER (object);
+        GUPnPDLNAProfileLoaderPrivate *priv = loader->priv;
+
+        g_clear_pointer (&priv->restrictions, g_hash_table_unref);
+        g_clear_pointer (&priv->profile_ids, g_hash_table_unref);
+        g_clear_pointer (&priv->files_hash, g_hash_table_unref);
+
+        G_OBJECT_CLASS (gupnp_dlna_profile_loader_parent_class)->dispose
+                                        (object);
+}
+
+static void
+gupnp_dlna_profile_loader_class_init
+                              (GUPnPDLNAProfileLoaderClass *loader_class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (loader_class);
+        GParamSpec *spec;
+
+        object_class->get_property = gupnp_dlna_profile_loader_get_property;
+        object_class->set_property = gupnp_dlna_profile_loader_set_property;
+        object_class->dispose = gupnp_dlna_profile_loader_dispose;
+        loader_class->pre_field = NULL;
+        loader_class->post_field = NULL;
+        loader_class->pre_parent = NULL;
+        loader_class->post_parent = NULL;
+        loader_class->pre_restriction = NULL;
+        loader_class->post_restriction = NULL;
+        loader_class->pre_restrictions = NULL;
+        loader_class->post_restrictions = NULL;
+        loader_class->pre_dlna_profile = NULL;
+        loader_class->create_profile = NULL;
+        loader_class->post_dlna_profile = NULL;
+        loader_class->cleanup = NULL;
+
+        spec = g_param_spec_boolean ("relaxed-mode",
+                                     "Relaxed mode",
+                                     "Whether loader loads relaxed profiles",
+                                     TRUE,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_property (object_class,
+                                         PROP_RELAXED_MODE,
+                                         spec);
+
+        spec = g_param_spec_boolean ("extended-mode",
+                                     "Extended mode",
+                                     "Whether loader loads extended profiles",
+                                     TRUE,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_property (object_class,
+                                         PROP_EXTENDED_MODE,
+                                         spec);
+
+        g_type_class_add_private (loader_class,
+                                  sizeof (GUPnPDLNAProfileLoaderPrivate));
+}
+
+static void
+gupnp_dlna_profile_loader_init (GUPnPDLNAProfileLoader *self)
+{
+        GUPnPDLNAProfileLoaderPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE
+                                        (self,
+                                         GUPNP_TYPE_DLNA_PROFILE_LOADER,
+                                         GUPnPDLNAProfileLoaderPrivate);
+
+        priv->restrictions = g_hash_table_new_full (g_str_hash,
+                                                    g_str_equal,
+                                                    g_free,
+                                                    NULL);
+        priv->profile_ids = g_hash_table_new_full (g_str_hash,
+                                                   g_str_equal,
+                                                   g_free,
+                                                   g_object_unref);
+        priv->files_hash = g_hash_table_new_full (g_str_hash,
+                                                  g_str_equal,
+                                                  g_free,
+                                                  NULL);
+        self->priv = priv;
+}
+
+static GUPnPDLNAFieldValue *
+get_value (xmlTextReaderPtr reader)
+{
+        GUPnPDLNAFieldValue *value = NULL;
+        xmlChar *curr = xmlTextReaderName (reader);
+        int ret = 1;
+
+        /* This function may be called with reader pointing to a <field> or
+         * the element just below a <field>. In the former case, we move the
+         * cursor forward and then continue processing. */
+        if (xmlStrEqual (curr, BAD_CAST ("field")))
+                ret = xmlTextReaderRead (reader);
+        xmlFree (curr);
+
+        while (ret == 1) {
+                xmlChar *tag = xmlTextReaderName (reader);
+
+                if (xmlTextReaderNodeType (reader) == NODE_TYPE_ELEMENT_START &&
+                    xmlStrEqual (tag, BAD_CAST ("value"))) {
+                        /* <value> */
+                        gint node_type;
+
+                        /* Note: This assumes you won't have a comment in the
+                         *       middle of your text */
+                        do {
+                                ret = xmlTextReaderRead (reader);
+                                node_type = xmlTextReaderNodeType (reader);
+                        } while (ret == 1 &&
+                                 node_type != NODE_TYPE_TEXT &&
+                                 node_type != NODE_TYPE_ELEMENT_END);
+
+                        /* We're now at the real text between a <value> and a
+                         * </value> */
+
+                        if (node_type == NODE_TYPE_TEXT) {
+                                xmlChar *string = xmlTextReaderValue (reader);
+
+                                value = gupnp_dlna_field_value_new_single
+                                                            ((gchar *) string);
+                                if (string)
+                                        xmlFree (string);
+                        }
+                }
+
+                if (xmlTextReaderNodeType (reader) == NODE_TYPE_ELEMENT_END &&
+                    xmlStrEqual (tag, BAD_CAST ("value"))) {
+                        /* </value> */
+                        xmlFree (tag);
+
+                        break;
+                }
+
+                xmlFree (tag);
+                ret = xmlTextReaderRead (reader);
+        }
+
+        if (!value)
+                g_warning ("Empty <value>s are illegal");
+
+        return value;
+}
+
+static GUPnPDLNAFieldValue *
+get_range (xmlTextReaderPtr reader)
+{
+        xmlChar *min = xmlTextReaderGetAttribute (reader, BAD_CAST ("min"));
+        xmlChar *max = xmlTextReaderGetAttribute (reader, BAD_CAST ("max"));
+        GUPnPDLNAFieldValue *value = gupnp_dlna_field_value_new_range
+                                        ((gchar *) min,
+                                         (gchar *) max);
+
+        if (min)
+                xmlFree (min);
+        if (max)
+                xmlFree (max);
+
+        return value;
+}
+
+static void
+process_field (GUPnPDLNAProfileLoader *loader,
+               xmlTextReaderPtr        reader)
+{
+        xmlChar *name = NULL;
+        xmlChar *type = NULL;
+        xmlChar *used;
+        GList *values = NULL;
+        gboolean done = FALSE;
+        gboolean skip = FALSE;
+        GUPnPDLNAFieldValue *value = NULL;
+        GUPnPDLNAProfileLoaderPrivate *priv = loader->priv;
+
+        gupnp_dlna_profile_loader_run_pre_field (loader);
+
+        /*
+         * Parse the 'used' attribute and figure out the mode we
+         * need to follow.
+         */
+        used = xmlTextReaderGetAttribute (reader, BAD_CAST ("used"));
+        if (used) {
+                if ((priv->relaxed_mode == FALSE) &&
+                    xmlStrEqual (used, BAD_CAST ("in-relaxed"))) {
+                        skip = TRUE;
+                } else if ((priv->relaxed_mode == TRUE) &&
+                           (xmlStrEqual (used, BAD_CAST ("in-strict")))) {
+                        skip = TRUE;
+                }
+
+                xmlFree (used);
+        }
+
+        if (!skip) {
+                name = xmlTextReaderGetAttribute (reader, BAD_CAST ("name"));
+                type = xmlTextReaderGetAttribute (reader, BAD_CAST ("type"));
+        }
+
+        /* I don't like it - we should check done first, then try to
+         * read next tag. But this is how it was done in original
+         * code, so I am not touching it for now - krnowak.
+         */
+        while ((xmlTextReaderRead (reader) == 1) && !done) {
+                xmlChar *tag = xmlTextReaderName (reader);
+
+                switch (xmlTextReaderNodeType (reader)) {
+                case NODE_TYPE_ELEMENT_START:
+                        if (skip)
+                                break;
+
+                        if (xmlStrEqual (tag, BAD_CAST ("range"))) {
+                                /* <range> */
+                                value = get_range (reader);
+                        } else if (xmlStrEqual (tag, BAD_CAST ("value"))) {
+                                /* <value> */
+                                value = get_value (reader);
+                        }
+
+                        if (value)
+                                values = g_list_prepend (values, value);
+                        break;
+
+                case NODE_TYPE_ELEMENT_END:
+                        if (xmlStrEqual (tag, BAD_CAST ("field")))
+                                /* </field> */
+                                done = TRUE;
+
+                        break;
+
+                default:
+                        break;
+                }
+
+                xmlFree (tag);
+        }
+
+        if (values)
+                values = g_list_reverse (values);
+
+        gupnp_dlna_profile_loader_run_post_field (loader,
+                                                  (gchar *)name,
+                                                  (gchar *)type,
+                                                  values);
+
+        if (name)
+                xmlFree (name);
+        if (type)
+                xmlFree (type);
+        if (values) {
+                g_list_free_full (values,
+                                  (GDestroyNotify) gupnp_dlna_field_value_free);
+        }
+}
+
+static void
+process_parent (GUPnPDLNAProfileLoader *loader,
+                xmlTextReaderPtr        reader)
+{
+        xmlChar *parent = NULL;
+        xmlChar *used = NULL;
+        GUPnPDLNAProfileLoaderPrivate *priv = loader->priv;
+
+        gupnp_dlna_profile_loader_run_pre_parent (loader);
+
+        /*
+         * Check to see if we need to follow any relaxed/strict mode
+         * restrictions.
+         */
+        used = xmlTextReaderGetAttribute (reader, BAD_CAST ("used"));
+        if (used) {
+                gboolean go_out = FALSE;
+
+                if ((priv->relaxed_mode == FALSE) &&
+                    xmlStrEqual (used, BAD_CAST ("in-relaxed"))) {
+                        go_out = TRUE;
+                } else if ((priv->relaxed_mode == TRUE) &&
+                           (xmlStrEqual (used, BAD_CAST ("in-strict")))) {
+                        go_out = TRUE;
+                }
+                xmlFree (used);
+                if (go_out)
+                        goto out;
+        }
+
+        parent = xmlTextReaderGetAttribute (reader, BAD_CAST ("name"));
+
+        if (!g_hash_table_contains (priv->restrictions, parent))
+                g_warning ("Could not find parent restriction: %s", parent);
+
+ out:
+        gupnp_dlna_profile_loader_run_post_parent (loader, (gchar*) parent);
+
+        if (parent)
+                xmlFree (parent);
+}
+
+static void
+process_restriction (GUPnPDLNAProfileLoader *loader,
+                     xmlTextReaderPtr        reader)
+{
+        xmlChar *used;
+        gboolean done = FALSE;
+        gboolean skip = FALSE;
+        xmlChar *id = NULL;
+        xmlChar *type = NULL;
+        gchar *name = NULL;
+        GUPnPDLNAProfileLoaderPrivate *priv = loader->priv;
+
+        gupnp_dlna_profile_loader_run_pre_restriction (loader);
+        /*
+         * First we parse the 'used' attribute and figure out
+         * the mode we need to comply to.
+         */
+        used = xmlTextReaderGetAttribute (reader, BAD_CAST ("used"));
+        if (used) {
+                if ((priv->relaxed_mode == FALSE) &&
+                    xmlStrEqual (used, BAD_CAST ("in-relaxed"))) {
+                        skip = TRUE;
+                } else if ((priv->relaxed_mode == TRUE) &&
+                           (xmlStrEqual (used, BAD_CAST ("in-strict")))) {
+                        skip = TRUE;
+                }
+                xmlFree (used);
+        }
+
+        if (!skip) {
+                id = xmlTextReaderGetAttribute (reader, BAD_CAST ("id"));
+                type = xmlTextReaderGetAttribute (reader, BAD_CAST ("type"));
+        }
+
+        /* I don't like it - we should check done first, then try to
+         * read next tag. But this is how it was done in original
+         * code, so I am not touching it for now - krnowak.
+         */
+        while ((xmlTextReaderRead (reader) == 1) && !done) {
+                xmlChar *tag = xmlTextReaderName (reader);
+
+                switch (xmlTextReaderNodeType (reader)) {
+                case NODE_TYPE_ELEMENT_START:
+                        if (skip)
+                                break;
+
+                        if (xmlStrEqual (tag, BAD_CAST ("field"))) {
+                                /* <field> */
+                                xmlChar *field;
+
+                                field = xmlTextReaderGetAttribute
+                                        (reader,
+                                         BAD_CAST ("name"));
+
+                                if (xmlStrEqual (field, BAD_CAST ("name"))) {
+                                        GUPnPDLNAFieldValue *value = get_value
+                                                (reader);
+
+                                        if (value) {
+                                                /* get_value returns
+                                                   single type
+                                                   value. */
+                                                name =
+                                                 g_strdup (value->value.single);
+                                                gupnp_dlna_field_value_free
+                                                        (value);
+                                        }
+                                } else
+                                        process_field (loader, reader);
+
+                                xmlFree (field);
+                        } else if (xmlStrEqual (tag, BAD_CAST ("parent"))) {
+                                /* <parent> */
+                                process_parent (loader, reader);
+                        }
+
+                        break;
+
+                case NODE_TYPE_ELEMENT_END:
+                        if (xmlStrEqual (tag, BAD_CAST ("restriction")))
+                                /* </restriction> */
+                                done = TRUE;
+
+                        break;
+
+                default:
+                        break;
+                }
+
+                xmlFree (tag);
+        }
+
+        if (skip)
+                goto out;
+
+        if (id)
+                g_hash_table_add (priv->restrictions, g_strdup ((gchar *) id));
+
+out:
+        gupnp_dlna_profile_loader_run_post_restriction (loader,
+                                                        (gchar *) type,
+                                                        (gchar *) id,
+                                                        name);
+        if (type)
+                xmlFree (type);
+        if (id)
+                xmlFree (id);
+        g_free (name);
+}
+
+static void
+process_restrictions (GUPnPDLNAProfileLoader *loader,
+                      xmlTextReaderPtr        reader)
+{
+        gboolean done = FALSE;
+
+        gupnp_dlna_profile_loader_run_pre_restrictions (loader);
+
+        while (!done && xmlTextReaderRead (reader) == 1) {
+                xmlChar *tag = xmlTextReaderName (reader);
+
+                switch (xmlTextReaderNodeType (reader)) {
+                case NODE_TYPE_ELEMENT_START:
+                        if (xmlStrEqual (tag, BAD_CAST ("restriction"))) {
+                                /* <restriction> */
+                                process_restriction (loader, reader);
+                        }
+
+                        break;
+
+                case NODE_TYPE_ELEMENT_END:
+                        if (xmlStrEqual (tag, BAD_CAST ("restrictions")))
+                                /* </restrictions> */
+                                done = TRUE;
+
+                default:
+                        break;
+                }
+
+                xmlFree (tag);
+        }
+
+        gupnp_dlna_profile_loader_run_post_restrictions (loader);
+}
+
+static void
+process_dlna_profile (GUPnPDLNAProfileLoader  *loader,
+                      xmlTextReaderPtr         reader,
+                      GList                  **profiles)
+{
+        GUPnPDLNAProfile *profile = NULL;
+        GUPnPDLNAProfile *base = NULL;
+        xmlChar *name;
+        xmlChar *mime;
+        xmlChar *id;
+        xmlChar *base_profile;
+        xmlChar *extended;
+        gboolean done = FALSE;
+        gboolean is_extended = FALSE;
+        GUPnPDLNAProfileLoaderPrivate *priv = loader->priv;
+
+        gupnp_dlna_profile_loader_run_pre_dlna_profile (loader);
+
+        name = xmlTextReaderGetAttribute (reader, BAD_CAST ("name"));
+        mime = xmlTextReaderGetAttribute (reader, BAD_CAST ("mime"));
+        extended = xmlTextReaderGetAttribute (reader, BAD_CAST ("extended"));
+        id = xmlTextReaderGetAttribute (reader, BAD_CAST ("id"));
+        base_profile = xmlTextReaderGetAttribute (reader,
+                                                  BAD_CAST ("base-profile"));
+
+        if (!name) {
+                g_assert (mime == NULL);
+
+                /* We need a non-NULL string to not trigger asserts in the
+                 * places these are used. Profiles without names are used
+                 * only for inheritance, not for actual matching. */
+                name = xmlStrdup (BAD_CAST (""));
+                mime = xmlStrdup (BAD_CAST (""));
+        }
+
+        if (extended && xmlStrEqual (extended, BAD_CAST ("true"))) {
+                /* If we're not in extended mode, skip this profile */
+                if (!priv->extended_mode)
+                        goto out;
+
+                is_extended = TRUE;
+        }
+
+        /* I don't like it - we should check done first, then try to
+         * read next tag. But this is how it was done in original
+         * code, so I am not touching it for now - krnowak.
+         */
+        while ((xmlTextReaderRead (reader) == 1) && !done) {
+                xmlChar *tag = xmlTextReaderName (reader);
+
+                switch (xmlTextReaderNodeType (reader)) {
+                case NODE_TYPE_ELEMENT_START:
+                        if (xmlStrEqual (tag, BAD_CAST ("restriction")))
+                                process_restriction (loader, reader);
+                        else if (xmlStrEqual (tag, BAD_CAST ("parent")))
+                                process_parent (loader, reader);
+                        break;
+
+                case NODE_TYPE_ELEMENT_END:
+                        if (xmlStrEqual (tag, BAD_CAST ("dlna-profile")))
+                                done = TRUE;
+
+                default:
+                        break;
+                }
+
+                xmlFree (tag);
+        }
+
+        if (base_profile) {
+                base = g_hash_table_lookup (priv->profile_ids, base_profile);
+                if (!base)
+                        g_warning ("Invalid base-profile reference");
+        }
+
+
+        profile = gupnp_dlna_profile_loader_run_create_profile (loader,
+                                                                base,
+                                                                (gchar *) name,
+                                                                (gchar *) mime,
+                                                                is_extended);
+
+        *profiles = g_list_prepend (*profiles, profile);
+
+        if (id) {
+                g_hash_table_replace (priv->profile_ids,
+                                      g_strdup ((gchar *) id),
+                                      g_object_ref (profile));
+        }
+
+out:
+        gupnp_dlna_profile_loader_run_post_dlna_profile (loader);
+
+        if (id)
+                xmlFree (id);
+        if (mime)
+                xmlFree (mime);
+        if (name)
+                xmlFree (name);
+        if (extended)
+                xmlFree (extended);
+        if (base_profile)
+                xmlFree (base_profile);
+}
+
+static void
+gupnp_dlna_profile_loader_get_from_file (GUPnPDLNAProfileLoader  *loader,
+                                         const char              *file_name,
+                                         GList                  **profiles);
+
+static void
+process_include (GUPnPDLNAProfileLoader  *loader,
+                 xmlTextReaderPtr         reader,
+                 GList                  **profiles)
+{
+        xmlChar *path;
+        gchar *g_path;
+
+        path = xmlTextReaderGetAttribute (reader, BAD_CAST ("ref"));
+        g_path = g_strdup ((gchar *) path);
+        if (path)
+                xmlFree (path);
+
+        if (!g_path_is_absolute (g_path)) {
+                gchar *tmp = g_build_filename (DLNA_DATA_DIR,
+                                               g_path,
+                                               NULL);
+                g_free (g_path);
+                g_path = tmp;
+        }
+
+        gupnp_dlna_profile_loader_get_from_file (loader, g_path, profiles);
+        g_free (g_path);
+}
+
+GUPnPDLNAProfileLoader *
+gupnp_dlna_profile_loader_get_default (gboolean relaxed_mode,
+                                       gboolean extended_mode)
+{
+        return gupnp_dlna_profile_backend_get_loader (relaxed_mode,
+                                                      extended_mode);
+}
+
+/* This can go away once we have a glib function to canonicalize paths (see
+ * https://bugzilla.gnome.org/show_bug.cgi?id=111848
+ *
+ * The implementation is not generic enough, but sufficient for our use. The
+ * idea is taken from Tristan Van Berkom's comment in the bug mentioned above:
+ *
+ *   1. cd dirname(path)
+ *   2. absdir = $CWD
+ *   3. cd $OLDPWD
+ *   4. abspath = absdir + basename(path)
+ */
+static gchar *
+canonicalize_path_name (const char *path)
+{
+        gchar *dir_name = NULL, *file_name = NULL, *abs_dir = NULL,
+              *old_dir = NULL, *ret = NULL;
+
+        if (g_path_is_absolute (path))
+                return g_strdup (path);
+
+        old_dir = g_get_current_dir ();
+        dir_name = g_path_get_dirname (path);
+
+        if (g_chdir (dir_name) < 0) {
+                ret = g_strdup (path);
+                goto out;
+        }
+
+        abs_dir = g_get_current_dir ();
+        g_chdir (old_dir);
+
+        file_name = g_path_get_basename (path);
+        ret = g_build_filename (abs_dir, file_name, NULL);
+
+out:
+        g_free (dir_name);
+        g_free (file_name);
+        g_free (abs_dir);
+        g_free (old_dir);
+
+        return ret;
+}
+
+static void
+gupnp_dlna_profile_loader_get_from_file (GUPnPDLNAProfileLoader  *loader,
+                                         const char              *file_name,
+                                         GList                  **profiles)
+{
+        gchar *path = canonicalize_path_name (file_name);
+        xmlTextReaderPtr reader = NULL;
+        xmlRelaxNGParserCtxtPtr rngp = NULL;
+        xmlRelaxNGPtr rngs = NULL;
+        GUPnPDLNAProfileLoaderPrivate *priv = loader->priv;
+
+        if (g_hash_table_contains (priv->files_hash, path))
+                goto out;
+        else
+                g_hash_table_add (priv->files_hash, g_strdup (path));
+
+        reader = xmlNewTextReaderFilename (path);
+        if (!reader)
+                goto out;
+
+        /* Load the schema for validation */
+        rngp = xmlRelaxNGNewParserCtxt (DLNA_DATA_DIR
+                                        G_DIR_SEPARATOR_S
+                                        "dlna-profiles.rng");
+        if (!rngp)
+                goto out;
+        rngs = xmlRelaxNGParse (rngp);
+        if (!rngs)
+                goto out;
+        if (xmlTextReaderRelaxNGSetSchema (reader, rngs) < 0)
+                goto out;
+
+        while (xmlTextReaderRead (reader) == 1) {
+                xmlChar *tag = xmlTextReaderName (reader);
+
+                switch (xmlTextReaderNodeType (reader)) {
+                        case NODE_TYPE_ELEMENT_START:
+                                if (xmlStrEqual (tag, BAD_CAST ("include"))) {
+                                        /* <include> */
+                                        process_include (loader,
+                                                         reader,
+                                                         profiles);
+                                } else if (xmlStrEqual (tag,
+                                        BAD_CAST ("restrictions"))) {
+                                        /* <restrictions> */
+                                        process_restrictions (loader,
+                                                              reader);
+                                } else if (xmlStrEqual (tag,
+                                        BAD_CAST ("dlna-profile"))) {
+                                        /* <dlna-profile> */
+                                        process_dlna_profile (loader,
+                                                              reader,
+                                                              profiles);
+
+                                }
+
+                                break;
+
+                        default:
+                                break;
+                }
+
+                xmlFree (tag);
+        }
+
+
+out:
+        g_free (path);
+        if (reader)
+                xmlFreeTextReader (reader);
+        if (rngs)
+                xmlRelaxNGFree (rngs);
+        if (rngp)
+                xmlRelaxNGFreeParserCtxt (rngp);
+}
+
+static GList *
+gupnp_dlna_profile_loader_get_from_dir (GUPnPDLNAProfileLoader *loader,
+                                        gchar                  *profile_dir)
+{
+        GDir *dir;
+        GList *profiles = NULL;
+
+        if ((dir = g_dir_open (profile_dir, 0, NULL))) {
+                const gchar *entry;
+
+                while ((entry = g_dir_read_name (dir))) {
+                        gchar *path = g_build_filename (profile_dir,
+                                                        entry,
+                                                        NULL);
+
+                        if (g_str_has_suffix (entry, ".xml") &&
+                            g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
+                                gupnp_dlna_profile_loader_get_from_file
+                                        (loader,
+                                         path,
+                                         &profiles);
+                        }
+
+                        g_free (path);
+                }
+
+                g_dir_close (dir);
+        }
+
+        return profiles;
+}
+
+GList *
+gupnp_dlna_profile_loader_get_from_disk (GUPnPDLNAProfileLoader *loader)
+{
+        GList *profiles;
+
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE_LOADER (loader), NULL);
+
+        profiles = gupnp_dlna_profile_loader_get_from_dir (loader,
+                                                           DLNA_DATA_DIR);
+
+        profiles = g_list_reverse (profiles);
+
+        return gupnp_dlna_profile_loader_run_cleanup (loader, profiles);
+}
diff --git a/libgupnp-dlna/gupnp-dlna-profile-loader.h b/libgupnp-dlna/gupnp-dlna-profile-loader.h
new file mode 100644
index 0000000..dbb8862
--- /dev/null
+++ b/libgupnp-dlna/gupnp-dlna-profile-loader.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Zeeshan Ali <zeeshanak gnome org>
+ *                      <zeeshan ali nokia com>
+ *          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_PROFILE_LOADER_H__
+#define __GUPNP_DLNA_PROFILE_LOADER_H__
+
+#include <glib-object.h>
+#include "gupnp-dlna-profile.h"
+#include "gupnp-dlna-field-value.h"
+
+G_BEGIN_DECLS
+
+#define GUPNP_TYPE_DLNA_PROFILE_LOADER (gupnp_dlna_profile_loader_get_type ())
+
+#define GUPNP_DLNA_PROFILE_LOADER(obj) \
+        (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                                     GUPNP_TYPE_DLNA_PROFILE_LOADER, \
+                                     GUPnPDLNAProfileLoader))
+
+#define GUPNP_DLNA_PROFILE_LOADER_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_CAST ((klass), \
+                                  GUPNP_TYPE_DLNA_PROFILE_LOADER, \
+                                  GUPnPDLNAProfileLoaderClass))
+
+#define GUPNP_IS_DLNA_PROFILE_LOADER(obj) \
+        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                                     GUPNP_TYPE_DLNA_PROFILE_LOADER))
+
+#define GUPNP_IS_DLNA_PROFILE_LOADER_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+                                  GUPNP_TYPE_DLNA_PROFILE_LOADER))
+
+#define GUPNP_DLNA_PROFILE_LOADER_GET_CLASS(obj) \
+        (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                                    GUPNP_TYPE_DLNA_PROFILE_LOADER, \
+                                    GUPnPDLNAProfileLoaderClass))
+
+typedef struct _GUPnPDLNAProfileLoaderPrivate GUPnPDLNAProfileLoaderPrivate;
+
+typedef struct {
+        GObject parent;
+
+        GUPnPDLNAProfileLoaderPrivate *priv;
+} GUPnPDLNAProfileLoader;
+
+typedef struct {
+        GObjectClass parent_class;
+
+        /* virtuals */
+        void
+        (* pre_field) (GUPnPDLNAProfileLoader *loader);
+
+        void
+        (* post_field) (GUPnPDLNAProfileLoader *loader,
+                        const gchar            *name,
+                        const gchar            *type,
+                        GList                  *values);
+
+        void
+        (* pre_parent) (GUPnPDLNAProfileLoader *loader);
+
+        void
+        (* post_parent) (GUPnPDLNAProfileLoader *loader,
+                         const gchar            *parent);
+
+        void
+        (* pre_restriction) (GUPnPDLNAProfileLoader *loader);
+
+        void
+        (* post_restriction) (GUPnPDLNAProfileLoader *loader,
+                              const gchar            *restriction_type,
+                              const gchar            *id,
+                              const gchar            *name);
+
+        void
+        (* pre_restrictions) (GUPnPDLNAProfileLoader *loader);
+
+        void
+        (* post_restrictions) (GUPnPDLNAProfileLoader *loader);
+
+        void
+        (* pre_dlna_profile) (GUPnPDLNAProfileLoader *loader);
+
+        GUPnPDLNAProfile *
+        (* create_profile) (GUPnPDLNAProfileLoader *loader,
+                            GUPnPDLNAProfile       *base,
+                            const gchar            *name,
+                            const gchar            *mime,
+                            gboolean                extended);
+
+        void
+        (* post_dlna_profile) (GUPnPDLNAProfileLoader *loader);
+
+        GList *
+        (* cleanup) (GUPnPDLNAProfileLoader *loader,
+                     GList                  *profiles);
+} GUPnPDLNAProfileLoaderClass;
+
+GType
+gupnp_dlna_profile_loader_get_type (void);
+
+GUPnPDLNAProfileLoader *
+gupnp_dlna_profile_loader_get_default (gboolean relaxed_mode,
+                                       gboolean extended_mode);
+
+GList *
+gupnp_dlna_profile_loader_get_from_disk (GUPnPDLNAProfileLoader *loader);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_PROFILE_LOADER_H__ */
diff --git a/libgupnp-dlna/gupnp-dlna-profile.c b/libgupnp-dlna/gupnp-dlna-profile.c
index 38494db..79f49a9 100644
--- a/libgupnp-dlna/gupnp-dlna-profile.c
+++ b/libgupnp-dlna/gupnp-dlna-profile.c
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation.
  *
  * Authors: Arun Raghavan <arun raghavan collabora co uk>
+ *          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
@@ -20,43 +22,31 @@
  */
 
 #include "gupnp-dlna-profile.h"
-#include "gupnp-dlna-profile-private.h"
-#include <gst/gstminiobject.h>
 
 /**
  * SECTION:gupnp-dlna-profile
  * @short_description: Object representing a DLNA profile
  *
- * The #GUPnPDLNADiscoverer object provides a few APIs that return
- * #GUPnPDLNAProfile objects. These represent a single DLNA profile. Each
- * #GUPnPDLNAProfile has a name (the name of the DLNA profile), the
- * corresponding MIME type, and a #GstEncodingProfile which represents the
- * various audio/video/container restrictions specified for that DLNA profile.
+ * The #GUPnPDLNAProfileGuesser object provides a few APIs that return
+ * #GUPnPDLNAProfile objects. These represent a single DLNA
+ * profile. Each #GUPnPDLNAProfile has a name (the name of the DLNA
+ * profile) and the corresponding MIME type.
+ *
+ * Public representation of the various audio/container/image/video
+ * restrictions specified for that DLNA profile is to be added.
  */
 G_DEFINE_TYPE (GUPnPDLNAProfile, gupnp_dlna_profile, G_TYPE_OBJECT)
 
-#define GET_PRIVATE(o)                                          \
-        (G_TYPE_INSTANCE_GET_PRIVATE ((o),                      \
-                                      GUPNP_TYPE_DLNA_PROFILE,  \
-                                      GUPnPDLNAProfilePrivate))
-
-typedef struct _GUPnPDLNAProfilePrivate GUPnPDLNAProfilePrivate;
-
 struct _GUPnPDLNAProfilePrivate {
-        gchar              *name;
-        gchar              *mime;
-        GstCaps            *container_caps;
-        GstCaps            *video_caps;
-        GstCaps            *audio_caps;
-        gboolean           extended;
-        GstEncodingProfile *enc_profile;
+        gchar    *name;
+        gchar    *mime;
+        gboolean  extended;
 };
 
 enum {
         PROP_0,
         PROP_DLNA_NAME,
         PROP_DLNA_MIME,
-        PROP_ENCODING_PROFILE,
         PROP_DLNA_EXTENDED,
 };
 
@@ -67,7 +57,7 @@ gupnp_dlna_profile_get_property (GObject    *object,
                                  GParamSpec *pspec)
 {
         GUPnPDLNAProfile *self = GUPNP_DLNA_PROFILE (object);
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
+        GUPnPDLNAProfilePrivate *priv = self->priv;
 
         switch (property_id) {
                 case PROP_DLNA_NAME:
@@ -78,11 +68,6 @@ gupnp_dlna_profile_get_property (GObject    *object,
                         g_value_set_string (value, priv->mime);
                         break;
 
-                case PROP_ENCODING_PROFILE:
-                        gst_value_set_mini_object (value,
-                                        GST_MINI_OBJECT (priv->enc_profile));
-                        break;
-
                 case PROP_DLNA_EXTENDED:
                         g_value_set_boolean (value, priv->extended);
                         break;
@@ -102,27 +87,26 @@ gupnp_dlna_profile_set_property (GObject      *object,
                                  GParamSpec   *pspec)
 {
         GUPnPDLNAProfile *self = GUPNP_DLNA_PROFILE (object);
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
+        GUPnPDLNAProfilePrivate *priv = self->priv;
 
         switch (property_id) {
-                case PROP_DLNA_NAME:
-                        g_free (priv->name);
-                        priv->name = g_value_dup_string (value);
-                        break;
-
-                case PROP_DLNA_MIME:
-                        g_free (priv->mime);
-                        priv->mime = g_value_dup_string (value);
-                        break;
-
-                case PROP_DLNA_EXTENDED:
-                        priv->extended = g_value_get_boolean (value);
-                        break;
-
-                default:
-                        G_OBJECT_WARN_INVALID_PROPERTY_ID
-                                (object, property_id, pspec);
-                        break;
+        case PROP_DLNA_NAME:
+                g_free (priv->name);
+                priv->name = g_value_dup_string (value);
+                break;
+
+        case PROP_DLNA_MIME:
+                g_free (priv->mime);
+                priv->mime = g_value_dup_string (value);
+                break;
+
+        case PROP_DLNA_EXTENDED:
+                priv->extended = g_value_get_boolean (value);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+                break;
         }
 }
 
@@ -130,21 +114,11 @@ static void
 gupnp_dlna_profile_finalize (GObject *object)
 {
         GUPnPDLNAProfile *self = GUPNP_DLNA_PROFILE (object);
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
+        GUPnPDLNAProfilePrivate *priv = self->priv;
 
         g_free (priv->name);
         g_free (priv->mime);
 
-        if (priv->container_caps)
-                gst_caps_unref (priv->container_caps);
-        if (priv->audio_caps)
-                gst_caps_unref (priv->audio_caps);
-        if (priv->video_caps)
-                gst_caps_unref (priv->video_caps);
-
-        if (priv->enc_profile)
-                gst_encoding_profile_unref (priv->enc_profile);
-
         G_OBJECT_CLASS (gupnp_dlna_profile_parent_class)->finalize (object);
 }
 
@@ -154,20 +128,28 @@ gupnp_dlna_profile_class_init (GUPnPDLNAProfileClass *klass)
         GObjectClass *object_class = G_OBJECT_CLASS (klass);
         GParamSpec *pspec;
 
-        g_type_class_add_private (klass, sizeof (GUPnPDLNAProfilePrivate));
-
         object_class->get_property = gupnp_dlna_profile_get_property;
         object_class->set_property = gupnp_dlna_profile_set_property;
         object_class->finalize = gupnp_dlna_profile_finalize;
 
+        /**
+         * GUPnPDLNAProfile:name:
+         *
+         * Name of the DLNA profile.
+         */
         pspec = g_param_spec_string ("name",
                                      "DLNA profile name",
-                                     "The name of the DLNA profile ",
+                                     "The name of the DLNA profile",
                                      NULL,
                                      G_PARAM_READWRITE |
                                      G_PARAM_CONSTRUCT_ONLY);
         g_object_class_install_property (object_class, PROP_DLNA_NAME, pspec);
 
+        /**
+         * GUPnPDLNAProfile:mime:
+         *
+         * MIME type of the DLNA profile.
+         */
         pspec = g_param_spec_string ("mime",
                                      "DLNA profile MIME type",
                                      "The MIME type of the DLNA profile",
@@ -176,17 +158,11 @@ gupnp_dlna_profile_class_init (GUPnPDLNAProfileClass *klass)
                                      G_PARAM_CONSTRUCT_ONLY);
         g_object_class_install_property (object_class, PROP_DLNA_MIME, pspec);
 
-        pspec = gst_param_spec_mini_object ("encoding-profile",
-                                            "Encoding Profile for the "
-                                            "DLNA Profile",
-                                            "GstEncodingProfile object"
-                                            "corresponding to the DLNA profile",
-                                            GST_TYPE_ENCODING_PROFILE,
-                                            G_PARAM_READABLE);
-        g_object_class_install_property (object_class,
-                                         PROP_ENCODING_PROFILE,
-                                         pspec);
-
+        /**
+         * GUPnPDLNAProfile:extended:
+         *
+         * Whether the DLNA profile is not a part of DLNA specification.
+         */
         pspec = g_param_spec_boolean ("extended",
                                       "Extended mode property",
                                       "Indicates that this profile is not "
@@ -198,189 +174,60 @@ gupnp_dlna_profile_class_init (GUPnPDLNAProfileClass *klass)
                                          PROP_DLNA_EXTENDED,
                                          pspec);
 
+        g_type_class_add_private (klass, sizeof (GUPnPDLNAProfilePrivate));
 }
 
 static void
 gupnp_dlna_profile_init (GUPnPDLNAProfile *self)
 {
-}
-
-const GstCaps *
-gupnp_dlna_profile_get_container_caps (GUPnPDLNAProfile *self)
-{
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-        return priv->container_caps;
-}
-
-const GstCaps *
-gupnp_dlna_profile_get_video_caps (GUPnPDLNAProfile *self)
-{
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-        return priv->video_caps;
-}
-
-const GstCaps *
-gupnp_dlna_profile_get_audio_caps (GUPnPDLNAProfile *self)
-{
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-        return priv->audio_caps;
-}
-
-void
-gupnp_dlna_profile_set_container_caps (GUPnPDLNAProfile *self, GstCaps *caps)
-{
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
+        GUPnPDLNAProfilePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                                  GUPNP_TYPE_DLNA_PROFILE,
+                                                  GUPnPDLNAProfilePrivate);
 
-        if (priv->container_caps)
-                gst_caps_unref (priv->container_caps);
-        priv->container_caps = gst_caps_copy (caps);
-}
-
-void
-gupnp_dlna_profile_set_video_caps (GUPnPDLNAProfile *self, GstCaps *caps)
-{
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-
-        if (priv->video_caps)
-                gst_caps_unref (priv->video_caps);
-        priv->video_caps = gst_caps_copy (caps);
-}
-
-void
-gupnp_dlna_profile_set_audio_caps (GUPnPDLNAProfile *self, GstCaps *caps)
-{
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-
-        if (priv->audio_caps)
-                gst_caps_unref (priv->audio_caps);
-        priv->audio_caps = gst_caps_copy (caps);
-}
-
-GUPnPDLNAProfile *
-gupnp_dlna_profile_new (gchar    *name,
-                        gchar    *mime,
-                        GstCaps  *container_caps,
-                        GstCaps  *video_caps,
-                        GstCaps  *audio_caps,
-                        gboolean extended)
-{
-        GUPnPDLNAProfile *prof;
-
-        prof =  g_object_new (GUPNP_TYPE_DLNA_PROFILE,
-                              "name", name,
-                              "mime", mime,
-                              "extended", extended,
-                              NULL);
-
-        gupnp_dlna_profile_set_container_caps (prof, container_caps);
-        gupnp_dlna_profile_set_video_caps (prof, video_caps);
-        gupnp_dlna_profile_set_audio_caps (prof, audio_caps);
-
-        return prof;
+        priv->name = NULL;
+        priv->mime = NULL;
+        priv->extended = FALSE;
+        self->priv = priv;
 }
 
 /**
  * gupnp_dlna_profile_get_name:
- * @self: The #GUPnPDLNAProfile object
+ * @profile: The #GUPnPDLNAProfile object.
  *
- * Returns: the name of the DLNA profile represented by @self
+ * Returns: The name of the DLNA profile represented by @profile.
  */
 const gchar *
-gupnp_dlna_profile_get_name (GUPnPDLNAProfile *self)
+gupnp_dlna_profile_get_name (GUPnPDLNAProfile *profile)
 {
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-        return priv->name;
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE (profile), NULL);
+
+        return profile->priv->name;
 }
 
 /**
  * gupnp_dlna_profile_get_mime:
- * @self: The #GUPnPDLNAProfile object
+ * @profile: The #GUPnPDLNAProfile object.
  *
- * Returns: the DLNA MIME type of the DLNA profile represented by @self
+ * Returns: The DLNA MIME type of the DLNA profile represented by @profile.
  */
 const gchar *
-gupnp_dlna_profile_get_mime (GUPnPDLNAProfile *self)
+gupnp_dlna_profile_get_mime (GUPnPDLNAProfile *profile)
 {
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-        return priv->mime;
-}
-
-/**
- * gupnp_dlna_profile_get_encoding_profile:
- * @self: The #GUPnPDLNAProfile object
- *
- * Returns: (transfer full): a #GstEncodingProfile object that, in a future
- *          version, can be used to transcode a given stream to match the DLNA
- *          profile represented by @self.
- *          The receiver must unref the returned #GstEncodingProfile when done
- *          using it.
- */
-GstEncodingProfile *
-gupnp_dlna_profile_get_encoding_profile (GUPnPDLNAProfile *self)
-{
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-
-        /* create an encoding-profile if we don't have one */
-        if (!priv->enc_profile) {
-                GstEncodingContainerProfile *container = NULL;
-                GstEncodingAudioProfile *audio_profile = NULL;
-                GstEncodingVideoProfile *video_profile = NULL;
-
-                if (GST_IS_CAPS (priv->video_caps) &&
-                    !gst_caps_is_empty (priv->video_caps))
-                        video_profile = gst_encoding_video_profile_new
-                                        (priv->video_caps,NULL, NULL, 0);
-
-                if (GST_IS_CAPS (priv->audio_caps) &&
-                    !gst_caps_is_empty (priv->audio_caps))
-                        audio_profile = gst_encoding_audio_profile_new
-                                        (priv->audio_caps,NULL, NULL, 0);
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE (profile), NULL);
 
-                if (GST_IS_CAPS (priv->container_caps)) {
-                        container = gst_encoding_container_profile_new
-                                        (priv->name,
-                                         priv->mime,
-                                         priv->container_caps,
-                                         NULL);
-
-                        if (video_profile)
-                                gst_encoding_container_profile_add_profile
-                                        (container,
-                                         (GstEncodingProfile *)video_profile);
-
-                        if (audio_profile)
-                                gst_encoding_container_profile_add_profile
-                                        (container,
-                                         (GstEncodingProfile *) audio_profile);
-
-                        priv->enc_profile = (GstEncodingProfile *)container;
-                } else {
-                        if(audio_profile)
-                                /* Container-less audio */
-                                priv->enc_profile =
-                                        (GstEncodingProfile *)audio_profile;
-
-                        if (video_profile)
-                                /* Container-less video isn't a possibility
-                                   yet */
-                                g_assert_not_reached ();
-                }
-        }
-
-        gst_encoding_profile_ref (priv->enc_profile);
-
-        return priv->enc_profile;
+        return profile->priv->mime;
 }
 
 /**
  * gupnp_dlna_profile_get_extended:
- * @self: The #GUPnPDLNAProfile object
+ * @profile: The #GUPnPDLNAProfile object.
  *
- * Returns: true if application is using extended mode and false otherwise
+ * Returns: %TRUE if @profile is extended one and %FALSE otherwise.
  */
 gboolean
-gupnp_dlna_profile_get_extended (GUPnPDLNAProfile *self)
+gupnp_dlna_profile_get_extended (GUPnPDLNAProfile *profile)
 {
-        GUPnPDLNAProfilePrivate *priv = GET_PRIVATE (self);
-        return priv->extended;
+        g_return_val_if_fail (GUPNP_IS_DLNA_PROFILE (profile), FALSE);
+
+        return profile->priv->extended;
 }
diff --git a/libgupnp-dlna/gupnp-dlna-profile.h b/libgupnp-dlna/gupnp-dlna-profile.h
index f34c35b..a03af9f 100644
--- a/libgupnp-dlna/gupnp-dlna-profile.h
+++ b/libgupnp-dlna/gupnp-dlna-profile.h
@@ -1,7 +1,9 @@
 /*
  * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation.
  *
  * Authors: Arun Raghavan <arun raghavan collabora co uk>
+ *          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
@@ -22,55 +24,68 @@
 #ifndef __GUPNP_DLNA_PROFILE_H__
 #define __GUPNP_DLNA_PROFILE_H__
 
-#include <gst/pbutils/pbutils.h>
 #include <glib-object.h>
 
 G_BEGIN_DECLS
 
 #define GUPNP_TYPE_DLNA_PROFILE gupnp_dlna_profile_get_type()
 
-#define GUPNP_DLNA_PROFILE(obj)                               \
-        (G_TYPE_CHECK_INSTANCE_CAST ((obj),                   \
+#define GUPNP_DLNA_PROFILE(obj) \
+        (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
                                      GUPNP_TYPE_DLNA_PROFILE, \
                                      GUPnPDLNAProfile))
 
-#define GUPNP_DLNA_PROFILE_CLASS(klass)                    \
-        (G_TYPE_CHECK_CLASS_CAST ((klass),                 \
+#define GUPNP_DLNA_PROFILE_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_CAST ((klass), \
                                   GUPNP_TYPE_DLNA_PROFILE, \
                                   GUPnPDLNAProfileClass))
 
-#define GUPNP_IS_DLNA_PROFILE(obj)                                   \
-        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GUPNP_TYPE_DLNA_PROFILE))
+#define GUPNP_IS_DLNA_PROFILE(obj) \
+        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                                     GUPNP_TYPE_DLNA_PROFILE))
 
-#define GUPNP_IS_DLNA_PROFILE_CLASS(klass)                           \
-        (G_TYPE_CHECK_CLASS_TYPE ((klass), GUPNP_TYPE_DLNA_PROFILE))
+#define GUPNP_IS_DLNA_PROFILE_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+                                  GUPNP_TYPE_DLNA_PROFILE))
 
-#define GUPNP_DLNA_PROFILE_GET_CLASS(obj)                    \
-        (G_TYPE_INSTANCE_GET_CLASS ((obj),                   \
+#define GUPNP_DLNA_PROFILE_GET_CLASS(obj) \
+        (G_TYPE_INSTANCE_GET_CLASS ((obj), \
                                     GUPNP_TYPE_DLNA_PROFILE, \
                                     GUPnPDLNAProfileClass))
 
+typedef struct _GUPnPDLNAProfilePrivate GUPnPDLNAProfilePrivate;
+
 /**
  * GUPnPDLNAProfile:
  *
- * The top-level object used for the in-memory representation of the DLNA
- * Profiles.
+ * The top-level object used for the in-memory representation of the
+ * DLNA Profiles.
  */
 typedef struct {
         GObject parent;
+
+        GUPnPDLNAProfilePrivate *priv;
 } GUPnPDLNAProfile;
 
+/**
+ * GUPnPDLNAProfileClass:
+ * @parent_class: A #GObjectClass - parent of this class.
+ */
 typedef struct {
         GObjectClass parent_class;
 } GUPnPDLNAProfileClass;
 
-GType gupnp_dlna_profile_get_type (void);
+GType
+gupnp_dlna_profile_get_type (void);
+
+const gchar *
+gupnp_dlna_profile_get_name (GUPnPDLNAProfile *profile);
+
+const gchar *
+gupnp_dlna_profile_get_mime (GUPnPDLNAProfile *profile);
 
-const gchar * gupnp_dlna_profile_get_name (GUPnPDLNAProfile *self);
-const gchar * gupnp_dlna_profile_get_mime (GUPnPDLNAProfile *self);
-GstEncodingProfile *
-gupnp_dlna_profile_get_encoding_profile (GUPnPDLNAProfile *self);
-gboolean gupnp_dlna_profile_get_extended (GUPnPDLNAProfile *self);
+gboolean
+gupnp_dlna_profile_get_extended (GUPnPDLNAProfile *profile);
 
 G_END_DECLS
 



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