[grilo-plugins/0.1.x] youtube: add quvi support



commit a318cda52eee7b27f4b6cbd79928f2eb2436297b
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date:   Tue Jun 21 15:09:49 2011 +0000

    youtube: add quvi support
    
    Signed-off-by: Juan A. Suarez Romero <jasuarez igalia com>

 configure.ac                    |    7 ++-
 src/media/youtube/Makefile.am   |    8 +-
 src/media/youtube/grl-youtube.c |  172 ++++++++++-----------------------------
 3 files changed, 56 insertions(+), 131 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a703acd..96feb3c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -119,6 +119,8 @@ PKG_CHECK_MODULES(SQLITE, sqlite3, HAVE_SQLITE=yes, HAVE_SQLITE=no)
 
 PKG_CHECK_MODULES(GDATA, libgdata >= 0.4.0, HAVE_GDATA=yes, HAVE_GDATA=no)
 
+PKG_CHECK_MODULES(QUVI, libquvi >= 0.2.15, HAVE_QUVI=yes, HAVE_QUVI=no)
+
 PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4, HAVE_LIBSOUP=yes, HAVE_LIBSOUP=no)
 
 AC_CHECK_HEADER([gcrypt.h], HAVE_GCRYPT=yes, HAVE_GCRYPT=no)
@@ -334,11 +336,14 @@ AC_ARG_ENABLE(youtube,
                         if test "x$HAVE_GDATA" = "xno"; then
                            AC_MSG_ERROR([libgdata not found, install it or use --disable-youtube])
                         fi
+                        if test "x$HAVE_QUVI" = "xno"; then
+                           AC_MSG_ERROR([libquvi not found, install it or use --disable-youtube])
+                        fi
                         ;;
                 esac
         ],
         [
-                if test "x$HAVE_GRLNET" = "xyes" -a "x$HAVE_XML" = "xyes" -a "x$HAVE_GDATA" = "xyes"; then
+                if test "x$HAVE_GRLNET" = "xyes" -a "x$HAVE_XML" = "xyes" -a "x$HAVE_GDATA" = "xyes" -a "x$HAVE_QUVI" = "xyes"; then
                    enable_youtube=yes
                 else
                    enable_youtube=no
diff --git a/src/media/youtube/Makefile.am b/src/media/youtube/Makefile.am
index 2384bb8..b173530 100644
--- a/src/media/youtube/Makefile.am
+++ b/src/media/youtube/Makefile.am
@@ -12,14 +12,16 @@ libgrlyoutube_la_CFLAGS =	\
 	$(GRLNET_CFLAGS)	\
 	$(XML_CFLAGS) 		\
 	$(GTHREAD_CFLAGS)	\
-	$(GDATA_CFLAGS)
+	$(GDATA_CFLAGS)	\
+	$(QUVI_CFLAGS)
 
 libgrlyoutube_la_LIBADD =	\
 	$(DEPS_LIBS)		\
 	$(GRLNET_LIBS)		\
 	$(XML_LIBS) 		\
-	$(GTHREAD_LIBS)		\
-	$(GDATA_LIBS)
+	$(GTHREAD_LIBS)	\
+	$(GDATA_LIBS)		\
+	$(QUVI_LIBS)
 
 libgrlyoutube_la_LDFLAGS = \
 	-module		   \
diff --git a/src/media/youtube/grl-youtube.c b/src/media/youtube/grl-youtube.c
index e125980..021bd9c 100644
--- a/src/media/youtube/grl-youtube.c
+++ b/src/media/youtube/grl-youtube.c
@@ -28,6 +28,7 @@
 #include <grilo.h>
 #include <net/grl-net.h>
 #include <gdata/gdata.h>
+#include <quvi/quvi.h>
 #include <string.h>
 
 #include "grl-youtube.h"
@@ -168,6 +169,7 @@ typedef enum {
 
 struct _GrlYoutubeSourcePriv {
   GDataService *service;
+  quvi_t quvi_handle;
 
   GrlNetWc *wc;
 };
@@ -321,6 +323,14 @@ grl_youtube_source_new (const gchar *api_key, const gchar *client_id)
                                              "yt-service", service,
 					     NULL));
 
