[libgdata] Bug 579170 – Eliminate gdata_parser_error_unhandled_element



commit f81049f70f1568f95b3db8ca5ed6d7e8891b0644
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sat Jun 13 19:44:17 2009 +0100

    Bug 579170 â?? Eliminate gdata_parser_error_unhandled_element
    
    Split parsing of app:control elements in GDataYouTubeVideo out into
    GDataYouTubeControl, and converted the GDataYouTubeState struct to a GObject.
    
    All instances of gdata_parser_error_unhandled_element are now banished.
    Closes: bgo#579170

 docs/reference/Makefile.am                     |    4 +-
 docs/reference/gdata-docs.xml                  |    6 +-
 docs/reference/gdata-sections.txt              |   29 ++-
 gdata/gdata-parser.c                           |   15 --
 gdata/gdata-parser.h                           |    1 -
 gdata/gdata.h                                  |    2 +-
 gdata/gdata.symbols                            |    7 +-
 gdata/services/youtube/Makefile.am             |   10 +-
 gdata/services/youtube/gdata-youtube-control.c |  190 +++++++++++++++
 gdata/services/youtube/gdata-youtube-control.h |   70 ++++++
 gdata/services/youtube/gdata-youtube-service.c |    5 +-
 gdata/services/youtube/gdata-youtube-state.c   |  297 ++++++++++++++++++++++++
 gdata/services/youtube/gdata-youtube-state.h   |   70 ++++++
 gdata/services/youtube/gdata-youtube-video.c   |   91 ++++----
 gdata/services/youtube/gdata-youtube-video.h   |    2 +-
 gdata/services/youtube/gdata-youtube.c         |   78 ------
 gdata/services/youtube/gdata-youtube.h         |   52 ----
 gdata/tests/youtube.c                          |   12 +-
 18 files changed, 721 insertions(+), 220 deletions(-)
---
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 0e65b30..1602c35 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -60,7 +60,9 @@ IGNORE_HFILES = \
 	gdata-media-group.c	\
 	gdata-media-group.h	\
 	gdata-youtube-group.c	\
-	gdata-youtube-group.h
+	gdata-youtube-group.h	\
+	gdata-youtube-control.c	\
+	gdata-youtube-control.h
 
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/docs/reference/gdata-docs.xml b/docs/reference/gdata-docs.xml
index cc9285c..b6e3d57 100644
--- a/docs/reference/gdata-docs.xml
+++ b/docs/reference/gdata-docs.xml
@@ -75,11 +75,7 @@
 			<title>YouTube API</title>
 			<xi:include href="xml/gdata-youtube-content.xml"/>
 			<xi:include href="xml/gdata-youtube-credit.xml"/>
-		</chapter>
-
-		<chapter>
-			<title>Other API</title>
-			<xi:include href="xml/gdata-youtube.xml"/>
+			<xi:include href="xml/gdata-youtube-state.xml"/>
 		</chapter>
 	</part>
 
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index f04cea1..efc928f 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -245,14 +245,6 @@ GDataYouTubeVideoPrivate
 </SECTION>
 
 <SECTION>
-<FILE>gdata-youtube</FILE>
-<TITLE>YouTube API</TITLE>
-GDataYouTubeState
-gdata_youtube_state_new
-gdata_youtube_state_free
-</SECTION>
-
-<SECTION>
 <FILE>gdata-contacts-service</FILE>
 <TITLE>GDataContactsService</TITLE>
 GDataContactsService
@@ -1102,3 +1094,24 @@ GDATA_TYPE_MEDIA_THUMBNAIL
 <SUBSECTION Private>
 GDataMediaThumbnailPrivate
 </SECTION>
+
+<SECTION>
+<FILE>gdata-youtube-state</FILE>
+<TITLE>GDataYouTubeState</TITLE>
+GDataYouTubeState
+GDataYouTubeStateClass
+gdata_youtube_state_get_name
+gdata_youtube_state_get_reason_code
+gdata_youtube_state_get_help_uri
+gdata_youtube_state_get_message
+<SUBSECTION Standard>
+gdata_youtube_state_get_type
+GDATA_YOUTUBE_STATE
+GDATA_YOUTUBE_STATE_CLASS
+GDATA_YOUTUBE_STATE_GET_CLASS
+GDATA_IS_YOUTUBE_STATE
+GDATA_IS_YOUTUBE_STATE_CLASS
+GDATA_TYPE_YOUTUBE_STATE
+<SUBSECTION Private>
+GDataYouTubeStatePrivate
+</SECTION>
diff --git a/gdata/gdata-parser.c b/gdata/gdata-parser.c
index b577f99..2adc56f 100644
--- a/gdata/gdata-parser.c
+++ b/gdata/gdata-parser.c
@@ -85,21 +85,6 @@ gdata_parser_error_not_iso8601_format (xmlNode *element, const gchar *actual_val
 }
 
 gboolean
