summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Georg <mail@jensge.org>2012-11-29 00:11:25 +0100
committerJens Georg <mail@jensge.org>2012-11-30 15:51:28 +0100
commitc1a77ee6eddc66d9674c9b391b5e0d2d2cf034ba (patch)
treee943bf2afe7406d6a53c40b39b69663a42d506ed
parent83302a3b8eeb9ec255482c9c6464678261fea5fc (diff)
downloadgupnp-av-c1a77ee6eddc66d9674c9b391b5e0d2d2cf034ba.tar.gz
Add LastChange parser for CDS:3
https://bugzilla.gnome.org/show_bug.cgi?id=689276
-rw-r--r--doc/gupnp-av-docs.sgml1
-rw-r--r--doc/gupnp-av-sections.txt31
-rw-r--r--doc/gupnp-av.types2
-rw-r--r--libgupnp-av/Makefile.am3
-rw-r--r--libgupnp-av/gupnp-av.h1
-rw-r--r--libgupnp-av/gupnp-cds-last-change-parser.c379
-rw-r--r--libgupnp-av/gupnp-cds-last-change-parser.h112
7 files changed, 528 insertions, 1 deletions
diff --git a/doc/gupnp-av-docs.sgml b/doc/gupnp-av-docs.sgml
index 93b6340..0e2b00e 100644
--- a/doc/gupnp-av-docs.sgml
+++ b/doc/gupnp-av-docs.sgml
@@ -58,6 +58,7 @@
<xi:include href="xml/gupnp-didl-lite-contributor.xml"/>
<xi:include href="xml/gupnp-didl-lite-create-class.xml"/>
<xi:include href="xml/gupnp-last-change-parser.xml"/>
+ <xi:include href="xml/gupnp-cds-last-change-parser.xml"/>
<xi:include href="xml/gupnp-search-criteria-parser.xml"/>
<xi:include href="xml/gupnp-protocol-info.xml"/>
<xi:include href="xml/gupnp-feature.xml"/>
diff --git a/doc/gupnp-av-sections.txt b/doc/gupnp-av-sections.txt
index 6351590..e373bc6 100644
--- a/doc/gupnp-av-sections.txt
+++ b/doc/gupnp-av-sections.txt
@@ -435,7 +435,6 @@ gupnp_feature_list_parser_get_type
<SECTION>
<FILE>gupnp-media-collection</FILE>
<TITLE>GUPnPMediaCollection</TITLE>
-GUPnPMediaCollectionType
GUPnPMediaCollection
gupnp_media_collection_new
gupnp_media_collection_new_from_string
@@ -460,6 +459,36 @@ gupnp_media_collection_get_type
</SECTION>
<SECTION>
+<FILE>gupnp-cds-last-change-parser</FILE>
+<TITLE>GUPnPCDSLastChangeParser</TITLE>
+GUPnPCDSLastChangeParser
+GUPnPCDSLastChangeEvent
+GUPnPCDSLastChangeEntry
+gupnp_cds_last_change_parser_new
+gupnp_cds_last_change_parser_parse
+gupnp_cds_last_change_entry_ref
+gupnp_cds_last_change_entry_unref
+gupnp_cds_last_change_entry_get_event
+gupnp_cds_last_change_entry_get_object_id
+gupnp_cds_last_change_entry_get_parent_id
+gupnp_cds_last_change_entry_get_class
+gupnp_cds_last_change_entry_is_subtree_update
+gupnp_cds_last_change_entry_get_update_id
+<SUBSECTION Standard>
+GUPnPCDSLastChangeParserClass
+GUPNP_CDS_LAST_CHANGE_PARSER
+GUPNP_CDS_LAST_CHANGE_PARSER_CLASS
+GUPNP_CDS_LAST_CHANGE_PARSER_GET_CLASS
+GUPNP_IS_CDS_LAST_CHANGE_PARSER
+GUPNP_IS_CDS_LAST_CHANGE_PARSER_CLASS
+GUPNP_TYPE_CDS_LAST_CHANGE_PARSER
+GUPnPCDSLastChangeParserPrivate
+gupnp_cds_last_change_entry_get_type
+gupnp_cds_last_change_parser_get_type
+</SECTION>
+
+
+<SECTION>
<FILE>gupnp-av-error</FILE>
<TITLE>Error codes</TITLE>
GUPNP_PROTOCOL_ERROR
diff --git a/doc/gupnp-av.types b/doc/gupnp-av.types
index 1e488f9..9f48dc6 100644
--- a/doc/gupnp-av.types
+++ b/doc/gupnp-av.types
@@ -15,3 +15,5 @@ gupnp_search_criteria_op_get_type
gupnp_feature_get_type
gupnp_feature_list_parser_get_type
gupnp_media_collection_get_type
+gupnp_cds_last_change_parser_get_type
+gupnp_cds_last_change_entry_get_type
diff --git a/libgupnp-av/Makefile.am b/libgupnp-av/Makefile.am
index e4f7bc7..7db04eb 100644
--- a/libgupnp-av/Makefile.am
+++ b/libgupnp-av/Makefile.am
@@ -27,6 +27,7 @@ libgupnp_av_inc_HEADERS = gupnp-didl-lite-object.h \
gupnp-protocol-info.h \
gupnp-search-criteria-parser.h \
gupnp-last-change-parser.h \
+ gupnp-cds-last-change-parser.h \
gupnp-media-collection.h \
gupnp-feature.h \
gupnp-feature-list-parser.h \
@@ -67,6 +68,7 @@ libgupnp_av_1_0_la_SOURCES = gupnp-didl-lite-object.c \
gupnp-protocol-info.c \
gupnp-search-criteria-parser.c \
gupnp-last-change-parser.c \
+ gupnp-cds-last-change-parser.c \
gupnp-media-collection.c \
gupnp-feature.c \
gupnp-feature-list-parser.c \
@@ -111,6 +113,7 @@ introspection_sources = \
$(top_srcdir)/libgupnp-av/gupnp-protocol-info.c \
$(top_srcdir)/libgupnp-av/gupnp-search-criteria-parser.c \
$(top_srcdir)/libgupnp-av/gupnp-last-change-parser.c \
+ $(top_srcdir)/libgupnp-av/gupnp-cds-last-change-parser.c \
$(top_srcdir)/libgupnp-av/gupnp-media-collection.c \
$(top_srcdir)/libgupnp-av/gupnp-feature.c \
$(top_srcdir)/libgupnp-av/gupnp-feature-list-parser.c \
diff --git a/libgupnp-av/gupnp-av.h b/libgupnp-av/gupnp-av.h
index dbf9df0..6741c02 100644
--- a/libgupnp-av/gupnp-av.h
+++ b/libgupnp-av/gupnp-av.h
@@ -33,6 +33,7 @@
#include "gupnp-protocol-info.h"
#include "gupnp-search-criteria-parser.h"
#include "gupnp-last-change-parser.h"
+#include "gupnp-cds-last-change-parser.h"
#include "gupnp-feature.h"
#include "gupnp-feature-list-parser.h"
#include "gupnp-dlna.h"
diff --git a/libgupnp-av/gupnp-cds-last-change-parser.c b/libgupnp-av/gupnp-cds-last-change-parser.c
new file mode 100644
index 0000000..1f120de
--- /dev/null
+++ b/libgupnp-av/gupnp-cds-last-change-parser.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Jens Georg <jensg@openismus.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+/**
+ * SECTION:gupnp-cds-last-change-parser
+ * @short_description: LastChange parser for the format used in
+ * CDS:3
+ *
+ * #GUPnPCDSLastChangeParser parses XML strings from
+ * CDS's LastChange state variable.
+ *
+ */
+
+#include <libgupnp/gupnp-error.h>
+
+#include "xml-util.h"
+#include "gupnp-cds-last-change-parser.h"
+
+/**
+ * GUPnPCDSLastChangeEntry:
+ *
+ * Opaque struct which contains information about the event.
+ **/
+struct _GUPnPCDSLastChangeEntry {
+ int ref_count;
+ GUPnPCDSLastChangeEvent event;
+ char *object_id;
+ char *parent_id;
+ char *class;
+ guint32 update_id;
+ gboolean is_subtree_update;
+};
+
+G_DEFINE_TYPE (GUPnPCDSLastChangeParser,
+ gupnp_cds_last_change_parser,
+ G_TYPE_OBJECT)
+
+G_DEFINE_BOXED_TYPE (GUPnPCDSLastChangeEntry,
+ gupnp_cds_last_change_entry,
+ gupnp_cds_last_change_entry_ref,
+ gupnp_cds_last_change_entry_unref);
+
+static void
+gupnp_cds_last_change_parser_init (GUPnPCDSLastChangeParser *parser)
+{
+}
+
+static void
+gupnp_cds_last_change_parser_class_init (GUPnPCDSLastChangeParserClass *klass)
+{
+}
+
+/**
+ * gupnp_cds_last_change_parser_new:
+ *
+ * Create a new #GUPnPCDSLastChangeParser.
+ *
+ * This parser is able to parse LastChange as defined in the
+ * ContentDirectory:3 specification.
+ *
+ * Returns:(transfer full): A new instance of #GUPnPCDSLastChangeParser.
+ **/
+GUPnPCDSLastChangeParser *
+gupnp_cds_last_change_parser_new (void)
+{
+ return g_object_new (GUPNP_TYPE_CDS_LAST_CHANGE_PARSER,
+ NULL);
+}
+
+/**
+ * gupnp_cds_last_change_parser_parse:
+ * @parser: #GUPnPCDSLastChangeParser
+ * @last_change: XML string to parse
+ * @error: Return value for parser error or %NULL to ingore
+ *
+ * Parse a LastChange XML document in the flavor defined by the
+ * ContentDirectory:3 specification.
+ *
+ * Returns: (element-type GUPnPCDSLastChangeEntry)(transfer full):
+ * List of #GUPnPCDSLastChangeEntry<!-- -->s
+ **/
+GList *
+gupnp_cds_last_change_parser_parse (GUPnPCDSLastChangeParser *parser,
+ const char *last_change,
+ GError **error)
+
+{
+ xmlDoc *doc;
+ xmlNode *state_event, *it;
+ GList *result = NULL;
+ GUPnPCDSLastChangeEntry *entry;
+
+ g_return_val_if_fail (GUPNP_IS_CDS_LAST_CHANGE_PARSER (parser),
+ NULL);
+
+ doc = xmlParseDoc ((const xmlChar *) last_change);
+ if (doc == NULL) {
+ g_set_error (error,
+ GUPNP_XML_ERROR,
+ GUPNP_XML_ERROR_PARSE,
+ "Could not parse LastChange XML");
+
+ goto out;
+ }
+
+ state_event = xml_util_get_element ((xmlNode *) doc,
+ "StateEvent",
+ NULL);
+ if (state_event == NULL) {
+ g_set_error (error,
+ GUPNP_XML_ERROR,
+ GUPNP_XML_ERROR_PARSE,
+ "Missing StateEvent node");
+
+ goto out;
+ }
+
+ for (it = state_event->children; it != NULL; it = it->next) {
+ if (it->type == XML_TEXT_NODE)
+ continue;
+ else if (g_ascii_strcasecmp ((const char *) it->name,
+ "objAdd") == 0) {
+ const char *tmp;
+
+ entry = g_slice_new0 (GUPnPCDSLastChangeEntry);
+ entry->ref_count = 1;
+ entry->event = GUPNP_CDS_LAST_CHANGE_EVENT_OBJECT_ADDED;
+
+ tmp = xml_util_get_attribute_content (it, "objID");
+ entry->object_id = g_strdup (tmp);
+
+ tmp = xml_util_get_attribute_content (it,
+ "objParentID");
+ entry->parent_id = g_strdup (tmp);
+
+ tmp = xml_util_get_attribute_content (it, "objClass");
+ entry->class = g_strdup (tmp);
+
+ entry->update_id = xml_util_get_uint_child_element
+ (it,
+ "updateID",
+ 0);
+ entry->is_subtree_update =
+ xml_util_get_boolean_attribute
+ (it,
+ "stUpdate");
+ } else if (g_ascii_strcasecmp ((const char *) it->name,
+ "objMod") == 0) {
+ const char *tmp;
+
+ entry = g_slice_new0 (GUPnPCDSLastChangeEntry);
+ entry->ref_count = 1;
+ entry->event = GUPNP_CDS_LAST_CHANGE_EVENT_OBJECT_MODIFIED;
+
+ tmp = xml_util_get_attribute_content (it, "objID");
+ entry->object_id = g_strdup (tmp);
+
+ entry->update_id = xml_util_get_uint_child_element
+ (it,
+ "updateID",
+ 0);
+ entry->is_subtree_update =
+ xml_util_get_boolean_attribute
+ (it,
+ "stUpdate");
+ } else if (g_ascii_strcasecmp ((const char *) it->name,
+ "objDel") == 0) {
+ const char *tmp;
+
+ entry = g_slice_new0 (GUPnPCDSLastChangeEntry);
+ entry->ref_count = 1;
+ entry->event = GUPNP_CDS_LAST_CHANGE_EVENT_OBJECT_REMOVED;
+
+ tmp = xml_util_get_attribute_content (it, "objID");
+ entry->object_id = g_strdup (tmp);
+
+ entry->update_id = xml_util_get_uint_child_element
+ (it,
+ "updateID",
+ 0);
+ entry->is_subtree_update =
+ xml_util_get_boolean_attribute
+ (it,
+ "stUpdate");
+ } else if (g_ascii_strcasecmp ((const char *) it->name,
+ "stDone") == 0) {
+ const char *tmp;
+
+ entry = g_slice_new0 (GUPnPCDSLastChangeEntry);
+ entry->ref_count = 1;
+ entry->event = GUPNP_CDS_LAST_CHANGE_EVENT_ST_DONE;
+
+ tmp = xml_util_get_attribute_content (it, "objID");
+ entry->object_id = g_strdup (tmp);
+
+ entry->update_id = xml_util_get_uint_child_element
+ (it,
+ "updateID",
+ 0);
+ } else {
+ g_warning ("Skipping invalid LastChange entry: %s",
+ (const char *) it->name);
+ continue;
+ }
+
+ result = g_list_prepend (result, entry);
+ }
+
+ result = g_list_reverse (result);
+out:
+ if (doc != NULL) {
+ xmlFreeDoc (doc);
+ }
+
+ return result;
+
+}
+
+/**
+ * gupnp_cds_last_change_entry_ref:
+ * @entry: A #GUPnPCDSLastChangeEntry
+ *
+ * Increase reference count of a #GUPnPCDSLastChangeEntry.
+ *
+ * Returns:(transfer full): The object passed in @entry.
+ **/
+GUPnPCDSLastChangeEntry *
+gupnp_cds_last_change_entry_ref (GUPnPCDSLastChangeEntry *entry)
+{
+ g_return_val_if_fail (entry != NULL, NULL);
+ g_return_val_if_fail (entry->ref_count > 0, NULL);
+
+ g_atomic_int_inc (&entry->ref_count);
+
+ return entry;
+}
+
+/**
+ * gupnp_cds_last_change_entry_unref:
+ * @entry: A #GUPnPCDSLastChangeEntry
+ *
+ * Decrease reference count of a #GUPnPCDSLastChangeEntry. If the reference
+ * count drops to 0, @entry is freed.
+ **/
+void
+gupnp_cds_last_change_entry_unref (GUPnPCDSLastChangeEntry *entry)
+{
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (entry->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test (&entry->ref_count)) {
+ g_free (entry->class);
+ g_free (entry->object_id);
+ g_free (entry->parent_id);
+
+ g_slice_free (GUPnPCDSLastChangeEntry, entry);
+ }
+}
+
+/**
+ * gupnp_cds_last_change_entry_get_event:
+ * @entry: A #GUPnPCDSLastChangeEntry
+ *
+ * Get the type of the last change entry as defined in
+ * #GUPnPCDSLastChangeEvent.
+ *
+ * Returns: An event from the #GUPnPCDSLastChangeEvent or
+ * %GUPNP_CDS_LAST_CHANGE_EVENT_INVALID if the entry is not valid.
+ **/
+GUPnPCDSLastChangeEvent
+gupnp_cds_last_change_entry_get_event (GUPnPCDSLastChangeEntry *entry)
+{
+ g_return_val_if_fail (entry != NULL,
+ GUPNP_CDS_LAST_CHANGE_EVENT_INVALID);
+
+ return entry->event;
+}
+
+/**
+ * gupnp_cds_last_change_entry_get_object_id:
+ * @entry: A #GUPnPCDSLastChangeEntry
+ *
+ * Get the ID of the object in this change entry.
+ *
+ * Returns: (transfer none): The id of the object of this entry.
+ **/
+const char *
+gupnp_cds_last_change_entry_get_object_id (GUPnPCDSLastChangeEntry *entry)
+{
+ g_return_val_if_fail (entry != NULL, NULL);
+
+ return entry->object_id;
+}
+
+/**
+ * gupnp_cds_last_change_entry_get_parent_id:
+ * @entry: A #GUPnPCDSLastChangeEntry
+ *
+ * Get the parent object id of the object in this change entry. This is only
+ * valid if gupnp_cds_last_change_entry_get_event() returns
+ * %GUPNP_CDS_LAST_CHANGE_EVENT_OBJECT_ADDED.
+ *
+ * Returns: (transfer none): The id of the object's parent of this entry.
+ **/
+const char *
+gupnp_cds_last_change_entry_get_parent_id (GUPnPCDSLastChangeEntry *entry)
+{
+ g_return_val_if_fail (entry != NULL, NULL);
+
+ return entry->parent_id;
+}
+
+/**
+ * gupnp_cds_last_change_entry_get_class:
+ * @entry: A #GUPnPCDSLastChangeEntry
+ *
+ * Get the class of the object in this change entry. This is only
+ * valid if gupnp_cds_last_change_entry_get_event() returns
+ * %GUPNP_CDS_LAST_CHANGE_EVENT_OBJECT_ADDED.
+ *
+ * Returns: (transfer none): The upnp class of the object of this entry.
+ **/
+const char *
+gupnp_cds_last_change_entry_get_class (GUPnPCDSLastChangeEntry *entry)
+{
+ g_return_val_if_fail (entry != NULL, NULL);
+
+ return entry->class;
+}
+
+/**
+ * gupnp_cds_last_change_entry_is_subtree_update:
+ * @entry: A #GUPnPCDSLastChangeEntry
+ *
+ * Returns whether this entry is part of a subtree update.
+ *
+ * Returns: %TRUE, if the entry is part of a subtree update, %FALSE otherwise.
+ **/
+gboolean
+gupnp_cds_last_change_entry_is_subtree_update (GUPnPCDSLastChangeEntry *entry)
+{
+ g_return_val_if_fail (entry != NULL, FALSE);
+
+ return entry->is_subtree_update;
+}
+
+/**
+ * gupnp_cds_last_change_entry_get_update_id:
+ * @entry: A #GUPnPCDSLastChangeEntry
+ *
+ * Get the update id of the last change entry.
+ *
+ * Returns: update id of the entry or 0 if the entry is not valid.
+ **/
+guint32
+gupnp_cds_last_change_entry_get_update_id (GUPnPCDSLastChangeEntry *entry)
+{
+ g_return_val_if_fail (entry != NULL, 0);
+
+ return entry->update_id;
+}
diff --git a/libgupnp-av/gupnp-cds-last-change-parser.h b/libgupnp-av/gupnp-cds-last-change-parser.h
new file mode 100644
index 0000000..279e108
--- /dev/null
+++ b/libgupnp-av/gupnp-cds-last-change-parser.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors: Jens Georg <jensg@openismus.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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_CDS_LAST_CHANGE_PARSER_H__
+#define __GUPNP_CDS_LAST_CHANGE_PARSER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+GType
+gupnp_cds_last_change_parser_get_type (void) G_GNUC_CONST;
+
+GType
+gupnp_cds_last_change_entry_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_CDS_LAST_CHANGE_PARSER \
+ (gupnp_cds_last_change_parser_get_type ())
+#define GUPNP_CDS_LAST_CHANGE_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_CDS_LAST_CHANGE_PARSER, \
+ GUPnPCDSLastChangeParser))
+#define GUPNP_CDS_LAST_CHANGE_PARSER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_CDS_LAST_CHANGE_PARSER, \
+ GUPnPCDSLastChangeParserClass))
+#define GUPNP_IS_CDS_LAST_CHANGE_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_CDS_LAST_CHANGE_PARSER))
+#define GUPNP_IS_CDS_LAST_CHANGE_PARSER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ GUPNP_TYPE_CDS_LAST_CHANGE_PARSER))
+#define GUPNP_CDS_LAST_CHANGE_PARSER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_CDS_LAST_CHANGE_PARSER, \
+ GUPnPCDSLastChangeParserClass))
+
+typedef struct _GUPnPCDSLastChangeParser GUPnPCDSLastChangeParser;
+typedef struct _GUPnPCDSLastChangeParserClass GUPnPCDSLastChangeParserClass;
+typedef struct _GUPnPCDSLastChangeParserPrivate GUPnPCDSLastChangeParserPrivate;
+typedef struct _GUPnPCDSLastChangeEntry GUPnPCDSLastChangeEntry;
+
+struct _GUPnPCDSLastChangeParser {
+ GObject parent;
+
+ GUPnPCDSLastChangeParserPrivate *priv;
+};
+
+struct _GUPnPCDSLastChangeParserClass {
+ GObjectClass parent_class;
+};
+
+typedef enum GUPnPCDSLastChangeEvent {
+ GUPNP_CDS_LAST_CHANGE_EVENT_INVALID,
+ GUPNP_CDS_LAST_CHANGE_EVENT_OBJECT_ADDED,
+ GUPNP_CDS_LAST_CHANGE_EVENT_OBJECT_REMOVED,
+ GUPNP_CDS_LAST_CHANGE_EVENT_OBJECT_MODIFIED,
+ GUPNP_CDS_LAST_CHANGE_EVENT_ST_DONE
+} GUPnPCDSLastChangeEvent;
+
+GUPnPCDSLastChangeParser *
+gupnp_cds_last_change_parser_new (void);
+
+GList *
+gupnp_cds_last_change_parser_parse (GUPnPCDSLastChangeParser *parser,
+ const char *last_change,
+ GError **error);
+
+GUPnPCDSLastChangeEntry *
+gupnp_cds_last_change_entry_ref (GUPnPCDSLastChangeEntry *entry);
+void
+gupnp_cds_last_change_entry_unref (GUPnPCDSLastChangeEntry *entry);
+
+GUPnPCDSLastChangeEvent
+gupnp_cds_last_change_entry_get_event (GUPnPCDSLastChangeEntry *entry);
+
+const char *
+gupnp_cds_last_change_entry_get_object_id (GUPnPCDSLastChangeEntry *entry);
+
+const char *
+gupnp_cds_last_change_entry_get_parent_id (GUPnPCDSLastChangeEntry *entry);
+
+const char *
+gupnp_cds_last_change_entry_get_class (GUPnPCDSLastChangeEntry *entry);
+
+gboolean
+gupnp_cds_last_change_entry_is_subtree_update (GUPnPCDSLastChangeEntry *entry);
+
+guint32
+gupnp_cds_last_change_parser_get_update_id (GUPnPCDSLastChangeEntry *entry);
+
+G_END_DECLS
+
+#endif /* __GUPNP_CDS_LAST_CHANGE_PARSER_H__ */