[gupnp-dlna] Add "native" profile backend.
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gupnp-dlna] Add "native" profile backend.
- Date: Fri, 30 Nov 2012 23:35:04 +0000 (UTC)
commit e1d3b216cce3f1aa6a40a092b7f9a168b0abc323
Author: Krzesimir Nowak <krnowak openismus com>
Date: Thu Nov 15 15:16:55 2012 +0100
Add "native" profile backend.
This backend implements profile guessing using the sets added
earlier. In future this is going to be merged into GUPnPDLNAProfile
and GUPnPDLNAProfileGuesser.
.../native/gupnp-dlna-native-profile-backend.c | 40 +
.../native/gupnp-dlna-native-profile-backend.h | 41 +
.../gupnp-dlna-native-profile-guesser-impl.c | 702 ++++++++++++++++
.../gupnp-dlna-native-profile-guesser-impl.h | 77 ++
.../native/gupnp-dlna-native-profile-loader.c | 864 ++++++++++++++++++++
.../native/gupnp-dlna-native-profile-loader.h | 77 ++
.../native/gupnp-dlna-native-profile.c | 260 ++++++
.../native/gupnp-dlna-native-profile.h | 93 +++
.../native/gupnp-dlna-native-sets.h | 30 +
.../native/gupnp-dlna-native-utils.c | 61 ++
.../native/gupnp-dlna-native-utils.h | 37 +
libgupnp-dlna/profile-backends/native/native.am | 59 ++
12 files changed, 2341 insertions(+), 0 deletions(-)
---
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-backend.c b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-backend.c
new file mode 100644
index 0000000..0521960
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-backend.c
@@ -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.
+ */
+
+#include "gupnp-dlna-native-profile-loader.h"
+#include "gupnp-dlna-native-profile-guesser-impl.h"
+#include "gupnp-dlna-native-profile-backend.h"
+
+GUPnPDLNAProfileLoader *
+gupnp_dlna_native_profile_backend_get_loader (gboolean relaxed_mode,
+ gboolean extended_mode)
+{
+ return GUPNP_DLNA_PROFILE_LOADER
+ (gupnp_dlna_native_profile_loader_new (relaxed_mode,
+ extended_mode));
+}
+
+GUPnPDLNAProfileGuesserImpl *
+gupnp_dlna_native_profile_backend_get_guesser_impl (void)
+{
+ return GUPNP_DLNA_PROFILE_GUESSER_IMPL
+ (gupnp_dlna_native_profile_guesser_impl_new ());
+}
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-backend.h b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-backend.h
new file mode 100644
index 0000000..a9a81ae
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-backend.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_PROFILE_BACKEND_H__
+#define __GUPNP_DLNA_NATIVE_PROFILE_BACKEND_H__
+
+#include "gupnp-dlna-profile-loader.h"
+
+G_BEGIN_DECLS
+
+void
+gupnp_dlna_native_profile_backend_init (void);
+
+GUPnPDLNAProfileLoader *
+gupnp_dlna_native_profile_backend_get_loader (gboolean relaxed_mode,
+ gboolean extended_mode);
+
+GUPnPDLNAProfileGuesserImpl *
+gupnp_dlna_native_profile_backend_get_guesser_impl (void);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_PROFILE_BACKEND_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-guesser-impl.c b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-guesser-impl.c
new file mode 100644
index 0000000..f12a7e3
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-guesser-impl.c
@@ -0,0 +1,702 @@
+/*
+ * 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.h>
+
+#include "gupnp-dlna-native-profile.h"
+#include "gupnp-dlna-native-profile-guesser-impl.h"
+#include "gupnp-dlna-information.h"
+#include "gupnp-dlna-audio-information.h"
+#include "gupnp-dlna-container-information.h"
+#include "gupnp-dlna-image-information.h"
+#include "gupnp-dlna-video-information.h"
+#include "gupnp-dlna-native-sets.h"
+#include "gupnp-dlna-native-utils.h"
+
+G_DEFINE_TYPE (GUPnPDLNANativeProfileGuesserImpl,
+ gupnp_dlna_native_profile_guesser_impl,
+ GUPNP_TYPE_DLNA_PROFILE_GUESSER_IMPL)
+
+struct _GUPnPDLNANativeProfileGuesserImplPrivate {
+ gpointer placeholder;
+};
+
+
+static gboolean
+is_video_profile (GUPnPDLNANativeProfile *profile)
+{
+ GList *container_restrictions =
+ gupnp_dlna_native_profile_get_container_restrictions (profile);
+ GList *video_restrictions =
+ gupnp_dlna_native_profile_get_video_restrictions (profile);
+
+ return (container_restrictions != NULL && video_restrictions != NULL);
+}
+
+static gboolean
+match_profile (GUPnPDLNANativeProfile *profile,
+ GUPnPDLNANativeInfoSet *stream_info_set,
+ GList *profile_restrictions)
+{
+ GUPnPDLNAProfile *dlna_profile = GUPNP_DLNA_PROFILE (profile);
+ const gchar *name = gupnp_dlna_profile_get_name (dlna_profile);
+ GList *iter;
+ gchar *stream_dump;
+ gchar *restrictions_dump;
+
+ /* Profiles with an empty name are used only for inheritance
+ * and should not be matched against. */
+ if (name == NULL || name[0] == '\0') {
+ /* TODO: if this warning never happens, then remove
+ * profile parameter from this function.
+ */
+ g_warning ("Profiles weren't cleaned up properly?");
+ return FALSE;
+ }
+
+ stream_dump = gupnp_dlna_native_info_set_to_string (stream_info_set);
+ restrictions_dump = gupnp_dlna_native_utils_restrictions_list_to_string
+ (profile_restrictions);
+ g_debug ("Stream: %s\nRestrictions: %s",
+ stream_dump,
+ restrictions_dump);
+ g_free (stream_dump);
+ g_free (restrictions_dump);
+
+ for (iter = profile_restrictions; iter != NULL; iter = iter->next) {
+ GUPnPDLNANativeRestriction *restriction =
+ GUPNP_DLNA_NATIVE_RESTRICTION (iter->data);
+
+ if (restriction != NULL &&
+ gupnp_dlna_native_info_set_fits_restriction
+ (stream_info_set,
+ restriction))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+add_bool (GUPnPDLNANativeInfoSet *info_set,
+ const gchar *name,
+ GUPnPDLNABoolValue value,
+ const gchar *type)
+{
+ switch (value.state) {
+ case GUPNP_DLNA_VALUE_STATE_SET:
+ if (!gupnp_dlna_native_info_set_add_bool (info_set,
+ name,
+ value.value))
+ g_warning ("Failed to add '%s' bool value (%s) to %s "
+ "info set.",
+ name,
+ (value.value ? "true" : "false"),
+ type);
+
+ break;
+ case GUPNP_DLNA_VALUE_STATE_UNSET:
+ break;
+ case GUPNP_DLNA_VALUE_STATE_UNSUPPORTED:
+ if (!gupnp_dlna_native_info_set_add_unsupported_bool (info_set,
+ name))
+ g_warning ("Failed to add '%s' bool unsupported value"
+ " to %s info set.",
+ name,
+ type);
+
+ break;
+ default:
+ g_critical ("Wrong value state value (%d).", value.state);
+ }
+}
+
+static void
+add_fraction (GUPnPDLNANativeInfoSet *info_set,
+ const gchar *name,
+ GUPnPDLNAFractionValue value,
+ const gchar *type)
+{
+ switch (value.state) {
+ case GUPNP_DLNA_VALUE_STATE_SET:
+ if (!gupnp_dlna_native_info_set_add_fraction
+ (info_set,
+ name,
+ value.numerator,
+ value.denominator))
+ g_warning ("Failed to add '%s' fraction value (%d/%d)"
+ " to %s info set.",
+ name,
+ value.numerator,
+ value.denominator,
+ type);
+
+ break;
+ case GUPNP_DLNA_VALUE_STATE_UNSET:
+ break;
+ case GUPNP_DLNA_VALUE_STATE_UNSUPPORTED:
+ if (!gupnp_dlna_native_info_set_add_unsupported_fraction
+ (info_set,
+ name))
+ g_warning ("Failed to add '%s' fraction unsupported"
+ " value to %s info set.",
+ name,
+ type);
+
+ break;
+ default:
+ g_critical ("Wrong value state value (%d).", value.state);
+ }
+}
+
+static void
+add_int (GUPnPDLNANativeInfoSet *info_set,
+ const gchar *name,
+ GUPnPDLNAIntValue value,
+ const gchar *type)
+{
+ switch (value.state) {
+ case GUPNP_DLNA_VALUE_STATE_SET:
+ if (!gupnp_dlna_native_info_set_add_int (info_set,
+ name,
+ value.value))
+ g_warning ("Failed to add '%s' int value (%d) to %s "
+ "info set.",
+ name,
+ value.value,
+ type);
+
+ break;
+ case GUPNP_DLNA_VALUE_STATE_UNSET:
+ break;
+ case GUPNP_DLNA_VALUE_STATE_UNSUPPORTED:
+ if (!gupnp_dlna_native_info_set_add_unsupported_int (info_set,
+ name))
+ g_warning ("Failed to add '%s' int unsupported value"
+ " to %s info set.",
+ name,
+ type);
+
+ break;
+ default:
+ g_critical ("Wrong value state value (%d).", value.state);
+ }
+}
+
+static void
+add_string (GUPnPDLNANativeInfoSet *info_set,
+ const gchar *name,
+ GUPnPDLNAStringValue value,
+ const gchar *type)
+{
+ switch (value.state) {
+ case GUPNP_DLNA_VALUE_STATE_SET:
+ if (!gupnp_dlna_native_info_set_add_string (info_set,
+ name,
+ value.value))
+ g_warning ("Failed to add '%s' int value (%s) to %s "
+ "info set.",
+ name,
+ value.value,
+ type);
+ g_free (value.value);
+
+ break;
+ case GUPNP_DLNA_VALUE_STATE_UNSET:
+ break;
+ case GUPNP_DLNA_VALUE_STATE_UNSUPPORTED:
+ if (!gupnp_dlna_native_info_set_add_unsupported_string
+ (info_set,
+ name))
+ g_warning ("Failed to add '%s' string unsupported value"
+ " to %s info set.",
+ name,
+ type);
+
+ break;
+ default:
+ g_critical ("Wrong value state value (%d).", value.state);
+ }
+}
+
+static GUPnPDLNANativeInfoSet *
+create_info_set (GUPnPDLNAStringValue value,
+ const gchar *type)
+{
+ gchar *mime;
+ gchar *lctype;
+ GUPnPDLNANativeInfoSet *info_set;
+
+ if (value.state == GUPNP_DLNA_VALUE_STATE_SET) {
+ mime = value.value;
+ lctype = g_ascii_strdown (type, -1);
+ } else {
+ g_warning ("%s information holds no mime type, expect it"
+ "to match to no DLNA profile.",
+ type);
+ mime = g_ascii_strdown (type, -1);
+ lctype = g_strdup (mime);
+ }
+
+ info_set = gupnp_dlna_native_info_set_new (mime);
+ if (info_set == NULL)
+ g_warning ("Failed to create %s info set with mime '%s'.",
+ lctype,
+ mime);
+ g_free (mime);
+ g_free (lctype);
+
+ return info_set;
+}
+
+static GUPnPDLNANativeInfoSet *
+info_set_from_container_information (GUPnPDLNAContainerInformation *info)
+{
+ static const gchar *const type = "container";
+ GUPnPDLNANativeInfoSet *info_set = create_info_set
+ (gupnp_dlna_container_information_get_mime (info),
+ "Container");
+
+ if (info_set == NULL)
+ return NULL;
+
+ add_int (info_set,
+ "mpegversion",
+ gupnp_dlna_container_information_get_mpeg_version (info),
+ type);
+
+ add_int (info_set,
+ "packetsize",
+ gupnp_dlna_container_information_get_packet_size (info),
+ type);
+
+ add_string (info_set,
+ "profile",
+ gupnp_dlna_container_information_get_profile (info),
+ type);
+
+ add_bool (info_set,
+ "systemstream",
+ gupnp_dlna_container_information_is_system_stream (info),
+ type);
+
+ add_string (info_set,
+ "variant",
+ gupnp_dlna_container_information_get_variant (info),
+ type);
+
+ return info_set;
+}
+
+static gboolean
+check_container_profile (GUPnPDLNAInformation *info,
+ GUPnPDLNANativeProfile *profile)
+{
+ GUPnPDLNAContainerInformation *container_info =
+ gupnp_dlna_information_get_container_information (info);
+ gboolean matched = FALSE;
+ GList *profile_restrictions =
+ gupnp_dlna_native_profile_get_container_restrictions (profile);
+
+ if (profile_restrictions != NULL && container_info != NULL) {
+ GUPnPDLNANativeInfoSet *stream_info_set =
+ info_set_from_container_information (container_info);
+
+ if (match_profile (profile,
+ stream_info_set,
+ profile_restrictions))
+ matched = TRUE;
+ else
+ g_debug ("Container did not match.");
+ gupnp_dlna_native_info_set_free (stream_info_set);
+ } else if (profile_restrictions == NULL && container_info == NULL)
+ matched = TRUE;
+
+ return matched;
+}
+
+static GUPnPDLNANativeInfoSet *
+info_set_from_audio_information (GUPnPDLNAAudioInformation *info)
+{
+ static const gchar *const type = "audio";
+ GUPnPDLNANativeInfoSet *info_set = create_info_set
+ (gupnp_dlna_audio_information_get_mime (info),
+ "Audio");
+
+ if (info_set == NULL)
+ return NULL;
+
+ add_int (info_set,
+ "bitrate",
+ gupnp_dlna_audio_information_get_bitrate (info),
+ type);
+
+ add_int (info_set,
+ "channels",
+ gupnp_dlna_audio_information_get_channels (info),
+ type);
+
+ add_int (info_set,
+ "depth",
+ gupnp_dlna_audio_information_get_depth (info),
+ type);
+
+ add_int (info_set,
+ "layer",
+ gupnp_dlna_audio_information_get_layer (info),
+ type);
+
+ add_string (info_set,
+ "level",
+ gupnp_dlna_audio_information_get_level (info),
+ type);
+
+ add_int (info_set,
+ "mpegaudioversion",
+ gupnp_dlna_audio_information_get_mpeg_audio_version (info),
+ type);
+
+ add_int (info_set,
+ "mpegversion",
+ gupnp_dlna_audio_information_get_mpeg_version (info),
+ type);
+
+ add_string (info_set,
+ "profile",
+ gupnp_dlna_audio_information_get_profile (info),
+ type);
+
+ add_int (info_set,
+ "rate",
+ gupnp_dlna_audio_information_get_rate (info),
+ type);
+
+ add_string (info_set,
+ "stream-format",
+ gupnp_dlna_audio_information_get_stream_format (info),
+ type);
+
+ add_int (info_set,
+ "wmaversion",
+ gupnp_dlna_audio_information_get_wma_version (info),
+ type);
+
+ return info_set;
+}
+
+static gboolean
+check_audio_profile (GUPnPDLNAInformation *info,
+ GUPnPDLNANativeProfile *profile)
+{
+ GUPnPDLNANativeInfoSet *info_set;
+ gboolean matched;
+ GUPnPDLNAAudioInformation *audio_info;
+ GList *restrictions;
+
+ if (is_video_profile (profile))
+ return FALSE;
+
+ matched = FALSE;
+ audio_info = gupnp_dlna_information_get_audio_information (info);
+ info_set = info_set_from_audio_information (audio_info);
+ restrictions =
+ gupnp_dlna_native_profile_get_audio_restrictions (profile);
+ if (match_profile (profile, info_set, restrictions))
+ matched = TRUE;
+ else
+ g_debug ("Audio did not match.");
+ gupnp_dlna_native_info_set_free (info_set);
+
+ return matched;
+}
+
+static GUPnPDLNANativeInfoSet *
+info_set_from_video_information (GUPnPDLNAVideoInformation *info)
+{
+ static const gchar *const type = "video";
+ GUPnPDLNANativeInfoSet *info_set = create_info_set
+ (gupnp_dlna_video_information_get_mime (info),
+ "Video");
+
+ if (info_set == NULL)
+ return NULL;
+
+ add_int (info_set,
+ "bitrate",
+ gupnp_dlna_video_information_get_bitrate (info),
+ type);
+
+ add_fraction (info_set,
+ "framerate",
+ gupnp_dlna_video_information_get_framerate (info),
+ type);
+
+ add_int (info_set,
+ "height",
+ gupnp_dlna_video_information_get_height (info),
+ type);
+
+ add_bool (info_set,
+ "interlaced",
+ gupnp_dlna_video_information_is_interlaced (info),
+ type);
+
+ add_string (info_set,
+ "level",
+ gupnp_dlna_video_information_get_level (info),
+ type);
+
+ add_int (info_set,
+ "mpegversion",
+ gupnp_dlna_video_information_get_mpeg_version (info),
+ type);
+
+ add_fraction
+ (info_set,
+ "pixel-aspect-ratio",
+ gupnp_dlna_video_information_get_pixel_aspect_ratio (info),
+ type);
+
+ add_string (info_set,
+ "profile",
+ gupnp_dlna_video_information_get_profile (info),
+ type);
+
+ add_bool (info_set,
+ "systemstream",
+ gupnp_dlna_video_information_is_system_stream (info),
+ type);
+
+ add_int (info_set,
+ "width",
+ gupnp_dlna_video_information_get_width (info),
+ type);
+
+ return info_set;
+}
+
+static gboolean
+check_video_profile (GUPnPDLNAInformation *info,
+ GUPnPDLNANativeProfile *profile)
+{
+ GUPnPDLNAVideoInformation *video_info =
+ gupnp_dlna_information_get_video_information (info);
+ GUPnPDLNAAudioInformation *audio_info =
+ gupnp_dlna_information_get_audio_information (info);
+ GUPnPDLNANativeInfoSet *info_set = NULL;
+ GList *restrictions;
+ gboolean result = FALSE;
+
+ if (video_info == NULL || audio_info == NULL)
+ goto out;
+
+ restrictions = gupnp_dlna_native_profile_get_video_restrictions
+ (profile);
+ info_set = info_set_from_video_information (video_info);
+ if (!match_profile (profile, info_set, restrictions)) {
+ g_debug ("Video did not match");
+
+ goto out;
+ }
+ gupnp_dlna_native_info_set_free (info_set);
+
+ restrictions = gupnp_dlna_native_profile_get_audio_restrictions
+ (profile);
+ info_set = info_set_from_audio_information (audio_info);
+ if (!match_profile (profile, info_set, restrictions)) {
+ g_debug ("Audio did not match");
+
+ goto out;
+ }
+
+ if (check_container_profile (info, profile))
+ result = TRUE;
+ out:
+ gupnp_dlna_native_info_set_free (info_set);
+
+ return result;
+}
+
+static GUPnPDLNANativeInfoSet *
+info_set_from_image_information (GUPnPDLNAImageInformation *info)
+{
+ static const gchar *const type = "image";
+ GUPnPDLNANativeInfoSet *info_set = create_info_set
+ (gupnp_dlna_image_information_get_mime (info),
+ "Image");
+
+ if (info_set == NULL)
+ return NULL;
+
+ add_int (info_set,
+ "depth",
+ gupnp_dlna_image_information_get_depth (info),
+ type);
+
+ add_int (info_set,
+ "height",
+ gupnp_dlna_image_information_get_height (info),
+ type);
+
+ add_int (info_set,
+ "width",
+ gupnp_dlna_image_information_get_width (info),
+ type);
+
+ return info_set;
+}
+
+static GUPnPDLNAProfile *
+backend_guess_image_profile
+ (GUPnPDLNAProfileGuesserImpl *guesser_impl G_GNUC_UNUSED,
+ GUPnPDLNAInformation *info,
+ GList *profiles)
+{
+ GList *iter;
+ GUPnPDLNAImageInformation *image_info =
+ gupnp_dlna_information_get_image_information (info);
+ GUPnPDLNANativeInfoSet *info_set;
+ GUPnPDLNAProfile *profile;
+
+ if (!image_info)
+ return NULL;
+
+ info_set = info_set_from_image_information (image_info);
+ profile = NULL;
+
+ for (iter = profiles; iter; iter = iter->next) {
+ GUPnPDLNANativeProfile *native_profile =
+ GUPNP_DLNA_NATIVE_PROFILE (iter->data);
+ GList *restrictions =
+ gupnp_dlna_native_profile_get_image_restrictions
+ (native_profile);
+
+ g_debug ("Matching image against profile: %s",
+ gupnp_dlna_profile_get_name
+ (GUPNP_DLNA_PROFILE (native_profile)));
+
+ if (match_profile (native_profile, info_set, restrictions)) {
+ profile = GUPNP_DLNA_PROFILE (native_profile);
+
+ break;
+ } else
+ g_debug ("Image did not match");
+ }
+
+ gupnp_dlna_native_info_set_free (info_set);
+
+ return profile;
+}
+
+static GUPnPDLNAProfile *
+backend_guess_video_profile
+ (GUPnPDLNAProfileGuesserImpl *guesser_impl G_GNUC_UNUSED,
+ GUPnPDLNAInformation *info,
+ GList *profiles)
+{
+ GUPnPDLNAProfile *profile = NULL;
+ GList *iter;
+
+ for (iter = profiles; iter; iter = iter->next) {
+ GUPnPDLNANativeProfile *native_profile =
+ GUPNP_DLNA_NATIVE_PROFILE (iter->data);
+
+ g_debug ("Matching video against profile: %s",
+ gupnp_dlna_profile_get_name
+ (GUPNP_DLNA_PROFILE (native_profile)));
+
+ if (check_video_profile (info, native_profile)) {
+ profile = GUPNP_DLNA_PROFILE (native_profile);
+
+ break;
+ }
+ }
+
+ return profile;
+}
+
+static GUPnPDLNAProfile *
+backend_guess_audio_profile
+ (GUPnPDLNAProfileGuesserImpl *guesser_impl G_GNUC_UNUSED,
+ GUPnPDLNAInformation *info,
+ GList *profiles)
+{
+ GList *iter;
+ GUPnPDLNAProfile *profile = NULL;
+
+ for (iter = profiles; iter != NULL; iter = iter->next) {
+ GUPnPDLNANativeProfile *native_profile =
+ GUPNP_DLNA_NATIVE_PROFILE (iter->data);
+
+ g_debug ("Matching audio against profile: %s",
+ gupnp_dlna_profile_get_name
+ (GUPNP_DLNA_PROFILE (native_profile)));
+
+ if (check_audio_profile (info, native_profile) &&
+ check_container_profile (info, native_profile)) {
+ profile = GUPNP_DLNA_PROFILE (native_profile);
+
+ break;
+ }
+ }
+
+ return profile;
+}
+
+static void
+gupnp_dlna_native_profile_guesser_impl_class_init
+ (GUPnPDLNANativeProfileGuesserImplClass *native_guesser_impl_class)
+{
+ GUPnPDLNAProfileGuesserImplClass *guesser_impl_class =
+ GUPNP_DLNA_PROFILE_GUESSER_IMPL_CLASS (native_guesser_impl_class);
+
+ guesser_impl_class->guess_image_profile = backend_guess_image_profile;
+ guesser_impl_class->guess_video_profile = backend_guess_video_profile;
+ guesser_impl_class->guess_audio_profile = backend_guess_audio_profile;
+
+ g_type_class_add_private
+ (native_guesser_impl_class,
+ sizeof (GUPnPDLNANativeProfileGuesserImplPrivate));
+}
+
+static void
+gupnp_dlna_native_profile_guesser_impl_init
+ (GUPnPDLNANativeProfileGuesserImpl *guesser_impl)
+{
+ GUPnPDLNANativeProfileGuesserImplPrivate *priv =
+ G_TYPE_INSTANCE_GET_PRIVATE
+ (guesser_impl,
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_GUESSER_IMPL,
+ GUPnPDLNANativeProfileGuesserImplPrivate);
+
+ guesser_impl->priv = priv;
+}
+
+GUPnPDLNANativeProfileGuesserImpl*
+gupnp_dlna_native_profile_guesser_impl_new (void)
+{
+ return GUPNP_DLNA_NATIVE_PROFILE_GUESSER_IMPL
+ (g_object_new
+ (GUPNP_TYPE_DLNA_NATIVE_PROFILE_GUESSER_IMPL,
+ NULL));
+}
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-guesser-impl.h b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-guesser-impl.h
new file mode 100644
index 0000000..df8e1bc
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-guesser-impl.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_PROFILE_GUESSER_IMPL_H__
+#define __GUPNP_DLNA_NATIVE_PROFILE_GUESSER_IMPL_H__
+
+#include <glib-object.h>
+#include "gupnp-dlna-profile-guesser-impl.h"
+
+G_BEGIN_DECLS
+
+#define GUPNP_TYPE_DLNA_NATIVE_PROFILE_GUESSER_IMPL \
+ (gupnp_dlna_native_profile_guesser_impl_get_type())
+
+#define GUPNP_DLNA_NATIVE_PROFILE_GUESSER_IMPL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_GUESSER_IMPL, \
+ GUPnPDLNANativeProfileGuesserImpl))
+
+#define GUPNP_DLNA_NATIVE_PROFILE_GUESSER_IMPL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_GUESSER_IMPL, \
+ GUPnPDLNANativeProfileGuesserImplClass))
+
+#define GUPNP_IS_DLNA_NATIVE_PROFILE_GUESSER_IMPL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_GUESSER_IMPL))
+
+#define GUPNP_IS_DLNA_NATIVE_PROFILE_GUESSER_IMPL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_GUESSER_IMPL))
+
+#define GUPNP_DLNA_NATIVE_PROFILE_GUESSER_IMPL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_GUESSER_IMPL, \
+ GUPnPDLNANativeProfileGuesserImplClass))
+
+typedef struct _GUPnPDLNANativeProfileGuesserImplPrivate
+ GUPnPDLNANativeProfileGuesserImplPrivate;
+
+typedef struct {
+ GUPnPDLNAProfileGuesserImpl parent;
+
+ GUPnPDLNANativeProfileGuesserImplPrivate *priv;
+} GUPnPDLNANativeProfileGuesserImpl;
+
+typedef struct {
+ GUPnPDLNAProfileGuesserImplClass parent_class;
+} GUPnPDLNANativeProfileGuesserImplClass;
+
+GType
+gupnp_dlna_native_profile_guesser_impl_get_type (void) G_GNUC_CONST;
+
+GUPnPDLNANativeProfileGuesserImpl *
+gupnp_dlna_native_profile_guesser_impl_new (void);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_PROFILE_GUESSER_IMPL_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-loader.c b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-loader.c
new file mode 100644
index 0000000..a90d170
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-loader.c
@@ -0,0 +1,864 @@
+/*
+ * 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-native-profile-loader.h"
+#include "gupnp-dlna-native-profile.h"
+#include "gupnp-dlna-native-sets.h"
+#include "gupnp-dlna-native-utils.h"
+
+G_DEFINE_TYPE (GUPnPDLNANativeProfileLoader,
+ gupnp_dlna_native_profile_loader,
+ GUPNP_TYPE_DLNA_PROFILE_LOADER)
+
+typedef enum {
+ GUPNP_DLNA_NATIVE_PARSED_ELEMENT_RESTRICTIONS,
+ GUPNP_DLNA_NATIVE_PARSED_ELEMENT_RESTRICTION,
+ GUPNP_DLNA_NATIVE_PARSED_ELEMENT_FIELD,
+ GUPNP_DLNA_NATIVE_PARSED_ELEMENT_PARENT,
+ GUPNP_DLNA_NATIVE_PARSED_ELEMENT_DLNA_PROFILE,
+ GUPNP_DLNA_NATIVE_PARSED_ELEMENT_INVALID
+} GUPnPDLNANativeParsedElement;
+
+typedef enum {
+ GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_AUDIO,
+ GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_CONTAINER,
+ GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_IMAGE,
+ GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_VIDEO,
+ GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_INVALID
+} GUPnPDLNANativeRestrictionType;
+
+typedef struct {
+ GList *audios;
+ GList *containers;
+ GList *images;
+ GList *videos;
+} GUPnPDLNANativeProfileData;
+
+typedef struct {
+ gchar *name;
+ GUPnPDLNANativeValueList *list;
+} GUPnPDLNANativeNameValueListPair;
+
+typedef struct {
+ GList *name_list_pairs;
+ GList *parents;
+} GUPnPDLNANativeRestrictionData;
+
+typedef struct {
+ GUPnPDLNANativeRestriction *restriction;
+ GUPnPDLNANativeRestrictionType type;
+} GUPnPDLNANativeDescription;
+
+struct _GUPnPDLNANativeProfileLoaderPrivate {
+ GHashTable *descriptions;
+ GList *tags_stack;
+ GList *dlna_profile_data_stack;
+ GList *restriction_data_stack;
+};
+
+static GUPnPDLNANativeNameValueListPair *
+gupnp_dlna_native_name_value_list_pair_new (const gchar *name,
+ GUPnPDLNANativeValueList *list)
+{
+ GUPnPDLNANativeNameValueListPair *pair =
+ g_slice_new (GUPnPDLNANativeNameValueListPair);
+
+ pair->name = g_strdup (name);
+ pair->list = list;
+
+ return pair;
+}
+
+static void
+gupnp_dlna_native_name_value_list_pair_free
+ (GUPnPDLNANativeNameValueListPair *pair)
+{
+ if (pair == NULL)
+ return;
+ g_free (pair->name);
+ gupnp_dlna_native_value_list_free (pair->list);
+ g_slice_free (GUPnPDLNANativeNameValueListPair, pair);
+}
+
+static GUPnPDLNANativeDescription *
+gupnp_dlna_native_description_new (GUPnPDLNANativeRestriction *restriction,
+ GUPnPDLNANativeRestrictionType type)
+{
+ GUPnPDLNANativeDescription *description =
+ g_slice_new (GUPnPDLNANativeDescription);
+
+ description->restriction = restriction;
+ description->type = type;
+
+ return description;
+}
+
+static void
+gupnp_dlna_native_description_free (GUPnPDLNANativeDescription *description)
+{
+ if (description == NULL)
+ return;
+
+ gupnp_dlna_native_restriction_free (description->restriction);
+ g_slice_free (GUPnPDLNANativeDescription, description);
+}
+
+static GUPnPDLNANativeProfileData*
+gupnp_dlna_native_profile_data_new (void)
+{
+ GUPnPDLNANativeProfileData* data =
+ g_slice_new (GUPnPDLNANativeProfileData);
+
+ data->audios = NULL;
+ data->containers = NULL;
+ data->images = NULL;
+ data->videos = NULL;
+
+ return data;
+}
+
+static void
+gupnp_dlna_native_profile_data_free (GUPnPDLNANativeProfileData *data)
+{
+ if (data == NULL)
+ return;
+
+ gupnp_dlna_native_utils_free_restrictions (data->audios);
+ gupnp_dlna_native_utils_free_restrictions (data->containers);
+ gupnp_dlna_native_utils_free_restrictions (data->images);
+ gupnp_dlna_native_utils_free_restrictions (data->videos);
+ g_slice_free (GUPnPDLNANativeProfileData, data);
+}
+
+static GUPnPDLNANativeRestrictionData *
+gupnp_dlna_native_restriction_data_new (void)
+{
+ GUPnPDLNANativeRestrictionData* data =
+ g_slice_new (GUPnPDLNANativeRestrictionData);
+
+ data->name_list_pairs = NULL;
+ data->parents = NULL;
+
+ return data;
+}
+
+static void
+gupnp_dlna_native_restriction_data_free (GUPnPDLNANativeRestrictionData *data)
+{
+ if (data == NULL)
+ return;
+
+ if (data->name_list_pairs != NULL)
+ g_list_free_full
+ (data->name_list_pairs,
+ (GDestroyNotify) gupnp_dlna_native_name_value_list_pair_free);
+ if (data->parents != NULL)
+ g_list_free_full
+ (data->parents,
+ (GDestroyNotify) gupnp_dlna_native_restriction_free);
+ g_slice_free (GUPnPDLNANativeRestrictionData, data);
+}
+
+static void
+gupnp_dlna_native_profile_data_stack_free (GList* stack)
+{
+ g_list_free_full (stack,
+ (GDestroyNotify) gupnp_dlna_native_profile_data_free);
+}
+
+static void
+gupnp_dlna_native_restriction_data_stack_free (GList* stack)
+{
+ g_list_free_full
+ (stack,
+ (GDestroyNotify) gupnp_dlna_native_restriction_data_free);
+}
+
+static void
+push_tag (GUPnPDLNANativeProfileLoader *native_loader,
+ GUPnPDLNANativeParsedElement element)
+{
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ gint raw_element = (gint) element;
+
+ priv->tags_stack = g_list_prepend (priv->tags_stack,
+ GINT_TO_POINTER (raw_element));
+}
+
+static void
+pop_tag (GUPnPDLNANativeProfileLoader *native_loader)
+{
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+
+ priv->tags_stack = g_list_delete_link (priv->tags_stack,
+ priv->tags_stack);
+}
+
+static GUPnPDLNANativeParsedElement
+top_tag (GUPnPDLNANativeProfileLoader *native_loader)
+{
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+
+ if (priv->tags_stack != NULL) {
+ gint top_raw = GPOINTER_TO_INT (priv->tags_stack->data);
+
+ return (GUPnPDLNANativeParsedElement) top_raw;
+ }
+
+ return GUPNP_DLNA_NATIVE_PARSED_ELEMENT_INVALID;
+}
+
+static void
+backend_pre_field (GUPnPDLNAProfileLoader *loader)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+
+ push_tag (native_loader, GUPNP_DLNA_NATIVE_PARSED_ELEMENT_FIELD);
+}
+
+static GUPnPDLNANativeValueType *
+value_type_from_string (const gchar *type)
+{
+ if (!g_strcmp0 (type, "boolean"))
+ return gupnp_dlna_native_value_type_bool ();
+ else if (!g_strcmp0 (type, "float")) {
+ g_warning ("'float' data type is not yet supported.");
+
+ return NULL;
+ } else if (!g_strcmp0 (type, "fourcc")) {
+ g_warning ("'fourcc' data type is not yet supported.");
+
+ return NULL;
+ } else if (!g_strcmp0 (type, "fraction"))
+ return gupnp_dlna_native_value_type_fraction ();
+ else if (!g_strcmp0 (type, "int"))
+ return gupnp_dlna_native_value_type_int ();
+ else if (!g_strcmp0 (type, "string"))
+ return gupnp_dlna_native_value_type_string ();
+ g_critical ("Unknown value type: %s", type);
+
+ return NULL;
+}
+
+static void
+append_value_to_list (GUPnPDLNAFieldValue *value,
+ GUPnPDLNANativeValueList *list)
+{
+ if (value == NULL)
+ return;
+
+ switch (value->type) {
+ case GUPNP_DLNA_FIELD_VALUE_TYPE_RANGE:
+ gupnp_dlna_native_value_list_add_range (list,
+ value->value.range.min,
+ value->value.range.max);
+
+ break;
+ case GUPNP_DLNA_FIELD_VALUE_TYPE_SINGLE:
+ gupnp_dlna_native_value_list_add_single (list,
+ value->value.single);
+
+ break;
+ default:
+ g_critical ("Unknown field value type: %d", (gint) value->type);
+ }
+}
+
+static void
+backend_post_field (GUPnPDLNAProfileLoader *loader,
+ const gchar *name,
+ const gchar *type,
+ GList *values)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+ GUPnPDLNANativeProfileLoaderPrivate *priv;
+ GUPnPDLNANativeRestrictionData *restriction_data;
+ GUPnPDLNANativeNameValueListPair *pair;
+ GUPnPDLNANativeValueList *value_list;
+ GUPnPDLNANativeValueType* value_type;
+ GList *iter;
+
+ pop_tag (native_loader);
+
+ if (name == NULL || type == NULL)
+ return;
+
+ value_type = value_type_from_string (type);
+
+ if (value_type == NULL)
+ return;
+
+ priv = native_loader->priv;
+ restriction_data =
+ (GUPnPDLNANativeRestrictionData *) priv->restriction_data_stack->data;
+ value_list = gupnp_dlna_native_value_list_new (value_type);
+
+ for (iter = values; iter != NULL; iter = iter->next) {
+ GUPnPDLNAFieldValue *field_value =
+ (GUPnPDLNAFieldValue *) iter->data;
+
+ append_value_to_list (field_value, value_list);
+ }
+
+ pair = gupnp_dlna_native_name_value_list_pair_new (name, value_list);
+ restriction_data->name_list_pairs = g_list_prepend
+ (restriction_data->name_list_pairs,
+ pair);
+}
+
+static void
+backend_merge_restrictions (GUPnPDLNANativeProfileLoader *native_loader,
+ GUPnPDLNANativeDescription *description)
+{
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ GUPnPDLNANativeProfileData* data =
+ (GUPnPDLNANativeProfileData *) priv->dlna_profile_data_stack->data;
+ GList **target_list;
+ GUPnPDLNANativeRestriction *copy;
+
+ if (description == NULL || description->restriction == NULL)
+ return;
+
+ switch (description->type) {
+ case GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_AUDIO:
+ target_list = &data->audios;
+
+ break;
+ case GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_CONTAINER:
+ target_list = &data->containers;
+
+ break;
+ case GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_IMAGE:
+ target_list = &data->images;
+
+ break;
+ case GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_VIDEO:
+ target_list = &data->videos;
+
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ copy = gupnp_dlna_native_restriction_copy (description->restriction);
+ *target_list = g_list_prepend (*target_list, copy);
+}
+
+static void
+backend_merge_restrictions_if_in_dlna_profile
+ (GUPnPDLNANativeProfileLoader *native_loader,
+ GUPnPDLNANativeDescription *description)
+{
+ GUPnPDLNANativeParsedElement element = top_tag (native_loader);
+
+ if (element == GUPNP_DLNA_NATIVE_PARSED_ELEMENT_DLNA_PROFILE)
+ backend_merge_restrictions (native_loader, description);
+}
+
+static void
+backend_collect_parents (GUPnPDLNANativeProfileLoader *native_loader,
+ GUPnPDLNANativeDescription *description)
+{
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ GUPnPDLNANativeRestrictionData *data =
+ (GUPnPDLNANativeRestrictionData *) priv->restriction_data_stack->data;
+
+ if (description != NULL && description->restriction != NULL) {
+ /* Collect parents in a list - we'll
+ * coalesce them later */
+ GUPnPDLNANativeRestriction *copy =
+ gupnp_dlna_native_restriction_copy (description->restriction);
+
+ data->parents = g_list_prepend (data->parents, copy);
+ }
+}
+
+static void
+backend_collect_parents_if_in_restriction
+ (GUPnPDLNANativeProfileLoader *native_loader,
+ GUPnPDLNANativeDescription *description)
+{
+ GUPnPDLNANativeParsedElement element = top_tag (native_loader);
+
+ if (element == GUPNP_DLNA_NATIVE_PARSED_ELEMENT_RESTRICTION)
+ backend_collect_parents (native_loader, description);
+}
+
+static void
+backend_pre_parent (GUPnPDLNAProfileLoader *loader)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+
+ push_tag (native_loader, GUPNP_DLNA_NATIVE_PARSED_ELEMENT_PARENT);
+}
+
+static void
+backend_post_parent (GUPnPDLNAProfileLoader *loader,
+ const gchar *parent)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+
+ pop_tag (native_loader);
+
+ if (parent != NULL) {
+ GUPnPDLNANativeDescription *description = g_hash_table_lookup
+ (priv->descriptions,
+ parent);
+
+ backend_merge_restrictions_if_in_dlna_profile (native_loader,
+ description);
+ backend_collect_parents_if_in_restriction (native_loader,
+ description);
+ }
+}
+
+static void
+backend_pre_restriction (GUPnPDLNAProfileLoader *loader)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ GUPnPDLNANativeRestrictionData *data =
+ gupnp_dlna_native_restriction_data_new ();
+
+ push_tag (native_loader, GUPNP_DLNA_NATIVE_PARSED_ELEMENT_RESTRICTION);
+
+ priv->restriction_data_stack = g_list_prepend
+ (priv->restriction_data_stack,
+ data);
+}
+
+static GUPnPDLNANativeRestrictionType
+restriction_type_from_string (const gchar *type)
+{
+ if (!g_strcmp0 (type, "audio"))
+ return GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_AUDIO;
+ else if (!g_strcmp0 (type, "container"))
+ return GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_CONTAINER;
+ else if (!g_strcmp0 (type, "image"))
+ return GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_IMAGE;
+ else if (!g_strcmp0 (type, "video"))
+ return GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_VIDEO;
+
+ return GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_INVALID;
+}
+
+static void
+backend_post_restriction (GUPnPDLNAProfileLoader *loader,
+ const gchar *restriction_type,
+ const gchar *id,
+ const gchar *name)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ GUPnPDLNANativeRestrictionData *data =
+ (GUPnPDLNANativeRestrictionData *) priv->restriction_data_stack->data;
+ GUPnPDLNANativeRestriction *restriction;
+ GUPnPDLNANativeDescription *description;
+ GUPnPDLNANativeRestrictionType type;
+ GList *iter;
+
+ pop_tag (native_loader);
+
+ /* If this is NULL then it means that 'used' attribute was
+ different from relaxed_mode setting. In this case we just
+ ignore it.
+ */
+ if (restriction_type == NULL)
+ goto out;
+
+ restriction = gupnp_dlna_native_restriction_new (name);
+
+ for (iter = data->name_list_pairs; iter != NULL; iter = iter->next) {
+ GUPnPDLNANativeNameValueListPair *pair =
+ (GUPnPDLNANativeNameValueListPair *) iter->data;
+
+ if (gupnp_dlna_native_restriction_add_value_list (restriction,
+ pair->name,
+ pair->list))
+ pair->list = NULL;
+ }
+
+ type = restriction_type_from_string (restriction_type);
+
+ if (type == GUPNP_DLNA_NATIVE_RESTRICTION_TYPE_INVALID) {
+ g_warning ("Support for '%s' restrictions not yet implemented.",
+ restriction_type);
+ goto out;
+ }
+
+ iter = data->parents = g_list_reverse (data->parents);
+ for (iter = data->parents; iter != NULL; iter = iter->next) {
+ /* Merge all the parent caps. The child overrides parent
+ * attributes */
+ GUPnPDLNANativeRestriction *parent =
+ (GUPnPDLNANativeRestriction *) iter->data;
+
+ if (gupnp_dlna_native_restriction_merge
+ (restriction,
+ parent,
+ GUPNP_DLNA_NATIVE_RESTRICTION_MERGE_RESOLUTION_FROM_TARGET))
+ iter->data = NULL;
+ else
+ g_critical ("Failed to do restriction overriding "
+ "merge.");
+ }
+
+ description = gupnp_dlna_native_description_new (restriction, type);
+ backend_merge_restrictions_if_in_dlna_profile (native_loader,
+ description);
+ if (id != NULL)
+ g_hash_table_replace (priv->descriptions,
+ g_strdup (id),
+ description);
+ else
+ gupnp_dlna_native_description_free (description);
+
+ out:
+ gupnp_dlna_native_restriction_data_free (data);
+ priv->restriction_data_stack = g_list_delete_link
+ (priv->restriction_data_stack,
+ priv->restriction_data_stack);
+}
+
+static void
+backend_pre_restrictions (GUPnPDLNAProfileLoader *loader)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+
+ push_tag (native_loader, GUPNP_DLNA_NATIVE_PARSED_ELEMENT_RESTRICTIONS);
+}
+
+static void
+backend_post_restrictions (GUPnPDLNAProfileLoader *loader)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+
+ pop_tag (native_loader);
+}
+
+static void
+backend_pre_dlna_profile (GUPnPDLNAProfileLoader *loader)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ GUPnPDLNANativeProfileData* data =
+ gupnp_dlna_native_profile_data_new ();
+
+ push_tag (native_loader, GUPNP_DLNA_NATIVE_PARSED_ELEMENT_DLNA_PROFILE);
+ priv->dlna_profile_data_stack = g_list_prepend
+ (priv->dlna_profile_data_stack,
+ data);
+}
+
+static GList *
+copy_restrictions_list (GList *list)
+{
+ GList *dup = NULL;
+ GList *iter;
+
+ for (iter = list; iter != NULL; iter = iter->next) {
+ GUPnPDLNANativeRestriction *restriction =
+ GUPNP_DLNA_NATIVE_RESTRICTION (iter->data);
+ GUPnPDLNANativeRestriction *copy =
+ gupnp_dlna_native_restriction_copy (restriction);
+
+ if (copy)
+ dup = g_list_prepend (dup, copy);
+ }
+
+ return dup;
+}
+
+static void
+merge_base_restrictions (GUPnPDLNANativeProfileData *data,
+ GUPnPDLNANativeProfile *profile)
+{
+ GList *audio_restrictions =
+ gupnp_dlna_native_profile_get_audio_restrictions (profile);
+ GList *container_restrictions =
+ gupnp_dlna_native_profile_get_container_restrictions (profile);
+ GList *image_restrictions =
+ gupnp_dlna_native_profile_get_image_restrictions (profile);
+ GList *video_restrictions =
+ gupnp_dlna_native_profile_get_video_restrictions (profile);
+
+ if (audio_restrictions != NULL) {
+ GList *copy = copy_restrictions_list (audio_restrictions);
+
+ data->audios = g_list_concat (copy, data->audios);
+ }
+ if (container_restrictions != NULL) {
+ GList *copy = copy_restrictions_list (container_restrictions);
+
+ data->containers = g_list_concat (copy, data->containers);
+ }
+ if (image_restrictions != NULL) {
+ GList *copy = copy_restrictions_list (image_restrictions);
+
+ data->images = g_list_concat (copy, data->images);
+ }
+ if (video_restrictions != NULL) {
+ GList *copy = copy_restrictions_list (video_restrictions);
+
+ data->videos = g_list_concat (copy, data->videos);
+ }
+}
+
+static gboolean
+restrictions_list_is_empty (GList *list)
+{
+ GList *iter;
+
+ for (iter = list; iter != NULL; iter = iter->next) {
+ GUPnPDLNANativeRestriction *restriction =
+ GUPNP_DLNA_NATIVE_RESTRICTION (iter->data);
+
+ if (restriction != NULL &&
+ !gupnp_dlna_native_restriction_is_empty (restriction))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GUPnPDLNAProfile *
+backend_create_profile (GUPnPDLNAProfileLoader *loader,
+ GUPnPDLNAProfile *base,
+ const gchar *name,
+ const gchar *mime,
+ gboolean extended)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ GUPnPDLNANativeProfileData *data =
+ (GUPnPDLNANativeProfileData *) priv->dlna_profile_data_stack->data;
+ GUPnPDLNANativeProfile *profile;
+ GList *audio_restrictions = NULL;
+ GList *container_restrictions = NULL;
+ GList *image_restrictions = NULL;
+ GList *video_restrictions = NULL;
+
+ /* Inherit from base profile, if it exists */
+ if (GUPNP_IS_DLNA_NATIVE_PROFILE (base))
+ merge_base_restrictions (data,
+ GUPNP_DLNA_NATIVE_PROFILE (base));
+
+ /* The merged caps will be our new GUPnPDLNAProfile */
+ if (!restrictions_list_is_empty (data->audios)) {
+ audio_restrictions = g_list_reverse (data->audios);
+ data->audios = NULL;
+ }
+ if (!restrictions_list_is_empty (data->containers)) {
+ container_restrictions = g_list_reverse (data->containers);
+ data->containers = NULL;
+ }
+ if (!restrictions_list_is_empty (data->images)) {
+ image_restrictions = g_list_reverse (data->images);
+ data->images = NULL;
+ }
+ if (!restrictions_list_is_empty (data->videos)) {
+ video_restrictions = g_list_reverse (data->videos);
+ data->videos = NULL;
+ }
+
+ profile = gupnp_dlna_native_profile_new (name,
+ mime,
+ audio_restrictions,
+ container_restrictions,
+ image_restrictions,
+ video_restrictions,
+ extended);
+
+ return GUPNP_DLNA_PROFILE (profile);
+}
+
+static void
+backend_post_dlna_profile (GUPnPDLNAProfileLoader *loader)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (loader);
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ GUPnPDLNANativeProfileData *data =
+ (GUPnPDLNANativeProfileData *) priv->dlna_profile_data_stack->data;
+
+ pop_tag (native_loader);
+ gupnp_dlna_native_profile_data_free (data);
+ priv->dlna_profile_data_stack = g_list_delete_link
+ (priv->dlna_profile_data_stack,
+ priv->dlna_profile_data_stack);
+}
+
+static GList *
+backend_cleanup (GUPnPDLNAProfileLoader *loader G_GNUC_UNUSED,
+ GList *profiles)
+{
+ /* Now that we're done loading profiles, remove all profiles
+ * with no name which are only used for inheritance and not
+ * matching. */
+ GList *iter = profiles;
+
+ while (iter != NULL) {
+ GList *next = iter->next;
+
+ if (GUPNP_IS_DLNA_NATIVE_PROFILE (iter->data)) {
+ GUPnPDLNANativeProfile *profile =
+ GUPNP_DLNA_NATIVE_PROFILE (iter->data);
+ const gchar *name = gupnp_dlna_profile_get_name
+ (GUPNP_DLNA_PROFILE (profile));
+
+ if (name == NULL || name[0] == '\0') {
+ profiles = g_list_delete_link (profiles, iter);
+ g_object_unref (profile);
+ } else {
+ /* TODO: simplify restrictions in
+ * profile if possible.
+ */
+ }
+ } else {
+ g_critical
+ ("Profile in list is not from this backend.");
+ }
+
+ iter = next;
+ }
+
+ for (iter = profiles; iter != NULL; iter = iter->next) {
+ GUPnPDLNANativeProfile *profile = GUPNP_DLNA_NATIVE_PROFILE
+ (iter->data);
+ GUPnPDLNAProfile *dlna_profile = GUPNP_DLNA_PROFILE (profile);
+ gchar *acaps =
+ gupnp_dlna_native_utils_restrictions_list_to_string
+ (gupnp_dlna_native_profile_get_audio_restrictions (profile));
+ gchar *ccaps =
+ gupnp_dlna_native_utils_restrictions_list_to_string
+ (gupnp_dlna_native_profile_get_container_restrictions
+ (profile));
+ gchar *icaps =
+ gupnp_dlna_native_utils_restrictions_list_to_string
+ (gupnp_dlna_native_profile_get_image_restrictions (profile));
+ gchar *vcaps =
+ gupnp_dlna_native_utils_restrictions_list_to_string
+ (gupnp_dlna_native_profile_get_video_restrictions (profile));
+
+ g_debug ("Loaded profile: %s\nMIME: %s\naudio caps: %s\n"
+ "container caps: %s\nimage caps: %s\nvideo caps: %s\n",
+ gupnp_dlna_profile_get_name (dlna_profile),
+ gupnp_dlna_profile_get_mime (dlna_profile),
+ acaps,
+ ccaps,
+ icaps,
+ vcaps);
+ g_free (acaps);
+ g_free (ccaps);
+ g_free (icaps);
+ g_free (vcaps);
+ }
+
+ return profiles;
+}
+
+static void
+gupnp_dlna_native_profile_loader_dispose (GObject *object)
+{
+ GUPnPDLNANativeProfileLoader *native_loader =
+ GUPNP_DLNA_NATIVE_PROFILE_LOADER (object);
+ GUPnPDLNANativeProfileLoaderPrivate *priv = native_loader->priv;
+ GObjectClass *parent =
+ G_OBJECT_CLASS (gupnp_dlna_native_profile_loader_parent_class);
+
+ g_clear_pointer (&priv->descriptions, g_hash_table_unref);
+ g_clear_pointer (&priv->tags_stack, g_list_free);
+ g_clear_pointer (&priv->dlna_profile_data_stack,
+ gupnp_dlna_native_profile_data_stack_free);
+ g_clear_pointer (&priv->restriction_data_stack,
+ gupnp_dlna_native_restriction_data_stack_free);
+
+ parent->dispose (object);
+}
+
+static void
+gupnp_dlna_native_profile_loader_class_init
+ (GUPnPDLNANativeProfileLoaderClass *native_loader_class)
+{
+ GUPnPDLNAProfileLoaderClass *loader_class =
+ GUPNP_DLNA_PROFILE_LOADER_CLASS (native_loader_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (native_loader_class);
+
+ object_class->dispose = gupnp_dlna_native_profile_loader_dispose;
+ loader_class->pre_field = backend_pre_field;
+ loader_class->post_field = backend_post_field;
+ loader_class->pre_parent = backend_pre_parent;
+ loader_class->post_parent = backend_post_parent;
+ loader_class->pre_restriction = backend_pre_restriction;
+ loader_class->post_restriction = backend_post_restriction;
+ loader_class->pre_restrictions = backend_pre_restrictions;
+ loader_class->post_restrictions = backend_post_restrictions;
+ loader_class->pre_dlna_profile = backend_pre_dlna_profile;
+ loader_class->create_profile = backend_create_profile;
+ loader_class->post_dlna_profile = backend_post_dlna_profile;
+ loader_class->cleanup = backend_cleanup;
+
+ g_type_class_add_private (native_loader_class,
+ sizeof (GUPnPDLNANativeProfileLoaderPrivate));
+}
+
+static void
+gupnp_dlna_native_profile_loader_init (GUPnPDLNANativeProfileLoader *self)
+{
+ GUPnPDLNANativeProfileLoaderPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self,
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_LOADER,
+ GUPnPDLNANativeProfileLoaderPrivate);
+
+ priv->descriptions = g_hash_table_new_full
+ (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) gupnp_dlna_native_description_free);
+ priv->tags_stack = NULL;
+ priv->dlna_profile_data_stack = NULL;
+ priv->restriction_data_stack = NULL;
+ self->priv = priv;
+}
+
+GUPnPDLNANativeProfileLoader *
+gupnp_dlna_native_profile_loader_new (gboolean relaxed_mode,
+ gboolean extended_mode)
+{
+ return GUPNP_DLNA_NATIVE_PROFILE_LOADER (g_object_new
+ (GUPNP_TYPE_DLNA_NATIVE_PROFILE_LOADER,
+ "relaxed-mode", relaxed_mode,
+ "extended-mode", extended_mode,
+ NULL));
+}
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-loader.h b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-loader.h
new file mode 100644
index 0000000..c8ab8a1
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile-loader.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_PROFILE_LOADER_H__
+#define __GUPNP_DLNA_NATIVE_PROFILE_LOADER_H__
+
+#include "gupnp-dlna-profile-loader.h"
+
+G_BEGIN_DECLS
+
+#define GUPNP_TYPE_DLNA_NATIVE_PROFILE_LOADER \
+ (gupnp_dlna_native_profile_loader_get_type ())
+
+#define GUPNP_DLNA_NATIVE_PROFILE_LOADER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_LOADER, \
+ GUPnPDLNANativeProfileLoader))
+
+#define GUPNP_DLNA_NATIVE_PROFILE_LOADER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_LOADER, \
+ GUPnPDLNANativeProfileLoaderClass))
+
+#define GUPNP_IS_DLNA_NATIVE_PROFILE_LOADER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_LOADER))
+
+#define GUPNP_IS_DLNA_NATIVE_PROFILE_LOADER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_LOADER))
+
+#define GUPNP_DLNA_NATIVE_PROFILE_LOADER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE_LOADER, \
+ GUPnPDLNANativeProfileLoaderClass))
+
+typedef struct _GUPnPDLNANativeProfileLoaderPrivate
+ GUPnPDLNANativeProfileLoaderPrivate;
+
+typedef struct {
+ GUPnPDLNAProfileLoader parent;
+
+ GUPnPDLNANativeProfileLoaderPrivate *priv;
+} GUPnPDLNANativeProfileLoader;
+
+typedef struct {
+ GUPnPDLNAProfileLoaderClass parent_class;
+} GUPnPDLNANativeProfileLoaderClass;
+
+GType
+gupnp_dlna_native_profile_loader_get_type (void);
+
+GUPnPDLNANativeProfileLoader *
+gupnp_dlna_native_profile_loader_new (gboolean relaxed_mode,
+ gboolean extended_mode);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_PROFILE_LOADER_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile.c b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile.c
new file mode 100644
index 0000000..162c705
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile.c
@@ -0,0 +1,260 @@
+/*
+ * 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-native-profile.h"
+#include "gupnp-dlna-native-utils.h"
+
+G_DEFINE_TYPE (GUPnPDLNANativeProfile,
+ gupnp_dlna_native_profile,
+ GUPNP_TYPE_DLNA_PROFILE)
+
+struct _GUPnPDLNANativeProfilePrivate {
+ GList *audio_restrictions;
+ GList *container_restrictions;
+ GList *image_restrictions;
+ GList *video_restrictions;
+};
+
+enum {
+ PROP_0,
+ PROP_AUDIO_RESTRICTIONS,
+ PROP_CONTAINER_RESTRICTIONS,
+ PROP_IMAGE_RESTRICTIONS,
+ PROP_VIDEO_RESTRICTIONS
+};
+
+static void
+gupnp_dlna_native_profile_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDLNANativeProfile *self = GUPNP_DLNA_NATIVE_PROFILE (object);
+ GUPnPDLNANativeProfilePrivate *priv = self->priv;
+
+ switch (property_id) {
+ case PROP_AUDIO_RESTRICTIONS:
+ g_value_set_pointer (value, priv->audio_restrictions);
+
+ break;
+ case PROP_CONTAINER_RESTRICTIONS:
+ g_value_set_pointer
+ (value, priv->container_restrictions);
+
+ break;
+ case PROP_IMAGE_RESTRICTIONS:
+ g_value_set_pointer (value, priv->image_restrictions);
+
+ break;
+ case PROP_VIDEO_RESTRICTIONS:
+ g_value_set_pointer (value, priv->video_restrictions);
+
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ property_id,
+ pspec);
+
+ break;
+ }
+}
+
+static void
+gupnp_dlna_native_profile_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDLNANativeProfile *self = GUPNP_DLNA_NATIVE_PROFILE (object);
+ GUPnPDLNANativeProfilePrivate *priv = self->priv;
+
+ switch (property_id) {
+ case PROP_AUDIO_RESTRICTIONS:
+ gupnp_dlna_native_utils_free_restrictions
+ (priv->audio_restrictions);
+ priv->audio_restrictions = g_value_get_pointer (value);
+
+ break;
+ case PROP_CONTAINER_RESTRICTIONS:
+ gupnp_dlna_native_utils_free_restrictions
+ (priv->container_restrictions);
+ priv->container_restrictions =
+ g_value_get_pointer (value);
+
+ break;
+ case PROP_IMAGE_RESTRICTIONS:
+ gupnp_dlna_native_utils_free_restrictions
+ (priv->image_restrictions);
+ priv->image_restrictions = g_value_get_pointer (value);
+
+ break;
+ case PROP_VIDEO_RESTRICTIONS:
+ gupnp_dlna_native_utils_free_restrictions
+ (priv->video_restrictions);
+ priv->video_restrictions = g_value_get_pointer (value);
+
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ property_id,
+ pspec);
+
+ break;
+ }
+}
+
+static void
+gupnp_dlna_native_profile_finalize (GObject *object)
+{
+ GUPnPDLNANativeProfile *self = GUPNP_DLNA_NATIVE_PROFILE (object);
+ GUPnPDLNANativeProfilePrivate *priv = self->priv;
+ GObjectClass *parent_class =
+ G_OBJECT_CLASS (gupnp_dlna_native_profile_parent_class);
+
+ gupnp_dlna_native_utils_free_restrictions (priv->audio_restrictions);
+ gupnp_dlna_native_utils_free_restrictions
+ (priv->container_restrictions);
+ gupnp_dlna_native_utils_free_restrictions (priv->image_restrictions);
+ gupnp_dlna_native_utils_free_restrictions (priv->video_restrictions);
+
+ parent_class->finalize (object);
+}
+
+static void
+gupnp_dlna_native_profile_class_init
+ (GUPnPDLNANativeProfileClass *native_profile_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (native_profile_class);
+ GParamSpec *pspec;
+
+ object_class->get_property = gupnp_dlna_native_profile_get_property;
+ object_class->set_property = gupnp_dlna_native_profile_set_property;
+ object_class->finalize = gupnp_dlna_native_profile_finalize;
+
+ pspec = g_param_spec_pointer ("audio-restrictions",
+ "Audio restrictions",
+ "Audio restrictions for the DLNA Profile",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class,
+ PROP_AUDIO_RESTRICTIONS,
+ pspec);
+ pspec = g_param_spec_pointer ("container-restrictions",
+ "Container restrictions",
+ "Container restrictions for the DLNA "
+ "Profile",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class,
+ PROP_CONTAINER_RESTRICTIONS,
+ pspec);
+ pspec = g_param_spec_pointer ("image-restrictions",
+ "Image restrictions",
+ "Image restrictions for the DLNA Profile",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class,
+ PROP_IMAGE_RESTRICTIONS,
+ pspec);
+ pspec = g_param_spec_pointer ("video-restrictions",
+ "Video restrictions",
+ "Video restrictions for the DLNA Profile",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class,
+ PROP_VIDEO_RESTRICTIONS,
+ pspec);
+
+ g_type_class_add_private (native_profile_class,
+ sizeof (GUPnPDLNANativeProfilePrivate));
+}
+
+static void
+gupnp_dlna_native_profile_init (GUPnPDLNANativeProfile *self)
+{
+ GUPnPDLNANativeProfilePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self,
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE,
+ GUPnPDLNANativeProfilePrivate);
+
+ priv->audio_restrictions = NULL;
+ priv->container_restrictions = NULL;
+ priv->image_restrictions = NULL;
+ priv->video_restrictions = NULL;
+ self->priv = priv;
+}
+
+GList *
+gupnp_dlna_native_profile_get_audio_restrictions (GUPnPDLNANativeProfile *self)
+{
+ g_return_val_if_fail (GUPNP_IS_DLNA_NATIVE_PROFILE (self), NULL);
+
+ return self->priv->audio_restrictions;
+}
+
+GList *
+gupnp_dlna_native_profile_get_container_restrictions
+ (GUPnPDLNANativeProfile *self)
+{
+ g_return_val_if_fail (GUPNP_IS_DLNA_NATIVE_PROFILE (self), NULL);
+
+ return self->priv->container_restrictions;
+}
+
+GList *
+gupnp_dlna_native_profile_get_image_restrictions (GUPnPDLNANativeProfile *self)
+{
+ g_return_val_if_fail (GUPNP_IS_DLNA_NATIVE_PROFILE (self), NULL);
+
+ return self->priv->image_restrictions;
+}
+
+GList *
+gupnp_dlna_native_profile_get_video_restrictions (GUPnPDLNANativeProfile *self)
+{
+ g_return_val_if_fail (GUPNP_IS_DLNA_NATIVE_PROFILE (self), NULL);
+
+ return self->priv->video_restrictions;
+}
+
+GUPnPDLNANativeProfile *
+gupnp_dlna_native_profile_new (const gchar *name,
+ const gchar *mime,
+ GList *audio_restrictions,
+ GList *container_restrictions,
+ GList *image_restrictions,
+ GList *video_restrictions,
+ gboolean extended)
+{
+ return GUPNP_DLNA_NATIVE_PROFILE
+ (g_object_new
+ (GUPNP_TYPE_DLNA_NATIVE_PROFILE,
+ "name", name,
+ "mime", mime,
+ "audio-restrictions", audio_restrictions,
+ "container-restrictions", container_restrictions,
+ "image-restrictions", image_restrictions,
+ "video-restrictions", video_restrictions,
+ "extended", extended,
+ NULL));
+}
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile.h b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile.h
new file mode 100644
index 0000000..ca68ab8
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-profile.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_PROFILE_H__
+#define __GUPNP_DLNA_NATIVE_PROFILE_H__
+
+#include <glib-object.h>
+#include "gupnp-dlna-profile.h"
+#include "gupnp-dlna-native-sets.h"
+
+G_BEGIN_DECLS
+
+#define GUPNP_TYPE_DLNA_NATIVE_PROFILE gupnp_dlna_native_profile_get_type()
+
+#define GUPNP_DLNA_NATIVE_PROFILE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE, \
+ GUPnPDLNANativeProfile))
+
+#define GUPNP_DLNA_NATIVE_PROFILE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE, \
+ GUPnPDLNANativeProfileClass))
+
+#define GUPNP_IS_DLNA_NATIVE_PROFILE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GUPNP_TYPE_DLNA_NATIVE_PROFILE))
+
+#define GUPNP_IS_DLNA_NATIVE_PROFILE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GUPNP_TYPE_DLNA_NATIVE_PROFILE))
+
+#define GUPNP_DLNA_NATIVE_PROFILE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DLNA_NATIVE_PROFILE, \
+ GUPnPDLNANativeProfileClass))
+
+typedef struct _GUPnPDLNANativeProfilePrivate GUPnPDLNANativeProfilePrivate;
+
+typedef struct {
+ GUPnPDLNAProfile parent;
+
+ GUPnPDLNANativeProfilePrivate *priv;
+} GUPnPDLNANativeProfile;
+
+typedef struct {
+ GUPnPDLNAProfileClass parent_class;
+} GUPnPDLNANativeProfileClass;
+
+GType
+gupnp_dlna_native_profile_get_type (void);
+
+GUPnPDLNANativeProfile *
+gupnp_dlna_native_profile_new (const gchar *name,
+ const gchar *mime,
+ GList *audio_restrictions,
+ GList *container_restrictions,
+ GList *image_restrictions,
+ GList *video_restrictions,
+ gboolean extended);
+
+GList *
+gupnp_dlna_native_profile_get_container_restrictions
+ (GUPnPDLNANativeProfile *self);
+
+GList *
+gupnp_dlna_native_profile_get_audio_restrictions (GUPnPDLNANativeProfile *self);
+
+GList *
+gupnp_dlna_native_profile_get_image_restrictions (GUPnPDLNANativeProfile *self);
+
+GList *
+gupnp_dlna_native_profile_get_video_restrictions (GUPnPDLNANativeProfile *self);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_PROFILE_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-sets.h b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-sets.h
new file mode 100644
index 0000000..2ef015b
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-sets.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_SETS_H__
+#define __GUPNP_DLNA_NATIVE_SETS_H__
+
+#include "gupnp-dlna-native-value-type.h"
+#include "gupnp-dlna-native-value-list.h"
+#include "gupnp-dlna-native-restriction.h"
+#include "gupnp-dlna-native-info-set.h"
+
+#endif /* __GUPNP_DLNA_NATIVE_SETS_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-utils.c b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-utils.c
new file mode 100644
index 0000000..f43ef03
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-utils.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "gupnp-dlna-native-utils.h"
+#include "gupnp-dlna-native-sets.h"
+
+void
+gupnp_dlna_native_utils_free_restrictions (GList *list)
+{
+ if (list == NULL)
+ return;
+ g_list_free_full (list,
+ (GDestroyNotify) gupnp_dlna_native_restriction_free);
+}
+
+gchar *
+gupnp_dlna_native_utils_restrictions_list_to_string (GList *list)
+{
+ GList *iter;
+ GPtrArray *strings = g_ptr_array_new_with_free_func (g_free);
+ gchar *final_string;
+
+ for (iter = list; iter != NULL; iter = iter->next) {
+ GUPnPDLNANativeRestriction *restriction =
+ GUPNP_DLNA_NATIVE_RESTRICTION (iter->data);
+
+ if (restriction)
+ g_ptr_array_add (strings,
+ gupnp_dlna_native_restriction_to_string
+ (restriction));
+ }
+
+ if (strings->len) {
+ g_ptr_array_add (strings, NULL);
+ final_string = g_strjoinv ("; ",
+ (gchar **) strings->pdata);
+ }
+ else
+ final_string = g_strdup ("EMPTY");
+ g_ptr_array_unref (strings);
+
+ return final_string;
+}
diff --git a/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-utils.h b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-utils.h
new file mode 100644
index 0000000..c8b079b
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/gupnp-dlna-native-utils.h
@@ -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.
+ */
+
+#ifndef __GUPNP_DLNA_NATIVE_UTILS_H__
+#define __GUPNP_DLNA_NATIVE_UTILS_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+void
+gupnp_dlna_native_utils_free_restrictions (GList *list);
+
+gchar *
+gupnp_dlna_native_utils_restrictions_list_to_string (GList *list);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_NATIVE_UTILS_H__ */
diff --git a/libgupnp-dlna/profile-backends/native/native.am b/libgupnp-dlna/profile-backends/native/native.am
new file mode 100644
index 0000000..2991cbe
--- /dev/null
+++ b/libgupnp-dlna/profile-backends/native/native.am
@@ -0,0 +1,59 @@
+native_profile_backend = \
+ profile-backends/native/libnativeprofilebackend.la
+native_loader = \
+ profile-backends/native/libnativeloader.la
+native_guesser = \
+ profile-backends/native/libnativeguesser.la
+
+native_cflags = \
+ $(common_cflags) \
+ -I$(top_srcdir)/libgupnp-dlna/profile-backends/native/sets
+
+noinst_LTLIBRARIES += \
+ $(native_profile_backend) \
+ $(native_loader) \
+ $(native_guesser)
+
+gupnp_cflags += \
+ -I$(top_srcdir)/libgupnp-dlna/profile-backends/native
+gupnp_libadd += \
+ $(native_profile_backend)
+
+include $(top_srcdir)/libgupnp-dlna/profile-backends/native/sets/sets.am
+
+profile_backends_native_libnativeloader_la_SOURCES = \
+ profile-backends/native/gupnp-dlna-native-profile-loader.c \
+ profile-backends/native/gupnp-dlna-native-profile-loader.h
+profile_backends_native_libnativeloader_la_LIBADD = \
+ $(common_libadd)
+profile_backends_native_libnativeloader_la_CFLAGS = \
+ $(loader_log_cflags) \
+ $(native_cflags)
+
+profile_backends_native_libnativeguesser_la_SOURCES = \
+ $(sets_sources) \
+ profile-backends/native/gupnp-dlna-native-profile-guesser-impl.c \
+ profile-backends/native/gupnp-dlna-native-profile-guesser-impl.h
+profile_backends_native_libnativeguesser_la_LIBADD = \
+ $(common_libadd)
+profile_backends_native_libnativeguesser_la_CFLAGS = \
+ $(guesser_log_cflags) \
+ $(native_cflags) \
+ $(metadata_cflags)
+
+profile_backends_native_libnativeprofilebackend_la_SOURCES = \
+ profile-backends/native/gupnp-dlna-native-profile-backend.c \
+ profile-backends/native/gupnp-dlna-native-profile-backend.h \
+ profile-backends/native/gupnp-dlna-native-profile.c \
+ profile-backends/native/gupnp-dlna-native-profile.h \
+ profile-backends/native/gupnp-dlna-native-sets.h \
+ profile-backends/native/gupnp-dlna-native-utils.c \
+ profile-backends/native/gupnp-dlna-native-utils.h
+profile_backends_native_libnativeprofilebackend_la_LIBADD = \
+ $(common_libadd) \
+ $(native_loader) \
+ $(native_guesser)
+profile_backends_native_libnativeprofilebackend_la_CFLAGS = \
+ $(general_log_cflags) \
+ $(native_cflags) \
+ $(metadata_cflags)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]