[grilo-plugins] [youtube] Started development of a new version based on libgdata.
- From: Iago Toral Quiroga <itoral src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grilo-plugins] [youtube] Started development of a new version based on libgdata.
- Date: Thu, 15 Apr 2010 09:15:48 +0000 (UTC)
commit 393be8335686da48000fbadf78e5a5e9129c11da
Author: Iago Toral Quiroga <itoral igalia com>
Date: Tue Apr 13 15:48:31 2010 +0200
[youtube] Started development of a new version based on libgdata.
src/youtube/grl-youtube.c | 1296 +++++++--------------------------------------
src/youtube/grl-youtube.h | 2 +
2 files changed, 182 insertions(+), 1116 deletions(-)
---
diff --git a/src/youtube/grl-youtube.c b/src/youtube/grl-youtube.c
index b8f27f0..d2f9548 100644
--- a/src/youtube/grl-youtube.c
+++ b/src/youtube/grl-youtube.c
@@ -26,10 +26,8 @@
#include <grilo.h>
#include <gio/gio.h>
-#include <libxml/parser.h>
-#include <libxml/xmlmemory.h>
+#include <gdata/gdata.h>
#include <string.h>
-#include <stdlib.h>
#include "grl-youtube.h"
@@ -44,7 +42,6 @@
#define YOUTUBE_FEEDS_ID "standard-feeds"
#define YOUTUBE_FEEDS_NAME "Standard feeds"
-#define YOUTUBE_FEEDS_URL NULL
#define YOUTUBE_CATEGORIES_ID "categories"
#define YOUTUBE_CATEGORIES_NAME "Categories"
@@ -54,47 +51,32 @@
#define YOUTUBE_VIEWED_ID (YOUTUBE_FEEDS_ID "/most-viewed")
#define YOUTUBE_VIEWED_NAME "Most viewed"
-#define YOUTUBE_VIEWED_URL "http://gdata.youtube.com/feeds/standardfeeds/most_viewed?start-index=%d&max-results=%d"
#define YOUTUBE_RATED_ID (YOUTUBE_FEEDS_ID "/most-rated")
#define YOUTUBE_RATED_NAME "Most rated"
-#define YOUTUBE_RATED_URL "http://gdata.youtube.com/feeds/standardfeeds/top_rated?start-index=%d&max-results=%d"
#define YOUTUBE_FAVS_ID (YOUTUBE_FEEDS_ID "/top-favs")
#define YOUTUBE_FAVS_NAME "Top favorites"
-#define YOUTUBE_FAVS_URL "http://gdata.youtube.com/feeds/standardfeeds/top_favorites?start-index=%d&max-results=%d"
#define YOUTUBE_RECENT_ID (YOUTUBE_FEEDS_ID "/most-recent")
#define YOUTUBE_RECENT_NAME "Most recent"
-#define YOUTUBE_RECENT_URL "http://gdata.youtube.com/feeds/standardfeeds/most_recent?start-index=%d&max-results=%d"
#define YOUTUBE_DISCUSSED_ID (YOUTUBE_FEEDS_ID "/most-discussed")
#define YOUTUBE_DISCUSSED_NAME "Most discussed"
-#define YOUTUBE_DISCUSSED_URL "http://gdata.youtube.com/feeds/standardfeeds/most_discussed?start-index=%d&max-results=%d"
#define YOUTUBE_FEATURED_ID (YOUTUBE_FEEDS_ID "/featured")
#define YOUTUBE_FEATURED_NAME "Featured"
-#define YOUTUBE_FEATURED_URL "http://gdata.youtube.com/feeds/standardfeeds/recently_featured?start-index=%d&max-results=%d"
#define YOUTUBE_MOBILE_ID (YOUTUBE_FEEDS_ID "/mobile")
#define YOUTUBE_MOBILE_NAME "Watch on mobile"
-#define YOUTUBE_MOBILE_URL "http://gdata.youtube.com/feeds/standardfeeds/watch_on_mobile?start-index=%d&max-results=%d"
-/* ----- Other Youtube URLs ---- */
+/* --- Other --- */
+
+#define YOUTUBE_MAX_CHUNK 50
#define YOUTUBE_VIDEO_INFO_URL "http://www.youtube.com/get_video_info?video_id=%s"
#define YOUTUBE_VIDEO_URL "http://www.youtube.com/get_video?video_id=%s&t=%s"
-#define YOUTUBE_SEARCH_URL "http://gdata.youtube.com/feeds/api/videos?vq=%s&start-index=%s&max-results=%s"
-#define YOUTUBE_CATEGORY_URL "http://gdata.youtube.com/feeds/api/videos/-/%s?&start-index=%s&max-results=%s"
-
-/* --- Youtube parsing hints ---- */
-
-#define YOUTUBE_TOTAL_RESULTS_START "<openSearch:totalResults>"
-#define YOUTUBE_TOTAL_RESULTS_END "</openSearch:totalResults>"
-
-/* --- Other --- */
-#define YOUTUBE_MAX_CHUNK 50
#define YOUTUBE_VIDEO_MIME "application/x-shockwave-flash"
#define YOUTUBE_SITE_URL "www.youtube.com"
@@ -117,18 +99,6 @@
typedef void (*AsyncReadCbFunc) (gchar *data, gpointer user_data);
typedef struct {
- gchar *id;
- gchar *title;
- gchar *published;
- gchar *author;
- gchar *thumbnail;
- gchar *description;
- gchar *duration;
- gchar *rating;
- gboolean restricted;
-} Entry;
-
-typedef struct {
GrlMediaSource *source;
guint operation_id;
const gchar *container_id;
@@ -136,47 +106,13 @@ typedef struct {
GrlMetadataResolutionFlags flags;
guint skip;
guint count;
- gboolean chained_chunk;
- gchar *query_url;
- gboolean cancelled;
GrlMediaSourceResultCb callback;
gpointer user_data;
+ const GDataYouTubeService *service;
+ guint error_code;
+ GDataQuery *query;
} OperationSpec;
-typedef struct {
- GrlMetadataSource *source;
- const GList *keys;
- GrlMediaSourceMetadataCb callback;
- gpointer user_data;
-} MetadataOperationSpec;
-
-typedef struct {
- OperationSpec *os;
- xmlNodePtr node;
- xmlDocPtr doc;
- guint count;
-} ParseEntriesIdle;
-
-typedef struct {
- gchar *id;
- gchar *name;
- gchar *url;
-} CategoryInfo;
-
-typedef struct {
- AsyncReadCbFunc callback;
- gchar *url;
- gpointer user_data;
-} AsyncReadCb;
-
-typedef struct {
- OperationSpec *os;
- CategoryInfo *directory;
- guint index;
- guint remaining;
- gboolean set_childcount;
-} ProduceFromDirectoryIdle;
-
typedef enum {
YOUTUBE_MEDIA_TYPE_ROOT,
YOUTUBE_MEDIA_TYPE_FEEDS,
@@ -186,6 +122,10 @@ typedef enum {
YOUTUBE_MEDIA_TYPE_VIDEO,
} YoutubeMediaType;
+#define YOUTUBE_DEVELOPER_KEY "AI39si4EfscPllSfUy1IwexMf__kntTL_G5dfSr2iUEVN45RHGq92Aq0lX25OlnOkG6KTN-4soVAkAf67fWYXuHfVADZYr7S1A"
+#define YOUTUBE_CLIENT_ID "test-client"
+
+
static GrlYoutubeSource *grl_youtube_source_new (void);
gboolean grl_youtube_plugin_init (GrlPluginRegistry *registry,
@@ -196,47 +136,14 @@ static const GList *grl_youtube_source_supported_keys (GrlMetadataSource *source
static const GList *grl_youtube_source_slow_keys (GrlMetadataSource *source);
-static void grl_youtube_source_metadata (GrlMediaSource *source,
- GrlMediaSourceMetadataSpec *ms);
-
static void grl_youtube_source_search (GrlMediaSource *source,
GrlMediaSourceSearchSpec *ss);
-static void grl_youtube_source_browse (GrlMediaSource *source,
- GrlMediaSourceBrowseSpec *bs);
-
-static void grl_youtube_source_cancel (GrlMediaSource *source,
- guint operation_id);
-
-static gchar *read_url (const gchar *url);
-
-static void build_categories_directory (void);
-
-static void produce_next_video_chunk (OperationSpec *os);
+static void grl_youtube_source_metadata (GrlMediaSource *source,
+ GrlMediaSourceMetadataSpec *ms);
/* ==================== Global Data ================= */
-guint root_dir_size = 2;
-CategoryInfo root_dir[] = {
- {YOUTUBE_FEEDS_ID, YOUTUBE_FEEDS_NAME, YOUTUBE_FEEDS_URL},
- {YOUTUBE_CATEGORIES_ID, YOUTUBE_CATEGORIES_NAME, YOUTUBE_CATEGORIES_URL},
- {NULL, NULL, NULL}
-};
-
-guint feeds_dir_size = 7;
-CategoryInfo feeds_dir[] = {
- {YOUTUBE_VIEWED_ID, YOUTUBE_VIEWED_NAME, YOUTUBE_VIEWED_URL},
- {YOUTUBE_RATED_ID, YOUTUBE_RATED_NAME, YOUTUBE_RATED_URL},
- {YOUTUBE_FAVS_ID, YOUTUBE_FAVS_NAME, YOUTUBE_FAVS_URL},
- {YOUTUBE_RECENT_ID, YOUTUBE_RECENT_NAME, YOUTUBE_RECENT_URL},
- {YOUTUBE_DISCUSSED_ID, YOUTUBE_DISCUSSED_NAME, YOUTUBE_DISCUSSED_URL},
- {YOUTUBE_FEATURED_ID, YOUTUBE_FEATURED_NAME, YOUTUBE_FEATURED_URL},
- {YOUTUBE_MOBILE_ID, YOUTUBE_MOBILE_NAME, YOUTUBE_MOBILE_URL},
- {NULL, NULL, NULL}
-};
-
-guint categories_dir_size = 0;
-CategoryInfo *categories_dir = NULL;
/* =================== Youtube Plugin =============== */
@@ -247,6 +154,11 @@ grl_youtube_plugin_init (GrlPluginRegistry *registry,
{
g_debug ("youtube_plugin_init\n");
+ /* libgdata needs this */
+ if (!g_thread_supported()) {
+ g_thread_init (NULL);
+ }
+
GrlYoutubeSource *source = grl_youtube_source_new ();
grl_plugin_registry_register_source (registry,
plugin,
@@ -270,11 +182,27 @@ static GrlYoutubeSource *
grl_youtube_source_new (void)
{
g_debug ("grl_youtube_source_new");
- return g_object_new (GRL_YOUTUBE_SOURCE_TYPE,
- "source-id", SOURCE_ID,
- "source-name", SOURCE_NAME,
- "source-desc", SOURCE_DESC,
- NULL);
+
+ GrlYoutubeSource *source;
+
+ GDataYouTubeService *service =
+ gdata_youtube_service_new (YOUTUBE_DEVELOPER_KEY, YOUTUBE_CLIENT_ID);
+
+ if (!service) {
+ g_warning ("Failed to connect to Youtube");
+ return NULL;
+ }
+
+ source = GRL_YOUTUBE_SOURCE (g_object_new (GRL_YOUTUBE_SOURCE_TYPE,
+ "source-id", SOURCE_ID,
+ "source-name", SOURCE_NAME,
+ "source-desc", SOURCE_DESC,
+ "auto-split-threshold",
+ YOUTUBE_MAX_CHUNK,
+ NULL));
+ source->service = service;
+
+ return source;
}
static void
@@ -282,9 +210,7 @@ grl_youtube_source_class_init (GrlYoutubeSourceClass * klass)
{
GrlMediaSourceClass *source_class = GRL_MEDIA_SOURCE_CLASS (klass);
GrlMetadataSourceClass *metadata_class = GRL_METADATA_SOURCE_CLASS (klass);
- source_class->browse = grl_youtube_source_browse;
source_class->search = grl_youtube_source_search;
- source_class->cancel = grl_youtube_source_cancel;
source_class->metadata = grl_youtube_source_metadata;
metadata_class->supported_keys = grl_youtube_source_supported_keys;
metadata_class->slow_keys = grl_youtube_source_slow_keys;
@@ -293,9 +219,6 @@ grl_youtube_source_class_init (GrlYoutubeSourceClass * klass)
static void
grl_youtube_source_init (GrlYoutubeSource *source)
{
- if (!categories_dir) {
- build_categories_directory ();
- }
}
G_DEFINE_TYPE (GrlYoutubeSource, grl_youtube_source, GRL_TYPE_MEDIA_SOURCE);
@@ -303,38 +226,34 @@ G_DEFINE_TYPE (GrlYoutubeSource, grl_youtube_source, GRL_TYPE_MEDIA_SOURCE);
/* ======================= Utilities ==================== */
static void
-print_entry (Entry *entry)
+free_operation_spec (OperationSpec *os)
{
- g_print ("Entry Information:\n");
- g_print (" ID: %s (%d)\n", entry->id, entry->restricted);
- g_print (" Title: %s\n", entry->title);
- g_print (" Date: %s\n", entry->published);
- g_print (" Author: %s\n", entry->author);
- g_print (" Duration: %s\n", entry->duration);
- g_print (" Thumbnail: %s\n", entry->thumbnail);
- g_print (" Rating: %s\n", entry->rating);
- g_print (" Description: %s\n", entry->description);
+ if (os->query) {
+ g_object_unref (os->query);
+ }
+ g_free (os);
}
-static void
-free_entry (Entry *entry)
+static gchar *
+read_url (const gchar *url)
{
- g_free (entry->id);
- g_free (entry->title);
- g_free (entry->published);
- g_free (entry->author);
- g_free (entry->duration);
- g_free (entry->thumbnail);
- g_free (entry->description);
- g_free (entry->rating);
- g_free (entry);
-}
+ GVfs *vfs;
+ GFile *uri;
+ GError *vfs_error = NULL;
+ gchar *content = NULL;
-static void
-free_operation_spec (OperationSpec *os)
-{
- g_free (os->query_url);
- g_free (os);
+ vfs = g_vfs_get_default ();
+
+ g_debug ("Opening '%s'", url);
+ uri = g_vfs_get_file_for_uri (vfs, url);
+ g_file_load_contents (uri, NULL, &content, NULL, NULL, &vfs_error);
+ g_object_unref (uri);
+ if (vfs_error) {
+ g_warning ("Failed reading '%s': %s", url, vfs_error->message);
+ return NULL;
+ } else {
+ return content;
+ }
}
static gchar *
@@ -371,81 +290,13 @@ get_video_url (const gchar *id)
return url;
}
-static void
-read_done_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- AsyncReadCb *arc = (AsyncReadCb *) user_data;
- GError *vfs_error = NULL;
- gchar *content = NULL;
-
- g_file_load_contents_finish (G_FILE (source_object),
- res,
- &content,
- NULL,
- NULL,
- &vfs_error);
- g_object_unref (source_object);
- if (vfs_error) {
- g_warning ("Failed to open '%s': %s", arc->url, vfs_error->message);
- } else {
- arc->callback (content, arc->user_data);
- }
- g_free (arc->url);
- g_free (arc);
-}
-
-static void
-read_url_async (const gchar *url,
- AsyncReadCbFunc callback,
- gpointer user_data)
-{
- GVfs *vfs;
- GFile *uri;
- AsyncReadCb *arc;
-
- vfs = g_vfs_get_default ();
-
- g_debug ("Opening async '%s'", url);
-
- arc = g_new0 (AsyncReadCb, 1);
- arc->url = g_strdup (url);
- arc->callback = callback;
- arc->user_data = user_data;
- uri = g_vfs_get_file_for_uri (vfs, url);
- g_file_load_contents_async (uri, NULL, read_done_cb, arc);
-}
-
-static gchar *
-read_url (const gchar *url)
-{
- GVfs *vfs;
- GFile *uri;
- GError *vfs_error = NULL;
- gchar *content = NULL;
-
- vfs = g_vfs_get_default ();
-
- g_debug ("Opening '%s'", url);
- uri = g_vfs_get_file_for_uri (vfs, url);
- g_file_load_contents (uri, NULL, &content, NULL, NULL, &vfs_error);
- g_object_unref (uri);
- if (vfs_error) {
- g_warning ("Failed reading '%s': %s", url, vfs_error->message);
- return NULL;
- } else {
- return content;
- }
-}
-
static GrlMedia *
build_media_from_entry (GrlMedia *content,
- const Entry *entry,
+ GDataEntry *entry,
const GList *keys)
{
+ GDataYouTubeVideo *video;
GrlMedia *media;
- gchar *url;
GList *iter;
if (!content) {
@@ -454,9 +305,11 @@ build_media_from_entry (GrlMedia *content,
media = content;
}
+ video = GDATA_YOUTUBE_VIDEO (entry);
+
/* Make sure we set the media id in any case */
if (!grl_media_get_id (media)) {
- grl_media_set_id (media, entry->id);
+ grl_media_set_id (media, gdata_youtube_video_get_video_id (video));
}
iter = (GList *) keys;
@@ -464,22 +317,35 @@ build_media_from_entry (GrlMedia *content,
GrlKeyID key_id = POINTER_TO_GRLKEYID (iter->data);
switch (key_id) {
case GRL_METADATA_KEY_TITLE:
- grl_media_set_title (media, entry->title);
- break;
- case GRL_METADATA_KEY_AUTHOR:
- grl_media_set_author (media, entry->author);
+ grl_media_set_title (media, gdata_entry_get_title (entry));
break;
case GRL_METADATA_KEY_DESCRIPTION:
- grl_media_set_description (media, entry->description);
+ grl_media_set_description (media, gdata_entry_get_summary (entry));
break;
case GRL_METADATA_KEY_THUMBNAIL:
- grl_media_set_thumbnail (media, entry->thumbnail);
+ {
+ GList *thumb_list;
+ thumb_list = gdata_youtube_video_get_thumbnails (video);
+ if (thumb_list) {
+ GDataMediaThumbnail *thumbnail;
+ thumbnail = GDATA_MEDIA_THUMBNAIL (thumb_list->data);
+ grl_media_set_thumbnail (media,
+ gdata_media_thumbnail_get_uri (thumbnail));
+ }
+ }
break;
case GRL_METADATA_KEY_DATE:
- grl_media_set_date (media, entry->published);
+ {
+ GTimeVal date;
+ gchar *date_str;
+ gdata_entry_get_published (entry, &date);
+ date_str = g_time_val_to_iso8601 (&date);
+ grl_media_set_date (media, date_str);
+ g_free (date_str);
+ }
break;
case GRL_METADATA_KEY_DURATION:
- grl_media_set_duration (media, atoi (entry->duration));
+ grl_media_set_duration (media, gdata_youtube_video_get_duration (video));
break;
case GRL_METADATA_KEY_MIME:
grl_media_set_mime (media, YOUTUBE_VIDEO_MIME);
@@ -488,15 +354,29 @@ build_media_from_entry (GrlMedia *content,
grl_media_set_site (media, YOUTUBE_SITE_URL);
break;
case GRL_METADATA_KEY_RATING:
- grl_media_set_rating (media, entry->rating, "5.00");
+ {
+ gdouble average;
+ gdata_youtube_video_get_rating (video, NULL, NULL, NULL, &average);
+ grl_media_set_rating (media, average, 5.00);
+ }
break;
case GRL_METADATA_KEY_URL:
- if (!entry->restricted) {
- url = get_video_url (entry->id);
+ {
+ gchar *url = get_video_url (gdata_youtube_video_get_video_id (video));
if (url) {
grl_media_set_url (media, url);
+ g_free (url);
+ } else {
+ GDataYouTubeContent *youtube_content;
+ youtube_content =
+ gdata_youtube_video_look_up_content (video,
+ "application/x-shockwave-flash");
+ if (youtube_content != NULL) {
+ GDataMediaContent *content = GDATA_MEDIA_CONTENT (youtube_content);
+ grl_media_set_url (media,
+ gdata_media_content_get_uri (content));
+ }
}
- g_free (url);
}
break;
default:
@@ -508,798 +388,98 @@ build_media_from_entry (GrlMedia *content,
return media;
}
-static gchar *
-parse_id (xmlDocPtr doc, xmlNodePtr id)
-{
- gchar *value, *video_id;
- value = (gchar *) xmlNodeListGetString (doc, id->xmlChildrenNode, 1);
- video_id = g_strdup (g_strrstr (value , "/") + 1);
- g_free (value);
- return video_id;
-}
-
-static gchar *
-parse_author (xmlDocPtr doc, xmlNodePtr author)
-{
- xmlNodePtr node;
- node = author->xmlChildrenNode;
- while (node) {
- if (!xmlStrcmp (node->name, (const xmlChar *) "name")) {
- return (gchar *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
- }
- node = node->next;
- }
- return NULL;
-}
-
-static void
-parse_media_group (xmlDocPtr doc, xmlNodePtr media, Entry *entry)
-{
- xmlNodePtr node;
- xmlNs *ns;
-
- node = media->xmlChildrenNode;
- while (node) {
- ns = node->ns;
- if (!xmlStrcmp (node->name, (const xmlChar *) "description")) {
- entry->description =
- (gchar *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
- } else if (!xmlStrcmp (node->name, (const xmlChar *) "thumbnail") &&
- !entry->thumbnail) {
- entry->thumbnail =
- (gchar *) xmlGetProp (node, (xmlChar *) "url");
- } else if (!xmlStrcmp (node->name, (const xmlChar *) "duration")) {
- entry->duration =
- (gchar *) xmlGetProp (node, (xmlChar *) "seconds");
- }
- node = node->next;
- }
-}
-
-static void
-parse_app_control (xmlDocPtr doc, xmlNodePtr media, Entry *entry)
-{
- xmlNodePtr node;
- xmlChar *value;
-
- node = media->xmlChildrenNode;
- while (node) {
- if (!xmlStrcmp (node->name, (const xmlChar *) "state")) {
- value = xmlGetProp (node, (xmlChar *) "name");
- if (!xmlStrcmp (value, (xmlChar *) "restricted")) {
- entry->restricted = TRUE;
- }
- g_free ((gchar *) value);
- }
- node = node->next;
- }
-}
-
-static void
-parse_entry (xmlDocPtr doc, xmlNodePtr entry, Entry *data)
-{
- xmlNodePtr node;
- xmlNs *ns;
-
- node = entry->xmlChildrenNode;
- while (node) {
- ns = node->ns;
- if (!xmlStrcmp (node->name, (const xmlChar *) "id")) {
- data->id = parse_id (doc, node);
- } else if (!xmlStrcmp (node->name, (const xmlChar *) "published")) {
- data->published =
- (gchar *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
- } else if (!xmlStrcmp (node->name, (const xmlChar *) "title")) {
- data->title =
- (gchar *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
- } else if (!xmlStrcmp (node->name, (const xmlChar *) "author")) {
- data->author = parse_author (doc, node);
- } else if (ns && !xmlStrcmp (ns->prefix, (const xmlChar *) "media") &&
- !xmlStrcmp (node->name, (const xmlChar *) "group")) {
- parse_media_group (doc, node, data);
- } else if (ns && !xmlStrcmp (ns->prefix, (const xmlChar *) "app") &&
- !xmlStrcmp (node->name, (const xmlChar *) "control")) {
- parse_app_control (doc, node, data);
- } else if (ns && !xmlStrcmp (ns->prefix, (const xmlChar *) "gd") &&
- !xmlStrcmp (node->name, (const xmlChar *) "rating")) {
- data->rating = (gchar *) xmlGetProp (node, (xmlChar *) "average");
- }
-
- node = node->next;
- }
-}
-
-static gboolean
-parse_entries_idle (gpointer user_data)
-{
- ParseEntriesIdle *pei = (ParseEntriesIdle *) user_data;
- gboolean parse_more = FALSE;
-
- g_debug ("parse_entries_idle");
-
- /* Do not bother if operation was cancelled */
- if (!pei->os->cancelled) {
- while (pei->node && xmlStrcmp (pei->node->name,
- (const xmlChar *) "entry")) {
- pei->node = pei->node->next;
- }
-
- if (pei->node) {
- Entry *entry = g_new0 (Entry, 1);
- parse_entry (pei->doc, pei->node, entry);
- if (0) print_entry (entry);
- GrlMedia *media =
- build_media_from_entry (NULL, entry, pei->os->keys);
- free_entry (entry);
-
- pei->os->skip++;
- pei->os->count--;
- pei->count++;
- pei->os->callback (pei->os->source,
- pei->os->operation_id,
- media,
- pei->os->count,
- pei->os->user_data,
- NULL);
-
- parse_more = TRUE;
- pei->node = pei->node->next;
- }
- }
-
- if (!parse_more) {
- xmlFreeDoc (pei->doc);
- /* Did we split the query in chunks? if so, query next chunk now */
- if (!pei->os->cancelled && pei->os->count > 0 && pei->count > 0) {
- /* We can go for the next chunk: operation not cancelled,
- still more results were requested and last chunk returned
- valid results */
- produce_next_video_chunk (pei->os);
- } else {
- /* The operation is finished */
- if (pei->os->cancelled && pei->os->count > 0) {
- /* Operation cancelled before finalization. We stop the
- operation now */
- g_debug ("Operation was cancelled, stopping next chunk");
- pei->os->callback (pei->os->source,
- pei->os->operation_id,
- NULL,
- 0,
- pei->os->user_data,
- NULL);
- } else if (pei->count == 0) {
- /* This can only happen in youtube's totalResults is wrong
- (actually greater than it should be). If that's the case
- there are not more results and we must finish the operation now */
- g_warning ("Wrong totalResults from Youtube " \
- "using NULL media to finish operation");
- pei->os->callback (pei->os->source,
- pei->os->operation_id,
- NULL,
- 0,
- pei->os->user_data,
- NULL);
- }
- free_operation_spec (pei->os);
- }
- g_free (pei);
- }
-
- return parse_more;
-}
-
-static void
-parse_feed (OperationSpec *os, const gchar *str, GError **error)
-{
- xmlDocPtr doc;
- xmlNodePtr node;
- guint total_results;
- xmlNs *ns;
-
- doc = xmlRecoverDoc ((xmlChar *) str);
- if (!doc) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_BROWSE_FAILED,
- "Failed to parse Youtube's response");
- goto free_resources;
- }
-
- node = xmlDocGetRootElement (doc);
- if (!node) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_BROWSE_FAILED,
- "Empty response from Youtube");
- goto free_resources;
- }
-
- if (xmlStrcmp (node->name, (const xmlChar *) "feed")) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_BROWSE_FAILED,
- "Unexpected response from Youtube: no feed");
- goto free_resources;
- }
-
- node = node->xmlChildrenNode;
- if (!node) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_BROWSE_FAILED,
- "Unexpected response from Youtube: empty feed");
- goto free_resources;
- }
-
- /* Compute # of items to send only when we execute the
- first chunk of the query (os->chained_chunk == FALSE) */
- if (!os->chained_chunk) {
- os->chained_chunk = TRUE;
- total_results = 0;
- while (node && !total_results) {
- if (!xmlStrcmp (node->name, (const xmlChar *) "entry")) {
- break;
- } else {
- ns = node->ns;
- if (ns && !xmlStrcmp (ns->prefix, (xmlChar *) "openSearch")) {
- if (!xmlStrcmp (node->name, (const xmlChar *) "totalResults")) {
- gchar *total_results_str =
- (gchar *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
- total_results = atoi (total_results_str);
- g_free (total_results_str);
- }
- }
- }
- node = node->next;
- }
-
- if (total_results >= os->skip + os->count) {
- /* Ok, we can send all the elements requested, no problem */
- } else if (total_results > os->skip) {
- /* We cannot send all, there aren't so many: adjust os->count
- so it represents the total available */
- os->count = total_results - os->skip;
- } else {
- /* No results to send */
- os->callback (os->source,
- os->operation_id,
- NULL,
- 0,
- os->user_data,
- NULL);
- goto free_resources;
- }
- }
-
- /* Now go for the entries */
- ParseEntriesIdle *pei = g_new0 (ParseEntriesIdle, 1);
- pei->os = os;
- pei->node = node;
- pei->doc = doc;
- g_idle_add (parse_entries_idle, pei);
- return;
-
- free_resources:
- xmlFreeDoc (doc);
- return;
-}
-
-static GrlMedia *
-parse_metadata_entry (GrlMediaSourceMetadataSpec *os,
- xmlDocPtr doc,
- xmlNodePtr node,
- GError **error)
-{
- xmlNs *ns;
- guint total_results = 0;
- GrlMedia *media = NULL;
-
- /* First checkout search information looking for totalResults */
- while (node && !total_results) {
- if (!xmlStrcmp (node->name, (const xmlChar *) "entry")) {
- break;
- } else {
- ns = node->ns;
- if (ns && !xmlStrcmp (ns->prefix, (xmlChar *) "openSearch")) {
- if (!xmlStrcmp (node->name, (const xmlChar *) "totalResults")) {
- gchar *total_results_str =
- (gchar *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
- total_results = atoi (total_results_str);
- g_free (total_results_str);
- }
- }
- }
- node = node->next;
- }
-
- if (total_results <= 0) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_MEDIA_NOT_FOUND,
- "Could not find requested media");
- return NULL;
- }
-
- while (node && xmlStrcmp (node->name, (const xmlChar *) "entry")) {
- node = node->next;
- }
- if (node) {
- const gchar *target_id = grl_media_get_id (os->media);
- Entry *entry = g_new0 (Entry, 1);
- parse_entry (doc, node, entry);
- if (0) print_entry (entry);
- if (!strcmp (entry->id, target_id)) {
- build_media_from_entry (os->media, entry, os->keys);
- } else {
- /* FIXME: The query using the video id at target text resulted in various
- matches and the one we were looking for was not the first one */
- g_warning ("Metadata query did not match expected target");
- }
- free_entry (entry);
- }
-
- return media;
-}
-
-static void
-parse_metadata_feed (GrlMediaSourceMetadataSpec *os,
- const gchar *str,
- GError **error)
-{
- xmlDocPtr doc;
- xmlNodePtr node;
-
- doc = xmlRecoverDoc ((xmlChar *) str);
- if (!doc) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_METADATA_FAILED,
- "Failed to parse Youtube's response");
- goto free_resources;
- }
-
- node = xmlDocGetRootElement (doc);
- if (!node) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_METADATA_FAILED,
- "Empty response from Youtube");
- goto free_resources;
- }
-
- if (xmlStrcmp (node->name, (const xmlChar *) "feed")) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_METADATA_FAILED,
- "Unexpected response from Youtube: no feed");
- goto free_resources;
- }
-
- node = node->xmlChildrenNode;
- if (!node) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_METADATA_FAILED,
- "Unexpected response from Youtube: empty feed");
- goto free_resources;
- }
-
- parse_metadata_entry (os, doc, node, error);
-
- free_resources:
- xmlFreeDoc (doc);
-}
-
-static void
-parse_categories (xmlDocPtr doc, xmlNodePtr node)
-{
- g_debug ("parse_categories");
-
- guint total = 0;
- GList *all = NULL, *iter;
- CategoryInfo *cat_info;
- gchar *id;
- guint index = 0;
-
- while (node) {
- cat_info = g_new (CategoryInfo, 1);
- id = (gchar *) xmlGetProp (node, (xmlChar *) "term");
- cat_info->id = g_strconcat (YOUTUBE_CATEGORIES_ID, "/", id, NULL);
- cat_info->name = (gchar *) xmlGetProp (node, (xmlChar *) "label");
- cat_info->url = g_strdup_printf (YOUTUBE_CATEGORY_URL,
- id, "%d", "%d");
- all = g_list_prepend (all, cat_info);
- g_free (id);
- node = node->next;
- total++;
- g_debug (" Found category: '%d - %s'", index++, cat_info->name);
- }
-
- if (all) {
- categories_dir_size = total;
- categories_dir = g_new0 (CategoryInfo, total + 1);
- iter = all;
- do {
- cat_info = (CategoryInfo *) iter->data;
- categories_dir[total - 1].id = cat_info->id ;
- categories_dir[total - 1].name = cat_info->name;
- categories_dir[total - 1].url = cat_info->url;
- total--;
- g_free (cat_info);
- iter = g_list_next (iter);
- } while (iter);
- g_list_free (all);
- }
-}
-
static void
-build_categories_directory_read_cb (gchar *xmldata, gpointer user_data)
+process_feed (GDataFeed *feed, OperationSpec *os)
{
- xmlDocPtr doc;
- xmlNodePtr node;
+ GList *entries;
- if (!xmldata) {
- g_critical ("Failed to build category directory (1)");
- return;
- }
-
- doc = xmlRecoverDoc ((xmlChar *) xmldata);
- if (!doc) {
- g_critical ("Failed to build category directory (2)");
- goto free_resources;
- }
-
- node = xmlDocGetRootElement (doc);
- if (!node) {
- g_critical ("Failed to build category directory (3)");
- goto free_resources;
- }
-
- if (xmlStrcmp (node->name, (const xmlChar *) "categories")) {
- g_critical ("Failed to build category directory (4)");
- goto free_resources;
- }
-
- node = node->xmlChildrenNode;
- if (!node) {
- g_critical ("Failed to build category directory (5)");
- goto free_resources;
- }
-
- parse_categories (doc, node);
-
- free_resources:
- xmlFreeDoc (doc);
- return;
-}
-
-static void
-build_categories_directory (void)
-{
- read_url_async (YOUTUBE_CATEGORIES_URL,
- build_categories_directory_read_cb,
- NULL);
-}
-
-static gboolean
-is_category_container (const gchar *container_id)
-{
- return g_str_has_prefix (container_id, YOUTUBE_CATEGORIES_ID "/");
-}
-
-static gboolean
-is_feeds_container (const gchar *container_id)
-{
- return g_str_has_prefix (container_id, YOUTUBE_FEEDS_ID "/");
-}
-
-static const gchar *
-get_container_url (const gchar *container_id)
-{
- g_debug ("get_container_url (%s)", container_id);
-
- guint index;
- CategoryInfo *directory;
-
- if (is_category_container (container_id)) {
- directory = categories_dir;
- } else if (is_feeds_container (container_id)) {
- directory = feeds_dir;
- } else {
- g_warning ("Cannot get URL for container id '%s'", container_id);
- return NULL;
- }
-
- if (directory == NULL) {
- g_critical ("Required directory is not initialized");
- return NULL;
- }
-
- index = 0;
- while (directory[index].id &&
- strcmp (container_id, directory[index].id)) {
- index++;
- }
- if (directory[index].id) {
- return directory[index].url;
- } else {
- return NULL;
- }
-}
-
-static void
-set_category_childcount (GrlMediaBox *content,
- CategoryInfo *dir,
- guint index)
-{
- gint childcount;
- gboolean set_childcount = TRUE;
-
- if (dir == NULL) {
- /* Special case: we want childcount of root category */
- childcount = root_dir_size;
- } else if (!strcmp (dir[index].id, YOUTUBE_FEEDS_ID)) {
- childcount = feeds_dir_size;
- } else if (!strcmp (dir[index].id, YOUTUBE_CATEGORIES_ID)) {
- childcount = categories_dir_size;
- } else {
- const gchar *_url = get_container_url (dir[index].id);
- if (_url) {
- gchar *url = g_strdup_printf (_url, 1, 0);
- gchar *xmldata = read_url (url);
- g_free (url);
- if (!xmldata) {
- g_warning ("Failed to connect to Youtube to get category childcount");
- return;
- }
- gchar *start = strstr (xmldata, YOUTUBE_TOTAL_RESULTS_START) +
- strlen (YOUTUBE_TOTAL_RESULTS_START);
- gchar *end = strstr (start, YOUTUBE_TOTAL_RESULTS_END);
- gchar *childcount_str = g_strndup (start, end - start);
- childcount = strtol (childcount_str, (char **) NULL, 10);
- } else {
- set_childcount = FALSE;
- }
- }
-
- if (set_childcount) {
- grl_media_box_set_childcount (content, childcount);
- }
-}
-
-static GrlMedia *
-produce_container_from_directory (GrlMedia *media,
- CategoryInfo *dir,
- guint index,
- gboolean set_childcount)
-{
- GrlMedia *content;
-
- if (!media) {
- /* Create mode */
- content = grl_media_box_new ();
- } else {
- /* Update mode */
- content = media;
- }
-
- if (!dir) {
- grl_media_set_id (content, NULL);
- grl_media_set_title (content, YOUTUBE_ROOT_NAME);
- } else {
- grl_media_set_id (content, dir[index].id);
- grl_media_set_title (content, dir[index].name);
- }
- grl_media_set_site (content, YOUTUBE_SITE_URL);
- if (set_childcount) {
- set_category_childcount (GRL_MEDIA_BOX (content), dir, index);
- }
-
- return content;
-}
-
-static GrlMedia *
-produce_container_from_directory_by_id (GrlMedia *media,
- CategoryInfo *dir,
- const gchar *id,
- gboolean set_childcount)
-{
- GrlMedia *content;
- guint index = 0;
-
- while (dir[index].id && strcmp (dir[index].id, id)) index++;
- if (dir[index].id) {
- content = produce_container_from_directory (media, dir,
- index, set_childcount);
- } else {
- /* If don't have that entry, return the media as it was
- provided (if media was NULL, we return NULL) */
- content = media;
- }
-
- return content;
-}
-
-static YoutubeMediaType
-classify_media_id (const gchar *media_id)
-{
- if (!media_id) {
- return YOUTUBE_MEDIA_TYPE_ROOT;
- } else if (!strcmp (media_id, YOUTUBE_FEEDS_ID)) {
- return YOUTUBE_MEDIA_TYPE_FEEDS;
- } else if (!strcmp (media_id, YOUTUBE_CATEGORIES_ID)) {
- return YOUTUBE_MEDIA_TYPE_CATEGORIES;
- } else if (is_category_container (media_id)) {
- return YOUTUBE_MEDIA_TYPE_CATEGORY;
- } else if (is_feeds_container (media_id)) {
- return YOUTUBE_MEDIA_TYPE_FEED;
- } else {
- return YOUTUBE_MEDIA_TYPE_VIDEO;
- }
-}
-
-static gboolean
-produce_from_directory_idle (gpointer user_data)
-{
- GrlMedia *content;
- ProduceFromDirectoryIdle *pfdi = (ProduceFromDirectoryIdle *) user_data;
-
- if (!pfdi->os->cancelled) {
- content = produce_container_from_directory (NULL,
- pfdi->directory,
- pfdi->index,
- pfdi->set_childcount);
- pfdi->remaining--;
- pfdi->index++;
- } else {
- content = NULL;
- pfdi->remaining = 0;
- }
-
- pfdi->os->callback (pfdi->os->source,
- pfdi->os->operation_id,
- content,
- pfdi->remaining,
- pfdi->os->user_data,
- NULL);
-
- if (pfdi->remaining == 0) {
- free_operation_spec (pfdi->os);
- g_free (pfdi);
- return FALSE;
+ /* Send results to client */
+ entries = gdata_feed_get_entries (feed);
+ while (entries) {
+ GrlMedia *media =
+ build_media_from_entry (NULL, GDATA_ENTRY (entries->data), os->keys);
+ os->callback (os->source,
+ os->operation_id,
+ media,
+ --(os->count),
+ os->user_data,
+ NULL);
+ entries = g_list_next (entries);
}
- return TRUE;
-}
-
-static void
-produce_from_directory (CategoryInfo *dir, guint dir_size, OperationSpec *os)
-{
- g_debug ("produce_from_directory");
-
- guint index, remaining;
- gboolean set_childcount;
- YoutubeMediaType media_type;
-
- if (os->skip >= dir_size) {
- /* No results */
+ /* Send last result if not yet sent */
+ if (os->count > 0) {
os->callback (os->source,
os->operation_id,
NULL,
0,
os->user_data,
NULL);
- free_operation_spec (os);
- } else {
- /* Do not compute childcount when it is expensive and user requested
- GRL_RESOLVE_FAST_ONLY */
- media_type = classify_media_id (os->container_id);
- if ((os->flags & GRL_RESOLVE_FAST_ONLY) &&
- (media_type == YOUTUBE_MEDIA_TYPE_CATEGORIES ||
- media_type == YOUTUBE_MEDIA_TYPE_FEEDS)) {
- set_childcount = FALSE;
- } else {
- set_childcount =
- (g_list_find (os->keys,
- GRLKEYID_TO_POINTER (GRL_METADATA_KEY_CHILDCOUNT)) != NULL);
- }
- index = os->skip;
- remaining = MIN (dir_size - os->skip, os->count);
-
- /* We use the idle loop because computing the childcount is blocking
- and it may be called for every entry in the directory */
- ProduceFromDirectoryIdle *pfdi = g_new0 (ProduceFromDirectoryIdle, 1);
- pfdi->os = os;
- pfdi->directory = dir;
- pfdi->index = index;
- pfdi->remaining = remaining;
- pfdi->set_childcount = set_childcount;
- g_idle_add (produce_from_directory_idle, pfdi);
}
+
+ free_operation_spec (os);
}
static void
-produce_next_video_chunk_read_cb (gchar *xmldata, gpointer user_data)
+process_metadata (GDataYouTubeVideo *video, GrlMediaSourceMetadataSpec *ms)
{
- GError *error = NULL;
- OperationSpec *os = (OperationSpec *) user_data;
-
- if (!xmldata) {
- error = g_error_new (GRL_ERROR,
- GRL_ERROR_BROWSE_FAILED,
- "Failed to read from Youtube");
- } else {
- parse_feed (os, xmldata, &error);
- g_free (xmldata);
- }
-
- if (error) {
- os->callback (os->source,
- os->operation_id,
- NULL,
- 0,
- os->user_data,
- error);
- g_error_free (error);
- free_operation_spec (os);
- }
+ build_media_from_entry (ms->media, GDATA_ENTRY (video), ms->keys);
+ ms->callback (ms->source, ms->media, ms->user_data, NULL);
}
static void
-produce_next_video_chunk (OperationSpec *os)
+metadata_cb (GObject *object,
+ GAsyncResult *result,
+ GrlMediaSourceMetadataSpec *ms)
{
- gchar *url;
+ g_debug ("metadata_cb");
- g_debug ("produce_next_video_chunk");
+ GError *error = NULL;
+ GrlYoutubeSource *source = GRL_YOUTUBE_SOURCE (ms->source);
- if (os->count > YOUTUBE_MAX_CHUNK) {
- url = g_strdup_printf (os->query_url, os->skip + 1, YOUTUBE_MAX_CHUNK);
+ GDataYouTubeVideo *video =
+ gdata_youtube_service_query_single_video_finish (GDATA_YOUTUBE_SERVICE (source->service),
+ result,
+ &error);
+ if (error) {
+ error->code = GRL_ERROR_METADATA_FAILED;
+ ms->callback (ms->source, ms->media, ms->user_data, error);
+ g_error_free (error);
} else {
- url = g_strdup_printf (os->query_url, os->skip + 1, os->count);
+ process_metadata (video, ms);
}
- read_url_async (url, produce_next_video_chunk_read_cb, os);
- g_free (url);
-}
-static void
-produce_videos_from_container (OperationSpec *os, GError **error)
-{
- const gchar *_url;
-
- _url = get_container_url (os->container_id);
- if (!_url) {
- *error = g_error_new (GRL_ERROR,
- GRL_ERROR_BROWSE_FAILED,
- "Invalid container-id: '%s'",
- os->container_id);
- } else {
- os->query_url = g_strdup (_url);
- produce_next_video_chunk (os);
+ if (video) {
+ g_object_unref (video);
}
}
static void
-produce_videos_from_search (const gchar *text,
- OperationSpec *os,
- GError **error)
+search_cb (GObject *object, GAsyncResult *result, OperationSpec *os)
{
- gchar *url;
- url = g_strdup_printf (YOUTUBE_SEARCH_URL, text, "%d", "%d");
- os->query_url = url;
- produce_next_video_chunk (os);
-}
+ g_debug ("search_cb");
-static void
-metadata_read_cb (gchar *xmldata, gpointer user_data)
-{
+ GDataFeed *feed;
GError *error = NULL;
- GrlMediaSourceMetadataSpec *ms = (GrlMediaSourceMetadataSpec *) user_data;
-
- if (!xmldata) {
- error = g_error_new (GRL_ERROR,
- GRL_ERROR_METADATA_FAILED,
- "Failed to read from Youtube");
- } else {
- parse_metadata_feed (ms, xmldata, &error);
- g_free (xmldata);
- }
-
+ GrlYoutubeSource *source = GRL_YOUTUBE_SOURCE (os->source);
+
+ feed = gdata_service_query_finish (GDATA_SERVICE (source->service),
+ result, &error);
if (error) {
- ms->callback (ms->source, ms->media, ms->user_data, error);
+ error->code = os->error_code;
+ os->callback (os->source, os->operation_id, NULL, 0, os->user_data, error);
g_error_free (error);
+ if (feed) {
+ g_object_unref (feed);
+ }
} else {
- ms->callback (ms->source, ms->media, ms->user_data, NULL);
+ g_debug ("Feed info: %s - %u/%u/%u",
+ gdata_feed_get_title (feed),
+ gdata_feed_get_start_index (feed),
+ gdata_feed_get_items_per_page (feed),
+ gdata_feed_get_total_results (feed));
+
+ process_feed (feed, os);
}
}
@@ -1313,7 +493,6 @@ grl_youtube_source_supported_keys (GrlMetadataSource *source)
keys = grl_metadata_key_list_new (GRL_METADATA_KEY_ID,
GRL_METADATA_KEY_TITLE,
GRL_METADATA_KEY_URL,
- GRL_METADATA_KEY_AUTHOR,
GRL_METADATA_KEY_DESCRIPTION,
GRL_METADATA_KEY_DURATION,
GRL_METADATA_KEY_DATE,
@@ -1342,55 +521,12 @@ grl_youtube_source_slow_keys (GrlMetadataSource *source)
}
static void
-grl_youtube_source_browse (GrlMediaSource *source,
- GrlMediaSourceBrowseSpec *bs)
-{
- OperationSpec *os;
- GError *error = NULL;
- const gchar *container_id;
-
- g_debug ("grl_youtube_source_browse");
-
- container_id = grl_media_get_id (bs->container);
-
- os = g_new0 (OperationSpec, 1);
- os->source = bs->source;
- os->operation_id = bs->browse_id;
- os->container_id = container_id;
- os->keys = bs->keys;
- os->flags = bs->flags;
- os->skip = bs->skip;
- os->count = bs->count;
- os->callback = bs->callback;
- os->user_data = bs->user_data;
-
- grl_media_source_set_operation_data (source, os->operation_id, os);
-
- if (!container_id) {
- produce_from_directory (root_dir, root_dir_size, os);
- } else if (!strcmp (container_id, YOUTUBE_FEEDS_ID)) {
- produce_from_directory (feeds_dir, feeds_dir_size, os);
- } else if (!strcmp (container_id, YOUTUBE_CATEGORIES_ID)) {
- produce_from_directory (categories_dir, categories_dir_size, os);
- } else {
- produce_videos_from_container (os, &error);
- if (error) {
- os->callback (os->source, os->operation_id, NULL,
- 0, os->user_data, error);
- g_error_free (error);
- free_operation_spec (os);
- }
- }
-}
-
-static void
grl_youtube_source_search (GrlMediaSource *source,
GrlMediaSourceSearchSpec *ss)
{
OperationSpec *os;
- GError *error = NULL;
- g_debug ("grl_youtube_source_search");
+ g_debug ("grl_youtube_source_search %u", ss->count);
os = g_new0 (OperationSpec, 1);
os->source = source;
@@ -1400,100 +536,28 @@ grl_youtube_source_search (GrlMediaSource *source,
os->count = ss->count;
os->callback = ss->callback;
os->user_data = ss->user_data;
+ os->error_code = GRL_ERROR_SEARCH_FAILED;
+ os->query = gdata_query_new_with_limits (ss->text, ss->skip, ss->count);
- grl_media_source_set_operation_data (source, os->operation_id, os);
- produce_videos_from_search (ss->text, os, &error);
-
- if (error) {
- error->code = GRL_ERROR_SEARCH_FAILED;
- os->callback (os->source, os->operation_id, NULL, 0, os->user_data, error);
- g_error_free (error);
- g_free (os->query_url);
- g_free (os);
- }
+ gdata_youtube_service_query_videos_async (GRL_YOUTUBE_SOURCE (source)->service,
+ os->query,
+ NULL,
+ NULL,
+ NULL,
+ (GAsyncReadyCallback) search_cb,
+ os);
}
static void
grl_youtube_source_metadata (GrlMediaSource *source,
GrlMediaSourceMetadataSpec *ms)
{
- gchar *url;
- GError *error = NULL;
- GrlMedia *media = NULL;
- YoutubeMediaType media_type;
- gboolean set_childcount;
- const gchar *id;
-
g_debug ("grl_youtube_source_metadata");
-
- id = grl_media_get_id (ms->media);
- media_type = classify_media_id (id);
-
- /* Do not compute childcount for expensive categories
- if user requested that */
- if ((ms->flags & GRL_RESOLVE_FAST_ONLY) &&
- (media_type == YOUTUBE_MEDIA_TYPE_CATEGORIES ||
- media_type == YOUTUBE_MEDIA_TYPE_FEEDS)) {
- set_childcount = FALSE;
- } else {
- set_childcount =
- (g_list_find (ms->keys,
- GRLKEYID_TO_POINTER (GRL_METADATA_KEY_CHILDCOUNT)) != NULL);
- }
-
- switch (media_type) {
- case YOUTUBE_MEDIA_TYPE_ROOT:
- media = produce_container_from_directory (ms->media, NULL,
- 0, set_childcount);
- break;
- case YOUTUBE_MEDIA_TYPE_FEEDS:
- media = produce_container_from_directory (ms->media, root_dir,
- 0, set_childcount);
- break;
- case YOUTUBE_MEDIA_TYPE_CATEGORIES:
- media = produce_container_from_directory (ms->media, root_dir,
- 1, set_childcount);
- break;
- case YOUTUBE_MEDIA_TYPE_FEED:
- media = produce_container_from_directory_by_id (ms->media,
- feeds_dir,
- id,
- set_childcount);
- break;
- case YOUTUBE_MEDIA_TYPE_CATEGORY:
- media = produce_container_from_directory_by_id (ms->media,
- categories_dir,
- id,
- set_childcount);
- break;
- case YOUTUBE_MEDIA_TYPE_VIDEO:
- default:
- {
- /* For metadata retrieval we just search by text using the video ID */
- /* This case is async, we will emit results in the read callback */
- url = g_strdup_printf (YOUTUBE_SEARCH_URL, id, "1", "1");
- read_url_async (url, metadata_read_cb, ms);
- g_free (url);
- }
- break;
- }
-
- if (error) {
- ms->callback (ms->source, ms->media, ms->user_data, error);
- g_error_free (error);
- } else if (media) {
- ms->callback (ms->source, ms->media, ms->user_data, NULL);
- }
-}
-
-static void
-grl_youtube_source_cancel (GrlMediaSource *source, guint operation_id)
-{
- OperationSpec *spec;
- g_debug ("grl_youtube_source_cancel");
- spec = (OperationSpec *) grl_media_source_get_operation_data (source,
- operation_id);
- if (spec) {
- spec->cancelled = TRUE;
- }
+
+ gdata_youtube_service_query_single_video_async (GRL_YOUTUBE_SOURCE (source)->service,
+ NULL,
+ grl_media_get_id (ms->media),
+ NULL,
+ (GAsyncReadyCallback) metadata_cb,
+ ms);
}
diff --git a/src/youtube/grl-youtube.h b/src/youtube/grl-youtube.h
index 5a26ac9..b88d637 100644
--- a/src/youtube/grl-youtube.h
+++ b/src/youtube/grl-youtube.h
@@ -24,6 +24,7 @@
#define _GRL_YOUTUBE_SOURCE_H_
#include <grilo.h>
+#include <gdata/gdata.h>
#define GRL_YOUTUBE_SOURCE_TYPE \
(grl_youtube_source_get_type ())
@@ -56,6 +57,7 @@ typedef struct _GrlYoutubeSource GrlYoutubeSource;
struct _GrlYoutubeSource {
GrlMediaSource parent;
+ GDataYouTubeService *service;
};
typedef struct _GrlYoutubeSourceClass GrlYoutubeSourceClass;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]