-gdata_parser_error_unhandled_element (xmlNode *element, GError **error)
-{
-	gchar *element_string = print_element (element);
-
-	/* Translators: the parameter is the name of an XML element, including the angle brackets ("<" and ">").
-	 *
-	 * For example:
-	 *  Unhandled <entry/yt:aspectRatio> element. */
-	g_set_error (error, GDATA_PARSER_ERROR, GDATA_PARSER_ERROR_UNHANDLED_XML_ELEMENT, _("Unhandled %s element."), element_string);
-	g_free (element_string);
-
-	return FALSE;
-}
-
-gboolean
 gdata_parser_error_unknown_property_value (xmlNode *element, const gchar *property_name, const gchar *actual_value, GError **error)
 {
 	gchar *property_string, *element_string;
diff --git a/gdata/gdata-parser.h b/gdata/gdata-parser.h
index 194baed..61b4708 100644
--- a/gdata/gdata-parser.h
+++ b/gdata/gdata-parser.h
@@ -26,7 +26,6 @@ G_BEGIN_DECLS
 
 gboolean gdata_parser_error_required_content_missing (xmlNode *element, GError **error);
 gboolean gdata_parser_error_not_iso8601_format (xmlNode *element, const gchar *actual_value, GError **error);
-gboolean gdata_parser_error_unhandled_element (xmlNode *element, GError **error);
 gboolean gdata_parser_error_unknown_property_value (xmlNode *element, const gchar *property_name, const gchar *actual_value, GError **error);
 gboolean gdata_parser_error_required_property_missing (xmlNode *element, const gchar *property_name, GError **error);
 gboolean gdata_parser_error_required_element_missing (const gchar *element_name, const gchar *parent_element_name, GError **error);
diff --git a/gdata/gdata.h b/gdata/gdata.h
index dbaf5c4..5275fe6 100644
--- a/gdata/gdata.h
+++ b/gdata/gdata.h
@@ -63,9 +63,9 @@
 #include <gdata/services/youtube/gdata-youtube-service.h>
 #include <gdata/services/youtube/gdata-youtube-query.h>
 #include <gdata/services/youtube/gdata-youtube-video.h>
-#include <gdata/services/youtube/gdata-youtube.h>
 #include <gdata/services/youtube/gdata-youtube-content.h>
 #include <gdata/services/youtube/gdata-youtube-credit.h>
+#include <gdata/services/youtube/gdata-youtube-state.h>
 #include <gdata/services/youtube/gdata-youtube-enums.h>
 
 /* Google Calendar */
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index c1a60d0..a6f4adf 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -138,8 +138,6 @@ gdata_youtube_video_set_is_draft
 gdata_youtube_video_get_state
 gdata_youtube_video_get_recorded
 gdata_youtube_video_set_recorded
-gdata_youtube_state_new
-gdata_youtube_state_free
 gdata_youtube_format_get_type
 gdata_youtube_safe_search_get_type
 gdata_youtube_sort_order_get_type
@@ -478,3 +476,8 @@ gdata_media_thumbnail_get_uri
 gdata_media_thumbnail_get_height
 gdata_media_thumbnail_get_width
 gdata_media_thumbnail_get_time
+gdata_youtube_state_get_type
+gdata_youtube_state_get_name
+gdata_youtube_state_get_reason_code
+gdata_youtube_state_get_help_uri
+gdata_youtube_state_get_message
diff --git a/gdata/services/youtube/Makefile.am b/gdata/services/youtube/Makefile.am
index 1ead040..a4f0761 100644
--- a/gdata/services/youtube/Makefile.am
+++ b/gdata/services/youtube/Makefile.am
@@ -30,11 +30,11 @@ gdatayoutubeincludedir = $(pkgincludedir)/gdata/services/youtube
 gdatayoutubeinclude_HEADERS = \
 	gdata-youtube-service.h		\
 	gdata-youtube-video.h		\
-	gdata-youtube.h			\
 	gdata-youtube-content.h		\
 	gdata-youtube-credit.h		\
 	gdata-youtube-enums.h		\
-	gdata-youtube-query.h
+	gdata-youtube-query.h		\
+	gdata-youtube-state.h
 
 noinst_LTLIBRARIES = libgdatayoutube.la
 
@@ -42,12 +42,14 @@ libgdatayoutube_la_SOURCES = \
 	gdata-youtube-enums.c		\
 	gdata-youtube-service.c		\
 	gdata-youtube-video.c		\
-	gdata-youtube.c			\
 	gdata-youtube-content.c		\
 	gdata-youtube-credit.c		\
 	gdata-youtube-query.c		\
 	gdata-youtube-group.c		\
-	gdata-youtube-group.h
+	gdata-youtube-group.h		\
+	gdata-youtube-state.c		\
+	gdata-youtube-control.c		\
+	gdata-youtube-control.h
 
 libgdatayoutube_la_CPPFLAGS = \
 	-I$(top_srcdir)				\
diff --git a/gdata/services/youtube/gdata-youtube-control.c b/gdata/services/youtube/gdata-youtube-control.c
new file mode 100644
index 0000000..9821dc8
--- /dev/null
+++ b/gdata/services/youtube/gdata-youtube-control.c
@@ -0,0 +1,190 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * GData Client
+ * Copyright (C) Philip Withnall 2009 <philip tecnocode co uk>
+ * 
+ * GData Client is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GData Client 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:gdata-youtube-control
+ * @short_description: Atom Publishing Protocol control element with YouTube-specific modifications
+ * @stability: Unstable
+ * @include: gdata/services/youtube/gdata-youtube-control.h
+ *
+ * #GDataYouTubeControl represents a "control" element from the
+ * <ulink type="http" url="http://www.atomenabled.org/developers/protocol/#appControl";>Atom Publishing Protocol specification</ulink>,
+ * with support for the YouTube-specific <ulink type="http" url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state";>
+ * "state" element</ulink>.
+ *
+ * It is private API, since it would be unnecessary and confusing to expose #GDataYouTubeControl itself. There is the option
+ * of breaking this up into #GDataAPPControl and extending #GDataYouTubeControl classes in the future, if more entry types implement
+ * APP support.
+ *
+ * For these reasons, properties have not been implemented on #GDataYouTubeControl (yet).
+ **/
+
+#include <glib.h>
+#include <libxml/parser.h>
+
+#include "gdata-youtube-control.h"
+#include "gdata-parsable.h"
+#include "gdata-parser.h"
+#include "gdata-private.h"
+#include "gdata-youtube-state.h"
+
+static void gdata_youtube_control_dispose (GObject *object);
+static gboolean parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error);
+static void get_xml (GDataParsable *parsable, GString *xml_string);
+static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
+
+struct _GDataYouTubeControlPrivate {
+	gboolean is_draft;
+	GDataYouTubeState *state;
+};
+
+G_DEFINE_TYPE (GDataYouTubeControl, gdata_youtube_control, GDATA_TYPE_PARSABLE)
+#define GDATA_YOUTUBE_CONTROL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GDATA_TYPE_YOUTUBE_CONTROL, GDataYouTubeControlPrivate))
+
+static void
+gdata_youtube_control_class_init (GDataYouTubeControlClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GDataYouTubeControlPrivate));
+
+	gobject_class->dispose = gdata_youtube_control_dispose;
+
+	parsable_class->parse_xml = parse_xml;
+	parsable_class->get_xml = get_xml;
+	parsable_class->get_namespaces = get_namespaces;
+}
+
+static void
+gdata_youtube_control_init (GDataYouTubeControl *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_YOUTUBE_CONTROL, GDataYouTubeControlPrivate);
+}
+
+static void
+gdata_youtube_control_dispose (GObject *object)
+{
+	GDataYouTubeControlPrivate *priv = GDATA_YOUTUBE_CONTROL (object)->priv;
+
+	if (priv->state != NULL)
+		g_object_unref (priv->state);
+	priv->state = NULL;
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (gdata_youtube_control_parent_class)->dispose (object);
+}
+
+static gboolean
+parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
+{
+	GDataYouTubeControl *self = GDATA_YOUTUBE_CONTROL (parsable);
+
+	if (xmlStrcmp (node->name, (xmlChar*) "draft") == 0) {
+		/* app:draft */
+		xmlChar *draft = xmlNodeListGetString (doc, node, TRUE);
+		if (xmlStrcmp (draft, (xmlChar*) "no") == 0)
+			self->priv->is_draft = FALSE;
+		else
+			self->priv->is_draft = TRUE;
+		xmlFree (draft);
+	} else if (xmlStrcmp (node->name, (xmlChar*) "state") == 0) {
+		/* yt:state */
+		GDataYouTubeState *state = GDATA_YOUTUBE_STATE (_gdata_parsable_new_from_xml_node (GDATA_TYPE_YOUTUBE_STATE, "state", doc,
+												   node, NULL, error));
+		if (state == NULL)
+			return FALSE;
+
+		if (self->priv->state != NULL) {
+			g_object_unref (state);
+			return gdata_parser_error_duplicate_element (node, error);
+		}
+
+		self->priv->state = state;
+	} else if (GDATA_PARSABLE_CLASS (gdata_youtube_control_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
+		/* Error! */
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+get_xml (GDataParsable *parsable, GString *xml_string)
+{
+	GDataYouTubeControlPrivate *priv = GDATA_YOUTUBE_CONTROL (parsable)->priv;
+
+	if (priv->is_draft == TRUE)
+		g_string_append (xml_string, "<app:draft>yes</app:draft>");
+	else
+		g_string_append (xml_string, "<app:draft>no</app:draft>");
+}
+
+static void
+get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
+{
+	g_hash_table_insert (namespaces, (gchar*) "app", (gchar*) "http://www.w3.org/2007/app";);
+}
+
+/**
+ * gdata_youtube_control_is_draft:
+ * @self: a #GDataYouTubeControl
+ *
+ * Gets the #GDataYouTubeControl:is-draft property.
+ *
+ * Return value: %TRUE if the object is a draft, %FALSE otherwise
+ **/
+gboolean
+gdata_youtube_control_is_draft (GDataYouTubeControl *self)
+{
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_CONTROL (self), FALSE);
+	return self->priv->is_draft;
+}
+
+/**
+ * gdata_youtube_control_set_is_draft:
+ * @self: a #GDataYouTubeControl
+ * @is_draft: whether the object is a draft
+ *
+ * Sets the #GDataYouTubeControl:is-draft property to decide whether the object is a draft.
+ **/
+void
+gdata_youtube_control_set_is_draft (GDataYouTubeControl *self, gboolean is_draft)
+{
+	g_return_if_fail (GDATA_IS_YOUTUBE_CONTROL (self));
+	self->priv->is_draft = is_draft;
+}
+
+/**
+ * gdata_youtube_control_get_state:
+ * @self: a #GDataYouTubeControl
+ *
+ * Gets the #GDataYouTubeControl:state property.
+ *
+ * For more information, see the <ulink type="http"
+ * url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state";>online documentation</ulink>.
+ *
+ * Return value: a #GDataYouTubeState showing the state of the video, or %NULL
+ **/
+GDataYouTubeState *
+gdata_youtube_control_get_state (GDataYouTubeControl *self)
+{
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_CONTROL (self), NULL);
+	return self->priv->state;
+}
diff --git a/gdata/services/youtube/gdata-youtube-control.h b/gdata/services/youtube/gdata-youtube-control.h
new file mode 100644
index 0000000..cd0916e
--- /dev/null
+++ b/gdata/services/youtube/gdata-youtube-control.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * GData Client
+ * Copyright (C) Philip Withnall 2009 <philip tecnocode co uk>
+ * 
+ * GData Client is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GData Client 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GDATA_YOUTUBE_CONTROL_H
+#define GDATA_YOUTUBE_CONTROL_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gdata/gdata-parsable.h>
+#include <gdata/services/youtube/gdata-youtube-state.h>
+
+G_BEGIN_DECLS
+
+#define GDATA_TYPE_YOUTUBE_CONTROL		(gdata_youtube_control_get_type ())
+#define GDATA_YOUTUBE_CONTROL(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GDATA_TYPE_YOUTUBE_CONTROL, GDataYouTubeControl))
+#define GDATA_YOUTUBE_CONTROL_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), GDATA_TYPE_YOUTUBE_CONTROL, GDataYouTubeControlClass))
+#define GDATA_IS_YOUTUBE_CONTROL(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GDATA_TYPE_YOUTUBE_CONTROL))
+#define GDATA_IS_YOUTUBE_CONTROL_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GDATA_TYPE_YOUTUBE_CONTROL))
+#define GDATA_YOUTUBE_CONTROL_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GDATA_TYPE_YOUTUBE_CONTROL, GDataYouTubeControlClass))
+
+typedef struct _GDataYouTubeControlPrivate	GDataYouTubeControlPrivate;
+
+/**
+ * GDataYouTubeControl:
+ *
+ * All the fields in the #GDataYouTubeControl structure are private and should never be accessed directly.
+ **/
+typedef struct {
+	GDataParsable parent;
+	GDataYouTubeControlPrivate *priv;
+} GDataYouTubeControl;
+
+/**
+ * GDataYouTubeControlClass:
+ *
+ * All the fields in the #GDataYouTubeControlClass structure are private and should never be accessed directly.
+ *
+ * Since: 0.4.0
+ **/
+typedef struct {
+	/*< private >*/
+	GDataParsableClass parent;
+} GDataYouTubeControlClass;
+
+GType gdata_youtube_control_get_type (void) G_GNUC_CONST;
+
+gboolean gdata_youtube_control_is_draft (GDataYouTubeControl *self);
+void gdata_youtube_control_set_is_draft (GDataYouTubeControl *self, gboolean is_draft);
+GDataYouTubeState *gdata_youtube_control_get_state (GDataYouTubeControl *self);
+
+G_END_DECLS
+
+#endif /* !GDATA_YOUTUBE_CONTROL_H */
diff --git a/gdata/services/youtube/gdata-youtube-service.c b/gdata/services/youtube/gdata-youtube-service.c
index 5f5b946..2fd82cd 100644
--- a/gdata/services/youtube/gdata-youtube-service.c
+++ b/gdata/services/youtube/gdata-youtube-service.c
@@ -282,10 +282,7 @@ parse_error_response (GDataService *self, GDataServiceError error_type, guint st
 				location = xmlNodeListGetString (doc, child_node->children, TRUE);
 			else if (xmlStrcmp (child_node->name, (xmlChar*) "internalReason") != 0) {
 				/* Unknown element (ignore internalReason) */
-				if (*error == NULL)
-					gdata_parser_error_unhandled_element (child_node, error);
-				else
-					g_warning ("Unhandled <error/%s> element.", child_node->name);
+				g_warning ("Unhandled <error/%s> element.", child_node->name);
 
 				xmlFree (domain);
 				xmlFree (code);
diff --git a/gdata/services/youtube/gdata-youtube-state.c b/gdata/services/youtube/gdata-youtube-state.c
new file mode 100644
index 0000000..eee7952
--- /dev/null
+++ b/gdata/services/youtube/gdata-youtube-state.c
@@ -0,0 +1,297 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * GData Client
+ * Copyright (C) Philip Withnall 2009 <philip tecnocode co uk>
+ * 
+ * GData Client is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GData Client 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:gdata-youtube-state
+ * @short_description: YouTube state element
+ * @stability: Unstable
+ * @include: gdata/services/youtube/gdata-youtube-state.h
+ *
+ * #GDataYouTubeState represents a "state" element from the
+ * <ulink type="http" url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state";>YouTube namespace</ulink>.
+ **/
+
+#include <glib.h>
+#include <libxml/parser.h>
+
+#include "gdata-youtube-state.h"
+#include "gdata-parsable.h"
+#include "gdata-parser.h"
+
+static void gdata_youtube_state_finalize (GObject *object);
+static void gdata_youtube_state_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static gboolean pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointer user_data, GError **error);
+static gboolean parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error);
+static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
+
+struct _GDataYouTubeStatePrivate {
+	gchar *name;
+	gchar *reason_code;
+	gchar *help_uri;
+	gchar *message;
+};
+
+enum {
+	PROP_NAME = 1,
+	PROP_REASON_CODE,
+	PROP_HELP_URI,
+	PROP_MESSAGE
+};
+
+G_DEFINE_TYPE (GDataYouTubeState, gdata_youtube_state, GDATA_TYPE_PARSABLE)
+#define GDATA_YOUTUBE_STATE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GDATA_TYPE_YOUTUBE_STATE, GDataYouTubeStatePrivate))
+
+static void
+gdata_youtube_state_class_init (GDataYouTubeStateClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GDataYouTubeStatePrivate));
+
+	gobject_class->get_property = gdata_youtube_state_get_property;
+	gobject_class->finalize = gdata_youtube_state_finalize;
+
+	parsable_class->pre_parse_xml = pre_parse_xml;
+	parsable_class->parse_xml = parse_xml;
+	parsable_class->get_namespaces = get_namespaces;
+
+	/**
+	 * GDataYouTubeState:name:
+	 *
+	 * The name of the status of the unpublished video. Valid values are: "processing", "restricted", "deleted", "rejected" and "failed".
+	 *
+	 * For more information, see the <ulink type="http" url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state";>
+	 * online documentation</ulink>.
+	 *
+	 * Since: 0.4.0
+	 **/
+	g_object_class_install_property (gobject_class, PROP_NAME,
+				g_param_spec_string ("name",
+					"Name", "The name of the status of the unpublished video.",
+					NULL,
+					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * GDataYouTubeState:reason-code:
+	 *
+	 * The reason code explaining why the video failed to upload.
+	 *
+	 * For more information, see the <ulink type="http" url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state";>
+	 * online documentation</ulink>.
+	 *
+	 * Since: 0.4.0
+	 **/
+	g_object_class_install_property (gobject_class, PROP_REASON_CODE,
+				g_param_spec_string ("reason-code",
+					"Reason code", "The reason code explaining why the video failed to upload.",
+					NULL,
+					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * GDataYouTubeState:help-uri:
+	 *
+	 * A URI for a YouTube Help Center page that may help the developer or the video owner to diagnose
+	 * the reason that an upload failed or was rejected.
+	 *
+	 * For more information, see the <ulink type="http" url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state";>
+	 * online documentation</ulink>.
+	 *
+	 * Since: 0.4.0
+	 **/
+	g_object_class_install_property (gobject_class, PROP_HELP_URI,
+				g_param_spec_string ("help-uri",
+					"Help URI", "A URI for a YouTube Help Center page.",
+					NULL,
+					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * GDataYouTubeState:message:
+	 *
+	 * A human-readable description of why the video failed to upload.
+	 *
+	 * For more information, see the <ulink type="http" url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state";>
+	 * online documentation</ulink>.
+	 *
+	 * Since: 0.4.0
+	 **/
+	g_object_class_install_property (gobject_class, PROP_MESSAGE,
+				g_param_spec_string ("message",
+					"Message", "A human-readable description of why the video failed to upload.",
+					NULL,
+					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gdata_youtube_state_init (GDataYouTubeState *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_YOUTUBE_STATE, GDataYouTubeStatePrivate);
+}
+
+static void
+gdata_youtube_state_finalize (GObject *object)
+{
+	GDataYouTubeStatePrivate *priv = GDATA_YOUTUBE_STATE (object)->priv;
+
+	xmlFree (priv->name);
+	xmlFree (priv->reason_code);
+	xmlFree (priv->help_uri);
+	xmlFree (priv->message);
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (gdata_youtube_state_parent_class)->finalize (object);
+}
+
+static void
+gdata_youtube_state_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	GDataYouTubeStatePrivate *priv = GDATA_YOUTUBE_STATE (object)->priv;
+
+	switch (property_id) {
+		case PROP_NAME:
+			g_value_set_string (value, priv->name);
+			break;
+		case PROP_REASON_CODE:
+			g_value_set_string (value, priv->reason_code);
+			break;
+		case PROP_HELP_URI:
+			g_value_set_string (value, priv->help_uri);
+			break;
+		case PROP_MESSAGE:
+			g_value_set_string (value, priv->message);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static gboolean
+pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointer user_data, GError **error)
+{
+	GDataYouTubeStatePrivate *priv = GDATA_YOUTUBE_STATE (parsable)->priv;
+	xmlChar *name, *message, *reason_code, *help_uri;
+
+	name = xmlGetProp (root_node, (xmlChar*) "name");
+	if (name == NULL || *name == '\0') {
+		xmlFree (name);
+		return gdata_parser_error_required_property_missing (root_node, "name", error);
+	}
+
+	message = xmlNodeListGetString (doc, root_node->children, TRUE);
+	reason_code = xmlGetProp (root_node, (xmlChar*) "reasonCode");
+	help_uri = xmlGetProp (root_node, (xmlChar*) "helpUrl");
+
+	priv->name = (gchar*) name;
+	priv->reason_code = (gchar*) reason_code;
+	priv->help_uri = (gchar*) help_uri;
+	priv->message = (gchar*) message;
+
+	return TRUE;
+}
+
+static gboolean
+parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
+{
+	/* Textual content's handled in pre_parse_xml */
+	if (node->type != XML_ELEMENT_NODE)
+		return TRUE;
+
+	if (GDATA_PARSABLE_CLASS (gdata_youtube_state_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
+		/* Error! */
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
+{
+	g_hash_table_insert (namespaces, (gchar*) "yt", (gchar*) "http://gdata.youtube.com/schemas/2007";);
+}
+
+/**
+ * gdata_youtube_state_get_name:
+ * @self: a #GDataYouTubeState
+ *
+ * Gets the #GDataYouTubeState:name property.
+ *
+ * Return value: the status name
+ *
+ * Since: 0.4.0
+ **/
+const gchar *
+gdata_youtube_state_get_name (GDataYouTubeState *self)
+{
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_STATE (self), NULL);
+	return self->priv->name;
+}
+
+/**
+ * gdata_youtube_state_get_reason_code:
+ * @self: a #GDataYouTubeState
+ *
+ * Gets the #GDataYouTubeState:reason-code property.
+ *
+ * Return value: the status reason code, or %NULL
+ *
+ * Since: 0.4.0
+ **/
+const gchar *
+gdata_youtube_state_get_reason_code (GDataYouTubeState *self)
+{
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_STATE (self), NULL);
+	return self->priv->reason_code;
+}
+
+/**
+ * gdata_youtube_state_get_help_uri:
+ * @self: a #GDataYouTubeState
+ *
+ * Gets the #GDataYouTubeState:help-uri property.
+ *
+ * Return value: the help URI, or %NULL
+ *
+ * Since: 0.4.0
+ **/
+const gchar *
+gdata_youtube_state_get_help_uri (GDataYouTubeState *self)
+{
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_STATE (self), NULL);
+	return self->priv->help_uri;
+}
+
+/**
+ * gdata_youtube_state_get_message:
+ * @self: a #GDataYouTubeState
+ *
+ * Gets the #GDataYouTubeState:message property.
+ *
+ * Return value: the status message, or %NULL
+ *
+ * Since: 0.4.0
+ **/
+const gchar *
+gdata_youtube_state_get_message (GDataYouTubeState *self)
+{
+	g_return_val_if_fail (GDATA_IS_YOUTUBE_STATE (self), NULL);
+	return self->priv->message;
+}
diff --git a/gdata/services/youtube/gdata-youtube-state.h b/gdata/services/youtube/gdata-youtube-state.h
new file mode 100644
index 0000000..e9460d9
--- /dev/null
+++ b/gdata/services/youtube/gdata-youtube-state.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * GData Client
+ * Copyright (C) Philip Withnall 2009 <philip tecnocode co uk>
+ * 
+ * GData Client is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GData Client 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GDATA_YOUTUBE_STATE_H
+#define GDATA_YOUTUBE_STATE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gdata/gdata-parsable.h>
+
+G_BEGIN_DECLS
+
+#define GDATA_TYPE_YOUTUBE_STATE		(gdata_youtube_state_get_type ())
+#define GDATA_YOUTUBE_STATE(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), GDATA_TYPE_YOUTUBE_STATE, GDataYouTubeState))
+#define GDATA_YOUTUBE_STATE_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), GDATA_TYPE_YOUTUBE_STATE, GDataYouTubeStateClass))
+#define GDATA_IS_YOUTUBE_STATE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GDATA_TYPE_YOUTUBE_STATE))
+#define GDATA_IS_YOUTUBE_STATE_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), GDATA_TYPE_YOUTUBE_STATE))
+#define GDATA_YOUTUBE_STATE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GDATA_TYPE_YOUTUBE_STATE, GDataYouTubeStateClass))
+
+typedef struct _GDataYouTubeStatePrivate	GDataYouTubeStatePrivate;
+
+/**
+ * GDataYouTubeState:
+ *
+ * All the fields in the #GDataYouTubeState structure are private and should never be accessed directly.
+ **/
+typedef struct {
+	GDataParsable parent;
+	GDataYouTubeStatePrivate *priv;
+} GDataYouTubeState;
+
+/**
+ * GDataYouTubeStateClass:
+ *
+ * All the fields in the #GDataYouTubeStateClass structure are private and should never be accessed directly.
+ *
+ * Since: 0.4.0
+ **/
+typedef struct {
+	/*< private >*/
+	GDataParsableClass parent;
+} GDataYouTubeStateClass;
+
+GType gdata_youtube_state_get_type (void) G_GNUC_CONST;
+
+const gchar *gdata_youtube_state_get_name (GDataYouTubeState *self);
+const gchar *gdata_youtube_state_get_reason_code (GDataYouTubeState *self);
+const gchar *gdata_youtube_state_get_help_uri (GDataYouTubeState *self);
+const gchar *gdata_youtube_state_get_message (GDataYouTubeState *self);
+
+G_END_DECLS
+
+#endif /* !GDATA_YOUTUBE_STATE_H */
diff --git a/gdata/services/youtube/gdata-youtube-video.c b/gdata/services/youtube/gdata-youtube-video.c
index 8abc394..f6c7561 100644
--- a/gdata/services/youtube/gdata-youtube-video.c
+++ b/gdata/services/youtube/gdata-youtube-video.c
@@ -43,13 +43,15 @@
 #include "media/gdata-media-thumbnail.h"
 #include "gdata-youtube-group.h"
 #include "gdata-types.h"
+#include "gdata-youtube-control.h"
 
 static void gdata_youtube_video_dispose (GObject *object);
 static void gdata_youtube_video_finalize (GObject *object);
 static void gdata_youtube_video_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
 static void gdata_youtube_video_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
-static void get_xml (GDataParsable *parsable, GString *xml_string);
 static gboolean parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error);
+static gboolean post_parse_xml (GDataParsable *parsable, gpointer user_data, GError **error);
+static void get_xml (GDataParsable *parsable, GString *xml_string);
 static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
 
 struct _GDataYouTubeVideoPrivate {
@@ -70,8 +72,7 @@ struct _GDataYouTubeVideoPrivate {
 	GDataMediaGroup *media_group; /* is actually a GDataYouTubeGroup */
 
 	/* Other properties */
-	gboolean is_draft;
-	GDataYouTubeState *state;
+	GDataYouTubeControl *youtube_control;
 	GTimeVal recorded;
 };
 
@@ -116,6 +117,7 @@ gdata_youtube_video_class_init (GDataYouTubeVideoClass *klass)
 	gobject_class->finalize = gdata_youtube_video_finalize;
 
 	parsable_class->parse_xml = parse_xml;
+	parsable_class->post_parse_xml = post_parse_xml;
 	parsable_class->get_xml = get_xml;
 	parsable_class->get_namespaces = get_namespaces;
 
@@ -396,8 +398,9 @@ gdata_youtube_video_class_init (GDataYouTubeVideoClass *klass)
 	 * url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state";>online documentation</ulink>.
 	 **/
 	g_object_class_install_property (gobject_class, PROP_STATE,
-				g_param_spec_pointer ("state",
+				g_param_spec_object ("state",
 					"State", "Information describing the state of the video.",
+					GDATA_TYPE_YOUTUBE_STATE,
 					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -432,6 +435,10 @@ gdata_youtube_video_dispose (GObject *object)
 		g_object_unref (priv->media_group);
 	priv->media_group = NULL;
 
+	if (priv->youtube_control != NULL)
+		g_object_unref (priv->youtube_control);
+	priv->youtube_control = NULL;
+
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (gdata_youtube_video_parent_class)->dispose (object);
 }
@@ -442,7 +449,6 @@ gdata_youtube_video_finalize (GObject *object)
 	GDataYouTubeVideoPrivate *priv = GDATA_YOUTUBE_VIDEO (object)->priv;
 
 	g_free (priv->location);
-	gdata_youtube_state_free (priv->state);
 
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (gdata_youtube_video_parent_class)->finalize (object);
@@ -511,10 +517,10 @@ gdata_youtube_video_get_property (GObject *object, guint property_id, GValue *va
 			g_value_set_string (value, gdata_youtube_group_get_video_id (GDATA_YOUTUBE_GROUP (priv->media_group)));
 			break;
 		case PROP_IS_DRAFT:
-			g_value_set_boolean (value, priv->is_draft);
+			g_value_set_boolean (value, gdata_youtube_control_is_draft (priv->youtube_control));
 			break;
 		case PROP_STATE:
-			g_value_set_pointer (value, priv->state);
+			g_value_set_object (value, gdata_youtube_control_get_state (priv->youtube_control));
 			break;
 		case PROP_RECORDED:
 			g_value_set_boxed (value, &(priv->recorded));
@@ -578,8 +584,9 @@ GDataYouTubeVideo *
 gdata_youtube_video_new (const gchar *id)
 {
 	GDataYouTubeVideo *video = g_object_new (GDATA_TYPE_YOUTUBE_VIDEO, "id", id, NULL);
-	/* We can't create this in init, or it would collide with the group created when parsing the XML */
+	/* We can't create these in init, or they would collide with the group and control created when parsing the XML */
 	video->priv->media_group = g_object_new (GDATA_TYPE_YOUTUBE_GROUP, NULL);
+	video->priv->youtube_control = g_object_new (GDATA_TYPE_YOUTUBE_CONTROL, NULL);
 	return video;
 }
 
@@ -735,40 +742,17 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		gdata_youtube_video_set_recorded (self, &recorded_timeval);
 	} else if (xmlStrcmp (node->name, (xmlChar*) "control") == 0) {
 		/* app:control */
-		xmlNode *child_node;
+		GDataYouTubeControl *control = GDATA_YOUTUBE_CONTROL (_gdata_parsable_new_from_xml_node (GDATA_TYPE_YOUTUBE_CONTROL, "control", doc,
+													 node, NULL, error));
+		if (control == NULL)
+			return FALSE;
 
-		child_node = node->children;
-		while (child_node != NULL) {
-			if (xmlStrcmp (child_node->name, (xmlChar*) "draft") == 0) {
-				/* app:draft */
-				gdata_youtube_video_set_is_draft (self, TRUE);
-			} else if (xmlStrcmp (child_node->name, (xmlChar*) "state") == 0) {
-				/* yt:state */
-				xmlChar *name, *message, *reason_code, *help_uri;
-
-				name = xmlGetProp (child_node, (xmlChar*) "name");
-				if (name == NULL)
-					return gdata_parser_error_required_property_missing (child_node, "name", error);
-
-				message = xmlNodeListGetString (doc, child_node->children, TRUE);
-				reason_code = xmlGetProp (child_node, (xmlChar*) "reasonCode");
-				help_uri = xmlGetProp (child_node, (xmlChar*) "helpUrl");
-
-				gdata_youtube_state_free (self->priv->state);
-				self->priv->state = gdata_youtube_state_new ((gchar*) name, (gchar*) message, (gchar*) reason_code, (gchar*) help_uri);
-				g_object_notify (G_OBJECT (self), "state");
-
-				xmlFree (name);
-				xmlFree (message);
-				xmlFree (reason_code);
-				xmlFree (help_uri);
-			} else {
-				/* Unhandled element */
-				return gdata_parser_error_unhandled_element (child_node, error);
-			}
-
-			child_node = child_node->next;
+		if (self->priv->youtube_control != NULL) {
+			g_object_unref (control);
+			return gdata_parser_error_duplicate_element (node, error);
 		}
+
+		self->priv->youtube_control = control;
 	} else if (GDATA_PARSABLE_CLASS (gdata_youtube_video_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
 		/* Error! */
 		return FALSE;
@@ -777,6 +761,21 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	return TRUE;
 }
 
+static gboolean
+post_parse_xml (GDataParsable *parsable, gpointer user_data, GError **error)
+{
+	GDataYouTubeVideoPrivate *priv = GDATA_YOUTUBE_VIDEO (parsable)->priv;
+
+	/* Chain up to the parent class */
+	GDATA_PARSABLE_CLASS (gdata_youtube_video_parent_class)->post_parse_xml (parsable, user_data, error);
+
+	/* This must always exist, so is_draft can be set on it */
+	if (priv->youtube_control == NULL)
+		priv->youtube_control = g_object_new (GDATA_TYPE_YOUTUBE_CONTROL, NULL);
+
+	return TRUE;
+}
+
 static void
 get_xml (GDataParsable *parsable, GString *xml_string)
 {
@@ -803,6 +802,9 @@ get_xml (GDataParsable *parsable, GString *xml_string)
 	if (priv->no_embed == TRUE)
 		g_string_append (xml_string, "<yt:noembed/>");
 
+	/* app:control */
+	g_string_append (xml_string, _gdata_parsable_get_xml (GDATA_PARSABLE (priv->youtube_control), "app:control", FALSE));
+
 	/* TODO:
 	 * - georss:where
 	 * - Check things are escaped (or not) as appropriate
@@ -819,8 +821,9 @@ get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
 
 	g_hash_table_insert (namespaces, (gchar*) "yt", (gchar*) "http://gdata.youtube.com/schemas/2007";);
 
-	/* Add the media:group namespaces */
+	/* Add the media:group and app:control namespaces */
 	GDATA_PARSABLE_GET_CLASS (priv->media_group)->get_namespaces (GDATA_PARSABLE (priv->media_group), namespaces);
+	GDATA_PARSABLE_GET_CLASS (priv->youtube_control)->get_namespaces (GDATA_PARSABLE (priv->youtube_control), namespaces);
 }
 
 /**
@@ -1247,7 +1250,7 @@ gboolean
 gdata_youtube_video_is_draft (GDataYouTubeVideo *self)
 {
 	g_return_val_if_fail (GDATA_IS_YOUTUBE_VIDEO (self), FALSE);
-	return self->priv->is_draft;
+	return gdata_youtube_control_is_draft (self->priv->youtube_control);
 }
 
 /**
@@ -1261,7 +1264,7 @@ void
 gdata_youtube_video_set_is_draft (GDataYouTubeVideo *self, gboolean is_draft)
 {
 	g_return_if_fail (GDATA_IS_YOUTUBE_VIDEO (self));
-	self->priv->is_draft = is_draft;
+	gdata_youtube_control_set_is_draft (self->priv->youtube_control, is_draft);
 	g_object_notify (G_OBJECT (self), "is-draft");
 }
 
@@ -1280,7 +1283,7 @@ GDataYouTubeState *
 gdata_youtube_video_get_state (GDataYouTubeVideo *self)
 {
 	g_return_val_if_fail (GDATA_IS_YOUTUBE_VIDEO (self), NULL);
-	return self->priv->state;
+	return gdata_youtube_control_get_state (self->priv->youtube_control);
 }
 
 /**
diff --git a/gdata/services/youtube/gdata-youtube-video.h b/gdata/services/youtube/gdata-youtube-video.h
index 1fb2be8..f886ff8 100644
--- a/gdata/services/youtube/gdata-youtube-video.h
+++ b/gdata/services/youtube/gdata-youtube-video.h
@@ -27,7 +27,7 @@
 #include <gdata/media/gdata-media-category.h>
 #include <gdata/services/youtube/gdata-youtube-content.h>
 #include <gdata/services/youtube/gdata-youtube-credit.h>
-#include <gdata/services/youtube/gdata-youtube.h>
+#include <gdata/services/youtube/gdata-youtube-state.h>
 
 G_BEGIN_DECLS
 
diff --git a/gdata/tests/youtube.c b/gdata/tests/youtube.c
index 832c52b..55458cc 100644
--- a/gdata/tests/youtube.c
+++ b/gdata/tests/youtube.c
@@ -362,10 +362,10 @@ test_parsing_app_control (void)
 	g_assert (gdata_youtube_video_is_draft (video) == TRUE);
 
 	state = gdata_youtube_video_get_state (video);
-	g_assert_cmpstr (state->name, ==, "blacklisted");
-	g_assert_cmpstr (state->message, ==, "This video is not available in your country");
-	g_assert (state->reason_code == NULL);
-	g_assert (state->help_uri == NULL);
+	g_assert_cmpstr (gdata_youtube_state_get_name (state), ==, "blacklisted");
+	g_assert_cmpstr (gdata_youtube_state_get_message (state), ==, "This video is not available in your country");
+	g_assert (gdata_youtube_state_get_reason_code (state) == NULL);
+	g_assert (gdata_youtube_state_get_help_uri (state) == NULL);
 
 	/* TODO: more tests on entry properties */
 
@@ -424,6 +424,7 @@ test_parsing_yt_recorded (void)
 				"xmlns:media='http://video.search.yahoo.com/mrss' "
 				"xmlns:gd='http://schemas.google.com/g/2005' "
 				"xmlns:yt='http://gdata.youtube.com/schemas/2007' "
+				"xmlns:app='http://www.w3.org/2007/app' "
 				"gd:etag='W/\"CEMFSX47eCp7ImA9WxVUGEw.\"'>"
 				"<title type='text'>Judas Priest - Painkiller</title>"
 				"<id>tag:youtube.com,2008:video:JAagedeKdcQ</id>"
@@ -441,6 +442,9 @@ test_parsing_yt_recorded (void)
 					"<media:title type='plain'>Judas Priest - Painkiller</media:title>"
 				"</media:group>"
 				"<yt:recorded>2005-10-02</yt:recorded>"
+				"<app:control>"
+					"<app:draft>no</app:draft>"
+				"</app:control>"
 			 "</entry>");
 	g_free (xml);
 



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