+  /* Set up quvi */
+  if (quvi_init (&(source->priv->quvi_handle)) != QUVI_OK) {
+    source->priv->quvi_handle = NULL;
+  } else {
+    quvi_setopt (source->priv->quvi_handle, QUVIOPT_FORMAT, "mp4_360p");
+    quvi_setopt (source->priv->quvi_handle, QUVIOPT_NOVERIFY);
+  }
+
   ytsrc = source;
 
   return source;
@@ -394,6 +404,9 @@ grl_youtube_source_finalize (GObject *object)
   if (self->priv->service)
     g_object_unref (self->priv->service);
 
+  if (self->priv->quvi_handle)
+    quvi_close (&(self->priv->quvi_handle));
+
   G_OBJECT_CLASS (grl_youtube_source_parent_class)->finalize (object);
 }
 
@@ -498,126 +511,21 @@ read_url_async (const gchar *url,
 }
 
 static void
-set_media_url_async_read_cb (gchar *data, gpointer user_data)
-{
-  SetMediaUrlAsyncReadCb *cb_data = (SetMediaUrlAsyncReadCb *) user_data;
-  gchar *url = NULL;
-  GMatchInfo *match_info = NULL;
-  static GRegex *regex = NULL;
-
-  if (!data) {
-    goto done;
-  }
-
-  if (regex == NULL) {
-    regex = g_regex_new (".*&fmt_url_map=([^&]+)&", G_REGEX_OPTIMIZE, 0, NULL);
-  }
-
-  /* Check if we find the url mapping */
-  g_regex_match (regex, data, 0, &match_info);
-  if (g_match_info_matches (match_info) == TRUE) {
-    gchar *url_map_escaped, *url_map;
-    gchar **mappings;
-
-    url_map_escaped = g_match_info_fetch (match_info, 1);
-    url_map = g_uri_unescape_string (url_map_escaped, NULL);
-    g_free (url_map_escaped);
-
-    mappings = g_strsplit (url_map, ",", 0);
-    g_free (url_map);
-
-    if (mappings != NULL) {
-      /* TODO: We get the URL from the first format available.
-       * We should provide the list of available urls or let the user
-       * configure preferred formats
-       */
-      gchar **mapping = g_strsplit (mappings[0], "|", 2);
-      url = g_strdup (mapping[1]);
-      g_strfreev (mapping);
-    }
-  } else {
-    GRL_DEBUG ("Format array not found, using token workaround");
-    gchar *token_start;
-    gchar *token_end;
-    gchar *token;
-    const gchar *video_id;
-
-    token_start = g_strrstr (data, "&token=");
-    if (!token_start) {
-      goto done;
-    }
-    token_start += 7;
-    token_end = strstr (token_start, "&");
-    token = g_strndup (token_start, token_end - token_start);
-
-    video_id = grl_media_get_id (cb_data->media);
-    url = g_strdup_printf (YOUTUBE_VIDEO_URL, video_id, token);
-    g_free (token);
-  }
-
- done:
-  if (url) {
-    grl_media_set_url (cb_data->media, url);
-    g_free (url);
-  }
-
-  cb_data->callback (cb_data->media, cb_data->user_data);
-
-  g_free (cb_data);
-}
-
-static void
-set_media_url (GrlMedia *media,
-               GCancellable *cancellable,
-	       BuildMediaFromEntryCbFunc callback,
-	       gpointer user_data)
-{
-  const gchar *video_id;
-  gchar *video_info_url;
-  SetMediaUrlAsyncReadCb *set_media_url_async_read_data;
-
-  /* The procedure to get the video url is:
-   * 1) Read the video info URL using the video id (async operation)
-   * 2) In the video info page, there should be an array of supported formats
-   *    and their corresponding URLs, right now we just use the first one we get.
-   *    (see set_media_url_async_read_cb).
-   *    TODO: we should be able to provide various urls or at least
-   *          select preferred formats via configuration
-   *    TODO: we should set mime-type accordingly to the format selected
-   * 3) As a workaround in case no format array is found we get the video token
-   *    and figure out the url of the video using the video id and the token.
-   */
-
-  video_id = grl_media_get_id (media);
-  video_info_url = g_strdup_printf (YOUTUBE_VIDEO_INFO_URL, video_id);
-
-  set_media_url_async_read_data = g_new0 (SetMediaUrlAsyncReadCb, 1);
-  set_media_url_async_read_data->media = media;
-  set_media_url_async_read_data->cancellable = cancellable;
-  set_media_url_async_read_data->callback = callback;
-  set_media_url_async_read_data->user_data = user_data;
-
-  read_url_async (video_info_url,
-                  cancellable,
-		  set_media_url_async_read_cb,
-		  set_media_url_async_read_data);
-
-  g_free (video_info_url);
-}
-
-static void
-build_media_from_entry (GrlMedia *content,
-			GDataEntry *entry,
+build_media_from_entry (GrlYoutubeSource *source,
+                        GrlMedia *content,
+                        GDataEntry *entry,
                         GCancellable *cancellable,
-			const GList *keys,
-			BuildMediaFromEntryCbFunc callback,
-			gpointer user_data)
+                        const GList *keys,
+                        BuildMediaFromEntryCbFunc callback,
+                        gpointer user_data)
 {
   GDataYouTubeVideo *video;
   GDataMediaThumbnail *thumbnail;
   GrlMedia *media;
   GList *iter;
-  gboolean need_url = FALSE;
+  quvi_media_t v;
+  QUVIcode rc;
+  gchar *url;
 
   if (!content) {
     media = grl_media_video_new ();
@@ -676,9 +584,17 @@ build_media_from_entry (GrlMedia *content,
       gdouble average;
       gdata_youtube_video_get_rating (video, NULL, NULL, NULL, &average);
       grl_media_set_rating (media, average, 5.00);
-    } else if (iter->data == GRL_METADATA_KEY_URL) {
-      /* This needs another query and will be resolved asynchronously p Q*/
-      need_url = TRUE;
+    } else if (iter->data == GRL_METADATA_KEY_URL && source->priv->quvi_handle) {
+      rc = quvi_parse (source->priv->quvi_handle,
+                       (char *) gdata_youtube_video_get_player_uri (video),
+                       &v);
+      if (rc == QUVI_OK) {
+        rc = quvi_getprop (v, QUVIPROP_MEDIAURL, &url);
+        if (rc == QUVI_OK) {
+          grl_media_set_url (media, url);
+        }
+        quvi_parse_close (&v);
+      }
     } else if (iter->data == GRL_METADATA_KEY_EXTERNAL_PLAYER) {
       GDataYouTubeContent *youtube_content;
       youtube_content =
@@ -693,12 +609,7 @@ build_media_from_entry (GrlMedia *content,
     iter = g_list_next (iter);
   }
 
-  if (need_url) {
-    /* URL resolution is async */
-    set_media_url (media, cancellable, callback, user_data);
-  } else {
-    callback (media, user_data);
-  }
+  callback (media, user_data);
 }
 
 static void
@@ -914,7 +825,8 @@ metadata_cb (GObject *object,
     ms->callback (ms->source, ms->metadata_id, ms->media, ms->user_data, error);
     g_error_free (error);
   } else {
-    build_media_from_entry (ms->media,
+    build_media_from_entry (GRL_YOUTUBE_SOURCE (ms->source),
+                            ms->media,
                             video,
                             grl_metadata_source_get_operation_data (GRL_METADATA_SOURCE (ms->source),
                                                                     ms->metadata_id),
@@ -949,8 +861,13 @@ search_progress_cb (GDataEntry *entry,
      * we have to check if we got as many results as we requested or
      * not, and handle that situation properly */
     os->matches++;
-    build_media_from_entry (NULL, entry, os->cancellable, os->keys,
-			    build_media_from_entry_search_cb, os);
+    build_media_from_entry (GRL_YOUTUBE_SOURCE (os->source),
+                            NULL,
+                            entry,
+                            os->cancellable,
+                            os->keys,
+                            build_media_from_entry_search_cb,
+                            os);
   } else {
     GRL_WARNING ("Invalid index/count received grom libgdata, ignoring result");
   }
@@ -1336,7 +1253,8 @@ media_from_uri_cb (GObject *object, GAsyncResult *result, gpointer user_data)
     mfus->callback (mfus->source, mfus->media_from_uri_id, NULL, mfus->user_data, error);
     g_error_free (error);
   } else {
-    build_media_from_entry (NULL,
+    build_media_from_entry (GRL_YOUTUBE_SOURCE (mfus->source),
+                            NULL,
                             video,
                             grl_metadata_source_get_operation_data (GRL_METADATA_SOURCE (mfus->source),
                                                                     mfus->media_from_uri_id),



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