[libgdata] Bug 647882 — Support rating schemes
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgdata] Bug 647882 — Support rating schemes
- Date: Fri, 29 Jul 2011 22:41:15 +0000 (UTC)
commit 96d88904bc10e066ebcee75e5eac4cf18e23ad55
Author: Philip Withnall <philip tecnocode co uk>
Date: Fri Jul 29 23:39:34 2011 +0100
Bug 647882 â Support rating schemes
Add support for media rating schemes (such as the MPAA's certificates) to
GDataYouTubeVideo (and GDataMediaGroup). This includes tests, and adds the
following new API:
â gdata_youtube_video_get_media_rating()
â GDATA_YOUTUBE_RATING_TYPE_SIMPLE
â GDATA_YOUTUBE_RATING_TYPE_MPAA
â GDATA_YOUTUBE_RATING_TYPE_V_CHIP
Closes: bgo#647882
docs/reference/gdata-sections.txt | 4 +
gdata/gdata.symbols | 4 +
gdata/media/gdata-media-group.c | 106 +++++++++++++++++++++----
gdata/media/gdata-media-group.h | 1 +
gdata/services/youtube/gdata-youtube-video.c | 27 ++++++
gdata/services/youtube/gdata-youtube-video.h | 34 ++++++++
gdata/tests/youtube.c | 111 ++++++++++++++++++++++++++
7 files changed, 271 insertions(+), 16 deletions(-)
---
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index 58ab6ee..2da91d1 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -217,6 +217,9 @@ GDATA_YOUTUBE_ACTION_COMMENT_VOTE
GDATA_YOUTUBE_ACTION_VIDEO_RESPOND
GDATA_YOUTUBE_ACTION_EMBED
GDATA_YOUTUBE_ACTION_SYNDICATE
+GDATA_YOUTUBE_RATING_TYPE_SIMPLE
+GDATA_YOUTUBE_RATING_TYPE_MPAA
+GDATA_YOUTUBE_RATING_TYPE_V_CHIP
GDataYouTubeVideo
GDataYouTubeVideoClass
GDataYouTubePermission
@@ -236,6 +239,7 @@ gdata_youtube_video_set_location
gdata_youtube_video_get_view_count
gdata_youtube_video_get_favorite_count
gdata_youtube_video_is_restricted_in_country
+gdata_youtube_video_get_media_rating
gdata_youtube_video_get_access_control
gdata_youtube_video_set_access_control
gdata_youtube_video_get_player_uri
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index 41f88ba..1220ce9 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -929,3 +929,7 @@ gdata_youtube_comment_get_parent_comment_uri
gdata_youtube_comment_set_parent_comment_uri
gdata_picasaweb_comment_get_type
gdata_picasaweb_comment_new
+GDATA_YOUTUBE_RATING_TYPE_SIMPLE
+GDATA_YOUTUBE_RATING_TYPE_MPAA
+GDATA_YOUTUBE_RATING_TYPE_V_CHIP
+gdata_youtube_video_get_media_rating
diff --git a/gdata/media/gdata-media-group.c b/gdata/media/gdata-media-group.c
index 94bf01e..21b9e33 100644
--- a/gdata/media/gdata-media-group.c
+++ b/gdata/media/gdata-media-group.c
@@ -55,6 +55,9 @@ struct _GDataMediaGroupPrivate {
gchar **keywords;
gchar *player_uri;
GHashTable *restricted_countries;
+ gchar *simple_rating;
+ gchar *mpaa_rating;
+ gchar *v_chip_rating;
GList *thumbnails; /* GDataMediaThumbnail */
gchar *title;
GDataMediaCategory *category;
@@ -126,6 +129,9 @@ gdata_media_group_finalize (GObject *object)
g_strfreev (priv->keywords);
g_free (priv->player_uri);
+ g_free (priv->v_chip_rating);
+ g_free (priv->mpaa_rating);
+ g_free (priv->simple_rating);
g_hash_table_destroy (priv->restricted_countries);
g_free (priv->title);
g_free (priv->description);
@@ -194,25 +200,61 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
self->priv->player_uri = (gchar*) player_uri;
} else if (xmlStrcmp (node->name, (xmlChar*) "rating") == 0) {
/* media:rating */
- xmlChar *countries;
-
- countries = xmlGetProp (node, (xmlChar*) "country");
-
- if (countries != NULL) {
- gchar **country_list, **country;
-
- /* It's either a comma-separated list of countries, or the value "all" */
- country_list = g_strsplit ((const gchar*) countries, ",", -1);
- xmlFree (countries);
+ xmlChar *scheme;
+
+ /* The possible schemes are defined here:
+ * â http://video.search.yahoo.com/mrss
+ * â http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_media:rating
+ */
+ scheme = xmlGetProp (node, (xmlChar*) "scheme");
+
+ if (scheme == NULL || xmlStrcmp (scheme, (xmlChar*) "urn:simple") == 0) {
+ /* Options: adult, nonadult */
+ gdata_parser_string_from_element (node, "rating", P_REQUIRED | P_NON_EMPTY, &(self->priv->simple_rating),
+ &success, error);
+ } else if (xmlStrcmp (scheme, (xmlChar*) "urn:mpaa") == 0) {
+ /* Options: g, pg, pg-13, r, nc-17 */
+ gdata_parser_string_from_element (node, "rating", P_REQUIRED | P_NON_EMPTY, &(self->priv->mpaa_rating),
+ &success, error);
+ } else if (xmlStrcmp (scheme, (xmlChar*) "urn:v-chip") == 0) {
+ /* Options: tv-y, tv-y7, tv-y7-fv, tv-g, tv-pg, tv-14, tv-ma */
+ gdata_parser_string_from_element (node, "rating", P_REQUIRED | P_NON_EMPTY, &(self->priv->v_chip_rating),
+ &success, error);
+ } else if (xmlStrcmp (scheme, (xmlChar*) "http://gdata.youtube.com/schemas/2007#mediarating") == 0) {
+ /* No content, but we do get a list of countries. There's nothing like overloading the semantics of XML elements
+ * to brighten up one's day. */
+ xmlChar *countries;
+
+ countries = xmlGetProp (node, (xmlChar*) "country");
+
+ if (countries != NULL) {
+ gchar **country_list, **country;
+
+ /* It's either a comma-separated list of countries, or the value "all" */
+ country_list = g_strsplit ((const gchar*) countries, ",", -1);
+ xmlFree (countries);
+
+ /* Add all the listed countries to the restricted countries table */
+ for (country = country_list; *country != NULL; country++) {
+ g_hash_table_insert (self->priv->restricted_countries, *country, GUINT_TO_POINTER (TRUE));
+ }
+
+ g_free (country_list);
+ } else {
+ /* Assume it's restricted in all countries */
+ g_hash_table_insert (self->priv->restricted_countries, g_strdup ("all"), GUINT_TO_POINTER (TRUE));
+ }
- /* Add all the listed countries to the restricted countries table */
- for (country = country_list; *country != NULL; country++)
- g_hash_table_insert (self->priv->restricted_countries, *country, GUINT_TO_POINTER (TRUE));
- g_free (country_list);
+ success = TRUE;
} else {
- /* Assume it's restricted in all countries */
- g_hash_table_insert (self->priv->restricted_countries, g_strdup ("all"), GUINT_TO_POINTER (TRUE));
+ /* Error */
+ gdata_parser_error_unknown_property_value (node, "scheme", (gchar*) scheme, error);
+ success = FALSE;
}
+
+ xmlFree (scheme);
+
+ return success;
} else if (xmlStrcmp (node->name, (xmlChar*) "restriction") == 0) {
/* media:restriction */
xmlChar *type, *countries, *relationship;
@@ -576,6 +618,38 @@ gdata_media_group_is_restricted_in_country (GDataMediaGroup *self, const gchar *
}
/**
+ * gdata_media_group_get_media_rating:
+ * @self: a #GDataMediaGroup
+ * @rating_type: the type of rating to retrieve
+ *
+ * Returns the rating of the given type for the media, if one exists. For example, this could be a film rating awarded by the MPAA.
+ * The valid values for @rating_type are: <code class="literal">simple</code>, <code class="literal">mpaa</code> and
+ * <code class="literal">v-chip</code>.
+ *
+ * The rating values returned for each of these rating types are string as defined in the
+ * <ulink type="http" url="http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_media:rating">YouTube documentation</ulink> and
+ * <ulink type="http" url="http://video.search.yahoo.com/mrss">MRSS specification</ulink>.
+ *
+ * Return value: rating for the given rating type, or %NULL if the media has no rating for that type (or the type is invalid)
+ */
+const gchar *
+gdata_media_group_get_media_rating (GDataMediaGroup *self, const gchar *rating_type)
+{
+ g_return_val_if_fail (GDATA_IS_MEDIA_GROUP (self), NULL);
+ g_return_val_if_fail (rating_type != NULL && *rating_type != '\0', NULL);
+
+ if (strcmp (rating_type, "simple") == 0) {
+ return self->priv->simple_rating;
+ } else if (strcmp (rating_type, "mpaa") == 0) {
+ return self->priv->mpaa_rating;
+ } else if (strcmp (rating_type, "v-chip") == 0) {
+ return self->priv->v_chip_rating;
+ }
+
+ return NULL;
+}
+
+/**
* gdata_media_group_get_thumbnails:
* @self: a #GDataMediaGroup
*
diff --git a/gdata/media/gdata-media-group.h b/gdata/media/gdata-media-group.h
index 9156699..f8ce7aa 100644
--- a/gdata/media/gdata-media-group.h
+++ b/gdata/media/gdata-media-group.h
@@ -79,6 +79,7 @@ GDataMediaCredit *gdata_media_group_get_credit (GDataMediaGroup *self) G_GNUC_PU
void _gdata_media_group_set_credit (GDataMediaGroup *self, GDataMediaCredit *credit);
const gchar *gdata_media_group_get_player_uri (GDataMediaGroup *self) G_GNUC_PURE;
gboolean gdata_media_group_is_restricted_in_country (GDataMediaGroup *self, const gchar *country) G_GNUC_PURE;
+const gchar *gdata_media_group_get_media_rating (GDataMediaGroup *self, const gchar *rating_type) G_GNUC_PURE;
GList *gdata_media_group_get_thumbnails (GDataMediaGroup *self) G_GNUC_PURE;
void _gdata_media_group_add_thumbnail (GDataMediaGroup *self, GDataMediaThumbnail *thumbnail);
diff --git a/gdata/services/youtube/gdata-youtube-video.c b/gdata/services/youtube/gdata-youtube-video.c
index c56a9ea..4b60ebf 100644
--- a/gdata/services/youtube/gdata-youtube-video.c
+++ b/gdata/services/youtube/gdata-youtube-video.c
@@ -1237,6 +1237,33 @@ gdata_youtube_video_is_restricted_in_country (GDataYouTubeVideo *self, const gch
}
/**
+ * gdata_youtube_video_get_media_rating:
+ * @self: a #GDataYouTubeVideo
+ * @rating_type: the type of rating to retrieve
+ *
+ * Returns the rating of the given type for the video, if one exists. For example, this could be a film rating awarded by the MPAA; or a simple
+ * rating specifying whether the video contains adult content.
+ *
+ * The valid values for @rating_type are: %GDATA_YOUTUBE_RATING_TYPE_SIMPLE, %GDATA_YOUTUBE_RATING_TYPE_MPAA and %GDATA_YOUTUBE_RATING_TYPE_V_CHIP.
+ * Further values may be added in future; if an unknown rating type is passed to the function, %NULL will be returned.
+ *
+ * The possible return values depend on what's passed to @rating_type. Valid values for each rating type are listed in the documentation for the
+ * rating types.
+ *
+ * Return value: the rating of the video for the given @rating_type, or %NULL if the video isn't rated with that type (or the type is unknown)
+ *
+ * Since: 0.9.2
+ */
+const gchar *
+gdata_youtube_video_get_media_rating (GDataYouTubeVideo *self, const gchar *rating_type)
+{
+ g_return_val_if_fail (GDATA_IS_YOUTUBE_VIDEO (self), NULL);
+ g_return_val_if_fail (rating_type != NULL && *rating_type != '\0', NULL);
+
+ return gdata_media_group_get_media_rating (self->priv->media_group, rating_type);
+}
+
+/**
* gdata_youtube_video_get_category:
* @self: a #GDataYouTubeVideo
*
diff --git a/gdata/services/youtube/gdata-youtube-video.h b/gdata/services/youtube/gdata-youtube-video.h
index 6fbce5e..93b80c2 100644
--- a/gdata/services/youtube/gdata-youtube-video.h
+++ b/gdata/services/youtube/gdata-youtube-video.h
@@ -98,6 +98,39 @@ G_BEGIN_DECLS
#define GDATA_YOUTUBE_ACTION_SYNDICATE "syndicate"
/**
+ * GDATA_YOUTUBE_RATING_TYPE_SIMPLE:
+ *
+ * A rating type to pass to gdata_youtube_video_get_media_rating() for âsimpleâ ratings. The values which can be returned for such ratings are:
+ * <code class="literal">adult</code> and <code class="literal">nonadult</code>.
+ *
+ * Since: 0.9.2
+ */
+#define GDATA_YOUTUBE_RATING_TYPE_SIMPLE "simple"
+
+/**
+ * GDATA_YOUTUBE_RATING_TYPE_MPAA:
+ *
+ * A rating type to pass to gdata_youtube_video_get_media_rating() for ratings by the <ulink type="http" url="http://www.mpaa.org/">MPAA</ulink>. The
+ * values which can be returned for such ratings are: <code class="literal">g</code>, <code class="literal">pg</code>,
+ * <code class="literal">pg-13</code>, <code class="literal">r</code> and <code class="literal">nc-17</code>.
+ *
+ * Since: 0.9.2
+ */
+#define GDATA_YOUTUBE_RATING_TYPE_MPAA "mpaa"
+
+/**
+ * GDATA_YOUTUBE_RATING_TYPE_V_CHIP:
+ *
+ * A rating type to pass to gdata_youtube_video_get_media_rating() for ratings following the FCC
+ * <ulink type="http" url="http://www.fcc.gov/vchip/">V-Chip</ulink> system. The values which can be returned for such ratings are:
+ * <code class="literal">tv-y</code>, <code class="literal">tv-y7</code>, <code class="literal">tv-y7-fv</code>, <code class="literal">tv-g</code>,
+ * <code class="literal">tv-pg</code>, <code class="literal">tv-14</code> and <code class="literal">tv-ma</code>.
+ *
+ * Since: 0.9.2
+ */
+#define GDATA_YOUTUBE_RATING_TYPE_V_CHIP "v-chip"
+
+/**
* GDataYouTubePermission:
* @GDATA_YOUTUBE_PERMISSION_ALLOWED: the action is allowed for everyone
* @GDATA_YOUTUBE_PERMISSION_DENIED: the action is denied for everyone
@@ -160,6 +193,7 @@ const gchar * const *gdata_youtube_video_get_keywords (GDataYouTubeVideo *self)
void gdata_youtube_video_set_keywords (GDataYouTubeVideo *self, const gchar * const *keywords);
const gchar *gdata_youtube_video_get_player_uri (GDataYouTubeVideo *self) G_GNUC_PURE;
gboolean gdata_youtube_video_is_restricted_in_country (GDataYouTubeVideo *self, const gchar *country) G_GNUC_PURE;
+const gchar *gdata_youtube_video_get_media_rating (GDataYouTubeVideo *self, const gchar *rating_type) G_GNUC_PURE;
GDataMediaCategory *gdata_youtube_video_get_category (GDataYouTubeVideo *self) G_GNUC_PURE;
void gdata_youtube_video_set_category (GDataYouTubeVideo *self, GDataMediaCategory *category);
GDataYouTubeCredit *gdata_youtube_video_get_credit (GDataYouTubeVideo *self) G_GNUC_PURE;
diff --git a/gdata/tests/youtube.c b/gdata/tests/youtube.c
index e9e0ae2..708e7db 100644
--- a/gdata/tests/youtube.c
+++ b/gdata/tests/youtube.c
@@ -1023,6 +1023,115 @@ test_parsing_media_group (void)
}
static void
+test_parsing_media_group_ratings (void)
+{
+ GDataYouTubeVideo *video;
+ GError *error = NULL;
+
+ /* Parse all ratings */
+ video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_xml (GDATA_TYPE_YOUTUBE_VIDEO,
+ "<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:media='http://search.yahoo.com/mrss/' "
+ "xmlns:yt='http://gdata.youtube.com/schemas/2007' "
+ "xmlns:gd='http://schemas.google.com/g/2005'>"
+ "<id>tag:youtube.com,2008:video:JAagedeKdcQ</id>"
+ "<published>2006-05-16T14:06:37.000Z</published>"
+ "<updated>2009-03-23T12:46:58.000Z</updated>"
+ "<category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#video'/>"
+ "<title>Some video somewhere</title>"
+ "<media:group>"
+ "<media:rating scheme='urn:simple'>nonadult</media:rating>"
+ "<media:rating scheme='urn:mpaa'>pg</media:rating>"
+ "<media:rating scheme='urn:v-chip'>tv-pg</media:rating>"
+ "</media:group>"
+ "</entry>", -1, &error));
+ g_assert_no_error (error);
+ g_assert (GDATA_IS_YOUTUBE_VIDEO (video));
+ g_clear_error (&error);
+
+ /* Check the ratings, and check that we haven't ended up with a country restriction */
+ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_SIMPLE), ==, "nonadult");
+ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_MPAA), ==, "pg");
+ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_V_CHIP), ==, "tv-pg");
+
+ g_assert (gdata_youtube_video_is_restricted_in_country (video, "US") == FALSE);
+
+ g_object_unref (video);
+
+ /* Parse a video with one rating missing and see what happens */
+ video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_xml (GDATA_TYPE_YOUTUBE_VIDEO,
+ "<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:media='http://search.yahoo.com/mrss/' "
+ "xmlns:yt='http://gdata.youtube.com/schemas/2007' "
+ "xmlns:gd='http://schemas.google.com/g/2005'>"
+ "<id>tag:youtube.com,2008:video:JAagedeKdcQ</id>"
+ "<published>2006-05-16T14:06:37.000Z</published>"
+ "<updated>2009-03-23T12:46:58.000Z</updated>"
+ "<category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#video'/>"
+ "<title>Some video somewhere</title>"
+ "<media:group>"
+ "<media:rating scheme='urn:v-chip'>tv-y7-fv</media:rating>"
+ "<media:rating>adult</media:rating>"
+ "</media:group>"
+ "</entry>", -1, &error));
+ g_assert_no_error (error);
+ g_assert (GDATA_IS_YOUTUBE_VIDEO (video));
+ g_clear_error (&error);
+
+ /* Check the ratings again */
+ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_SIMPLE), ==, "adult");
+ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_MPAA), ==, NULL);
+ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_V_CHIP), ==, "tv-y7-fv");
+
+ /* Check that calling with an arbitrary rating type returns NULL */
+ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, "fooish bar"), ==, NULL);
+
+ g_object_unref (video);
+}
+
+static void
+test_parsing_media_group_ratings_error_handling (void)
+{
+ GDataYouTubeVideo *video;
+ GError *error = NULL;
+
+#define TEST_XML_ERROR_HANDLING(x) \
+ video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_xml (GDATA_TYPE_YOUTUBE_VIDEO,\
+ "<entry xmlns='http://www.w3.org/2005/Atom' "\
+ "xmlns:media='http://search.yahoo.com/mrss/' "\
+ "xmlns:yt='http://gdata.youtube.com/schemas/2007' "\
+ "xmlns:gd='http://schemas.google.com/g/2005'>"\
+ "<id>tag:youtube.com,2008:video:JAagedeKdcQ</id>"\
+ "<published>2006-05-16T14:06:37.000Z</published>"\
+ "<updated>2009-03-23T12:46:58.000Z</updated>"\
+ "<category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#video'/>"\
+ "<title>Some video somewhere</title>"\
+ "<media:group>"\
+ x\
+ "</media:group>"\
+ "</entry>", -1, &error));\
+ g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
+ g_assert (video == NULL);\
+ g_clear_error (&error)
+
+ /* Missing content */
+ TEST_XML_ERROR_HANDLING ("<media:rating scheme='urn:simple'/>");
+ TEST_XML_ERROR_HANDLING ("<media:rating scheme='urn:mpaa'/>");
+ TEST_XML_ERROR_HANDLING ("<media:rating scheme='urn:v-chip'/>");
+
+ /* Empty content */
+ TEST_XML_ERROR_HANDLING ("<media:rating scheme='urn:simple'></media:rating>");
+ TEST_XML_ERROR_HANDLING ("<media:rating scheme='urn:mpaa'></media:rating>");
+ TEST_XML_ERROR_HANDLING ("<media:rating scheme='urn:v-chip'></media:rating>");
+
+ /* Unknown/Empty scheme */
+ TEST_XML_ERROR_HANDLING ("<media:rating scheme=''>foo</media:rating>");
+ TEST_XML_ERROR_HANDLING ("<media:rating scheme='urn:baz'>bob</media:rating>");
+
+#undef TEST_XML_ERROR_HANDLING
+}
+
+static void
test_video_escaping (void)
{
GDataYouTubeVideo *video;
@@ -1980,6 +2089,8 @@ main (int argc, char *argv[])
g_test_add_func ("/youtube/parsing/video_id_from_uri", test_parsing_video_id_from_uri);
g_test_add_func ("/youtube/parsing/georss:where", test_parsing_georss_where);
g_test_add_func ("/youtube/parsing/media:group", test_parsing_media_group);
+ g_test_add_func ("/youtube/parsing/media:group/ratings", test_parsing_media_group_ratings);
+ g_test_add_func ("/youtube/parsing/media:group/ratings/error_handling", test_parsing_media_group_ratings_error_handling);
g_test_add_func ("/youtube/video/escaping", test_video_escaping);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]