[grilo-plugins] plugins: add Blip.TV plugin



commit 17aec072e38e137086c55d705ae181fa39380d29
Author: Lionel Landwerlin <lionel g landwerlin linux intel com>
Date:   Tue Jun 21 01:05:33 2011 +0100

    plugins: add Blip.TV plugin
    
    Currently only support search and browse (last posted videos)
    features. Also paging isn't properly implemented, it needs manage the
    next page tag.
    
    Signed-off-by: Lionel Landwerlin <lionel g landwerlin linux intel com>
    Signed-off-by: Juan A. Suarez Romero <jasuarez igalia com>

 configure.ac                    |   38 +++
 src/media/Makefile.am           |    6 +-
 src/media/bliptv/Makefile.am    |   38 +++
 src/media/bliptv/grl-bliptv.c   |  479 +++++++++++++++++++++++++++++++++++++++
 src/media/bliptv/grl-bliptv.h   |   79 +++++++
 src/media/bliptv/grl-bliptv.xml |   10 +
 6 files changed, 649 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index e0bea7d..e94379a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,6 +123,8 @@ 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)
 
+PKG_CHECK_MODULES(LIBREST, rest-0.7, HAVE_REST=yes, HAVE_REST=no)
+
 AC_CHECK_HEADER([gcrypt.h], HAVE_GCRYPT=yes, HAVE_GCRYPT=no)
 
 PKG_CHECK_MODULES(GTHREAD, gthread-2.0, HAVE_GTHREAD=yes, HAVE_GTHREAD=no)
@@ -699,6 +701,41 @@ AC_SUBST(TRACKER_PLUGIN_ID)
 AC_DEFINE_UNQUOTED([TRACKER_PLUGIN_ID], ["$TRACKER_PLUGIN_ID"], [Tracker plugin ID])
 
 # ----------------------------------------------------------
+# BUILD BLIP.TV PLUGIN
+# ----------------------------------------------------------
+
+AC_ARG_ENABLE(bliptv,
+        AC_HELP_STRING([--enable-bliptv],
+                [enable Blip.tv plugin (default: auto)]),
+        [
+                case "$enableval" in
+                     yes)
+                        if test "x$HAVE_REST" = "xno"; then
+                           AC_MSG_ERROR([librest not found, install it or use --disable-bliptv])
+                        fi
+                        ;;
+                esac
+        ],
+        [
+                if test "x$HAVE_REST" = "xyes"; then
+                   enable_bliptv=yes
+                else
+                   enable_bliptv=no
+                fi
+        ])
+
+AM_CONDITIONAL([BLIPTV_PLUGIN], [test "x$enable_bliptv" = "xyes"])
+GRL_PLUGINS_ALL="$GRL_PLUGINS_ALL blip.tv"
+if test "x$enable_bliptv" = "xyes"
+then
+	GRL_PLUGINS_ENABLED="$GRL_PLUGINS_ENABLED blip.tv"
+fi
+
+BLIPTV_PLUGIN_ID="grl-bliptv"
+AC_SUBST(BLIPTV_PLUGIN_ID)
+AC_DEFINE_UNQUOTED([BLIPTV_PLUGIN_ID], ["$BLIPTV_PLUGIN_ID"], [Blip.tv plugin ID])
+
+# ----------------------------------------------------------
 # BUILD LOCAL METADATA PLUGIN
 # ----------------------------------------------------------
 
@@ -770,6 +807,7 @@ AC_CONFIG_FILES([
   src/media/shoutcast/Makefile
   src/media/flickr/Makefile
   src/media/filesystem/Makefile
+  src/media/bliptv/Makefile
   src/media/Makefile
   src/media/apple-trailers/Makefile
   src/metadata/metadata-store/Makefile
diff --git a/src/media/Makefile.am b/src/media/Makefile.am
index df7df83..7caa50f 100644
--- a/src/media/Makefile.am
+++ b/src/media/Makefile.am
@@ -52,9 +52,13 @@ if TRACKER_PLUGIN
 SUBDIRS += tracker
 endif
 
+if BLIPTV_PLUGIN
+SUBDIRS += bliptv
+endif
+
 DIST_SUBDIRS =									\
 	filesystem jamendo upnp youtube flickr podcasts bookmarks shoutcast	\
-	apple-trailers vimeo tracker
+	apple-trailers vimeo tracker bliptv
 
 MAINTAINERCLEANFILES =	\
         *.in		\
diff --git a/src/media/bliptv/Makefile.am b/src/media/bliptv/Makefile.am
new file mode 100644
index 0000000..66fce37
--- /dev/null
+++ b/src/media/bliptv/Makefile.am
@@ -0,0 +1,38 @@
+#
+# Makefile.am
+#
+# Author: Lionel Landwerlin <lionel g landwerlin linux intel com>
+#
+# Copyright (C) 2011 Intel Corporation.
+
+lib_LTLIBRARIES		 = libgrlbliptv.la
+
+libgrlbliptv_la_CFLAGS =	\
+	$(DEPS_CFLAGS)		\
+	$(LIBXML_CFLAGS)	\
+	$(LIBREST_CFLAGS)
+
+libgrlbliptv_la_LIBADD =	\
+	$(DEPS_LIBS)		\
+	$(LIBXML_LIBS)		\
+	$(LIBREST_LIBS)
+
+libgrlbliptv_la_LDFLAGS = \
+	-module		   \
+	-avoid-version
+
+libgrlbliptv_la_SOURCES = 		\
+	grl-bliptv.c			\
+	grl-bliptv.h
+
+libdir = $(GRL_PLUGINS_DIR)
+bliptvxmldir = $(GRL_PLUGINS_CONF_DIR)
+bliptvxml_DATA	= $(BLIPTV_PLUGIN_ID).xml
+
+EXTRA_DIST = $(bliptvxml_DATA)
+
+MAINTAINERCLEANFILES =	\
+	*.in		\
+	*~
+
+DISTCLEANFILES = $(MAINTAINERCLEANFILES)
diff --git a/src/media/bliptv/grl-bliptv.c b/src/media/bliptv/grl-bliptv.c
new file mode 100644
index 0000000..1828cc1
--- /dev/null
+++ b/src/media/bliptv/grl-bliptv.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * Contact: Iago Toral Quiroga <itoral igalia com>
+ *
+ * Authors: Lionel Landwerlin <lionel g landwerlin linux intel com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <rest/rest-proxy.h>
+
+#include "grl-bliptv.h"
+
+/* --------- Logging  -------- */
+
+#define GRL_LOG_DOMAIN_DEFAULT bliptv_log_domain
+GRL_LOG_DOMAIN_STATIC(bliptv_log_domain);
+
+/* --- Plugin information --- */
+
+#define PLUGIN_ID   BLIPTV_PLUGIN_ID
+
+#define SOURCE_ID   "grl-bliptv"
+#define SOURCE_NAME "Blip.tv"
+#define SOURCE_DESC "A source for browsing and searching Blip.tv videos"
+
+
+G_DEFINE_TYPE (GrlBliptvSource, grl_bliptv_source, GRL_TYPE_MEDIA_SOURCE)
+
+#define BLIPTV_SOURCE_PRIVATE(o)                                        \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o),                                    \
+                                GRL_TYPE_BLIPTV_SOURCE,                 \
+                                GrlBliptvSourcePrivate))
+
+struct _GrlBliptvSourcePrivate
+{
+  guint not_used;
+};
+
+typedef struct
+{
+  GrlMediaSource *source;
+  guint           operation_id;
+  guint           count;
+
+  GrlMediaSourceResultCb callback;
+  gpointer               user_data;
+
+  RestProxy     *proxy;
+  RestProxyCall *call;
+} BliptvOperation;
+
+typedef struct
+{
+  GrlKeyID     grl_key;
+  const gchar *exp;
+} BliptvAssoc;
+
+/**/
+
+static GList *bliptv_mappings = NULL;
+
+static void bliptv_setup_mapping (void);
+
+static GrlBliptvSource *grl_bliptv_source_new (void);
+
+gboolean grl_bliptv_plugin_init (GrlPluginRegistry *registry,
+                                 const GrlPluginInfo *plugin,
+                                 GList *configs);
+
+static const GList *grl_bliptv_source_supported_keys (GrlMetadataSource *source);
+
+static void grl_bliptv_source_browse (GrlMediaSource *source,
+                                      GrlMediaSourceBrowseSpec *bs);
+
+static void grl_bliptv_source_search (GrlMediaSource *source,
+                                      GrlMediaSourceSearchSpec *ss);
+
+static void grl_bliptv_source_cancel (GrlMediaSource *source,
+                                      guint operation_id);
+
+/**/
+
+gboolean
+grl_bliptv_plugin_init (GrlPluginRegistry *registry,
+                        const GrlPluginInfo *plugin,
+                        GList *configs)
+{
+  GRL_LOG_DOMAIN_INIT (bliptv_log_domain, "bliptv");
+
+  bliptv_setup_mapping ();
+
+  GrlBliptvSource *source = grl_bliptv_source_new ();
+  grl_plugin_registry_register_source (registry,
+                                       plugin,
+                                       GRL_MEDIA_PLUGIN (source),
+                                       NULL);
+  return TRUE;
+}
+
+GRL_PLUGIN_REGISTER (grl_bliptv_plugin_init,
+                     NULL,
+                     PLUGIN_ID);
+
+
+/* ================== Blip.tv GObject ================ */
+
+static GrlBliptvSource *
+grl_bliptv_source_new (void)
+{
+  return g_object_new (GRL_TYPE_BLIPTV_SOURCE,
+                       "source-id", SOURCE_ID,
+                       "source-name", SOURCE_NAME,
+                       "source-desc", SOURCE_DESC,
+                       NULL);
+}
+
+static void
+grl_bliptv_source_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (grl_bliptv_source_parent_class)->dispose (object);
+}
+
+static void
+grl_bliptv_source_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (grl_bliptv_source_parent_class)->finalize (object);
+}
+
+static void
+grl_bliptv_source_class_init (GrlBliptvSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GrlMediaSourceClass *source_class = GRL_MEDIA_SOURCE_CLASS (klass);
+  GrlMetadataSourceClass *metadata_class = GRL_METADATA_SOURCE_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GrlBliptvSourcePrivate));
+
+  object_class->dispose = grl_bliptv_source_dispose;
+  object_class->finalize = grl_bliptv_source_finalize;
+
+  source_class->browse = grl_bliptv_source_browse;
+  source_class->search = grl_bliptv_source_search;
+  source_class->cancel = grl_bliptv_source_cancel;
+
+  metadata_class->supported_keys = grl_bliptv_source_supported_keys;
+}
+
+static void
+grl_bliptv_source_init (GrlBliptvSource *self)
+{
+  self->priv = BLIPTV_SOURCE_PRIVATE (self);
+}
+
+/**/
+
+static void
+bliptv_insert_mapping (GrlKeyID grl_key, const gchar *exp)
+{
+  BliptvAssoc *assoc = g_new (BliptvAssoc, 1);
+
+  assoc->grl_key = grl_key;
+  assoc->exp     = exp;
+
+  bliptv_mappings = g_list_append (bliptv_mappings, assoc);
+}
+
+static void
+bliptv_setup_mapping (void)
+{
+  bliptv_insert_mapping (GRL_METADATA_KEY_ID,
+                         "blip:item_id");
+
+  bliptv_insert_mapping (GRL_METADATA_KEY_DATE,
+                         "blip:datestamp");
+
+  bliptv_insert_mapping (GRL_METADATA_KEY_TITLE,
+                         "title");
+
+  bliptv_insert_mapping (GRL_METADATA_KEY_MIME,
+                         "enclosure/@type");
+
+  bliptv_insert_mapping (GRL_METADATA_KEY_URL,
+                         "enclosure/@url");
+
+  bliptv_insert_mapping (GRL_METADATA_KEY_THUMBNAIL,
+                         "media:thumbnail/@url");
+}
+
+static void
+bliptv_operation_free (BliptvOperation *op)
+{
+  if (op->call)
+    g_object_unref (op->call);
+  if (op->proxy)
+    g_object_unref (op->proxy);
+  if (op->source)
+    g_object_unref (op->source);
+  g_slice_free (BliptvOperation, op);
+}
+
+static void
+proxy_call_raw_async_cb (RestProxyCall *call,
+                         const GError  *error,
+                         GObject       *weak_object,
+                         gpointer       data)
+{
+  BliptvOperation    *op = (BliptvOperation *) data;
+  xmlDocPtr           doc = NULL;
+  xmlXPathContextPtr  xpath = NULL;
+  xmlXPathObjectPtr   obj = NULL;
+  gint i, nb_items = 0;
+
+  GRL_DEBUG ("Response id=%u", op->operation_id);
+
+  doc = xmlParseMemory (rest_proxy_call_get_payload (call),
+                        rest_proxy_call_get_payload_length (call));
+
+  g_object_unref (op->call);
+  op->call = NULL;
+
+  if (!doc)
+    goto finalize;
+
+  xpath = xmlXPathNewContext (doc);
+  if (!xpath)
+    goto finalize;
+
+  xmlXPathRegisterNs (xpath,
+                      (xmlChar *) "blip",
+                      (xmlChar *) "http://blip.tv/dtd/blip/1.0";);
+  xmlXPathRegisterNs (xpath,
+                      (xmlChar *) "media",
+                      (xmlChar *) "http://search.yahoo.com/mrss/";);
+
+  obj = xmlXPathEvalExpression ((xmlChar *) "/rss/channel/item", xpath);
+  if (obj)
+    {
+      nb_items = xmlXPathNodeSetGetLength (obj->nodesetval);
+      xmlXPathFreeObject (obj);
+    }
+
+  if (nb_items < op->count)
+    op->count = nb_items;
+
+  for (i = 0; i < nb_items; i++)
+    {
+      GList *mapping = bliptv_mappings;
+      GrlMedia *media = grl_media_video_new ();
+
+      while (mapping)
+        {
+          BliptvAssoc *assoc = (BliptvAssoc *) mapping->data;
+          gchar *str;
+
+          str = g_strdup_printf ("string(/rss/channel/item[%i]/%s)",
+                                 i + 1, assoc->exp);
+
+          obj = xmlXPathEvalExpression ((xmlChar *) str, xpath);
+          g_free (str);
+          if (obj)
+            {
+              if (obj->stringval && obj->stringval[0] != '\0')
+                {
+                  GRL_DEBUG ("\t%s -> %s", str, obj->stringval);
+                  switch (grl_metadata_key_get_type (assoc->grl_key))
+                    {
+                    case G_TYPE_STRING:
+                      grl_data_set_string (GRL_DATA (media),
+                                           assoc->grl_key,
+                                           (gchar *) obj->stringval);
+                      break;
+
+                    case G_TYPE_INT:
+                      grl_data_set_int (GRL_DATA (media),
+                                        assoc->grl_key,
+                                        (gint) atoi ((gchar *) obj->stringval));
+                      break;
+
+                    case G_TYPE_FLOAT:
+                      grl_data_set_float (GRL_DATA (media),
+                                          assoc->grl_key,
+                                          (gfloat) atof ((gchar *) obj->stringval));
+                      break;
+
+                    default:
+                      GRL_DEBUG ("\tUnexpected data type");
+                      break;
+                    }
+                }
+              xmlXPathFreeObject (obj);
+            }
+
+          mapping = mapping->next;
+        }
+
+      op->callback (op->source,
+                    op->operation_id,
+                    media,
+                    --op->count,
+                    op->user_data,
+                    NULL);
+
+      if (op->count == 0)
+        break;
+    }
+
+ finalize:
+  /* Signal the last element if it was not already signaled */
+  if (nb_items == 0) {
+    op->callback (op->source,
+                  op->operation_id,
+                  NULL,
+                  0,
+                  op->user_data,
+                  NULL);
+  }
+
+  if (xpath)
+    xmlXPathFreeContext (xpath);
+  if (doc)
+    xmlFreeDoc (doc);
+
+  bliptv_operation_free (op);
+}
+
+/* ================== API Implementation ================ */
+
+static const GList *
+grl_bliptv_source_supported_keys (GrlMetadataSource *source)
+{
+  static GList *keys = NULL;
+  if (!keys) {
+    keys = grl_metadata_key_list_new (GRL_METADATA_KEY_ID,
+                                      GRL_METADATA_KEY_DATE,
+                                      GRL_METADATA_KEY_TITLE,
+                                      GRL_METADATA_KEY_MIME,
+                                      GRL_METADATA_KEY_URL,
+                                      GRL_METADATA_KEY_THUMBNAIL,
+                                      NULL);
+  }
+  return keys;
+}
+
+static void
+grl_bliptv_source_browse (GrlMediaSource *source,
+                          GrlMediaSourceBrowseSpec *bs)
+{
+  BliptvOperation *op = g_slice_new0 (BliptvOperation);
+  GError *error = NULL;
+  gchar *length;
+
+  op->source       = g_object_ref (source);
+  op->count        = bs->count;
+  op->operation_id = bs->browse_id;
+  op->callback     = bs->callback;
+  op->user_data    = bs->user_data;
+
+  grl_operation_set_data (bs->browse_id, op);
+
+  op->proxy = rest_proxy_new ("http://blip.tv/posts/";, FALSE);
+  op->call = rest_proxy_new_call (op->proxy);
+  rest_proxy_call_add_param (op->call, "skin", "rss");
+  length = g_strdup_printf ("%u", bs->count);
+  rest_proxy_call_add_param (op->call, "pagelen", length);
+  g_free (length);
+
+  GRL_DEBUG ("Starting browse request for id=%u", bs->browse_id);
+
+  if (!rest_proxy_call_async (op->call,
+                              proxy_call_raw_async_cb,
+                              NULL,
+                              op,
+                              &error))
+    {
+      if (error)
+        {
+          GRL_WARNING ("Could not start search request : %s", error->message);
+          g_error_free (error);
+        }
+      bs->callback (source, bs->browse_id, NULL, 0, bs->user_data, NULL);
+      bliptv_operation_free (op);
+    }
+}
+
+static void
+grl_bliptv_source_search (GrlMediaSource *source,
+                          GrlMediaSourceSearchSpec *ss)
+{
+  BliptvOperation *op = g_slice_new0 (BliptvOperation);
+  GError *error = NULL;
+  GError *grl_error;
+  gchar *length;
+
+  op->source       = g_object_ref (source);
+  op->count        = ss->count;
+  op->operation_id = ss->search_id;
+  op->callback     = ss->callback;
+  op->user_data    = ss->user_data;
+
+  grl_operation_set_data (ss->search_id, op);
+
+  op->proxy = rest_proxy_new ("http://blip.tv/posts/";, FALSE);
+  op->call = rest_proxy_new_call (op->proxy);
+  rest_proxy_call_add_param (op->call, "skin", "rss");
+  rest_proxy_call_add_param (op->call, "search", ss->text);
+  length = g_strdup_printf ("%u", ss->count);
+  rest_proxy_call_add_param (op->call, "pagelen", length);
+  g_free (length);
+
+  GRL_DEBUG ("Starting search request for id=%u : '%s'",
+             ss->search_id, ss->text);
+
+  if (!rest_proxy_call_async (op->call,
+                              proxy_call_raw_async_cb,
+                              NULL,
+                              op,
+                              &error))
+    {
+      if (error)
+        {
+          GRL_WARNING ("Could not start search request : %s", error->message);
+          g_error_free (error);
+        }
+      grl_error = g_error_new (GRL_CORE_ERROR,
+                               GRL_CORE_ERROR_SEARCH_FAILED,
+                               "Unable to search '%s'",
+                               ss->text? ss->text: "");
+      ss->callback (source, ss->search_id, NULL, 0, ss->user_data, grl_error);
+      g_error_free (grl_error);
+      bliptv_operation_free (op);
+    }
+}
+
+static void
+grl_bliptv_source_cancel (GrlMediaSource *source, guint operation_id)
+{
+  BliptvOperation *op = grl_operation_get_data (operation_id);
+
+  GRL_WARNING ("Cancelling id=%u", operation_id);
+
+  if (!op)
+    {
+      GRL_WARNING ("\tNo such operation id=%u", operation_id);
+    }
+
+  if (op->call)
+    {
+      if (!rest_proxy_call_cancel (op->call))
+        {
+          GRL_WARNING ("\tCannot cancel rest call id=%u", operation_id);
+        }
+    }
+
+  grl_operation_set_data (operation_id, NULL);
+  bliptv_operation_free (op);
+}
diff --git a/src/media/bliptv/grl-bliptv.h b/src/media/bliptv/grl-bliptv.h
new file mode 100644
index 0000000..44b8c77
--- /dev/null
+++ b/src/media/bliptv/grl-bliptv.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * Contact: Iago Toral Quiroga <itoral igalia com>
+ *
+ * Authors: Lionel Landwerlin <lionel g landwerlin linux intel com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef _GRL_BLIPTV_H
+#define _GRL_BLIPTV_H
+
+#include <glib-object.h>
+#include <grilo.h>
+
+G_BEGIN_DECLS
+
+#define GRL_TYPE_BLIPTV_SOURCE grl_bliptv_source_get_type()
+
+#define GRL_BLIPTV_SOURCE(obj)                                  \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj),                           \
+                               GRL_TYPE_BLIPTV_SOURCE,          \
+                               GrlBliptvSource))
+
+#define GRL_BLIPTV_SOURCE_CLASS(klass)                          \
+  (G_TYPE_CHECK_CLASS_CAST ((klass),                            \
+                            GRL_TYPE_BLIPTV_SOURCE,             \
+                            GrlBliptvSourceClass))
+
+#define GRL_IS_BLIPTV_SOURCE(obj)                       \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj),                   \
+                               GRL_TYPE_BLIPTV_SOURCE))
+
+#define GRL_IS_BLIPTV_SOURCE_CLASS(klass)              \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass),                   \
+                            GRL_TYPE_BLIPTV_SOURCE))
+
+#define GRL_BLIPTV_SOURCE_GET_CLASS(obj)                        \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj),                            \
+                              GRL_TYPE_BLIPTV_SOURCE,           \
+                              GrlBliptvSourceClass))
+
+typedef struct _GrlBliptvSource        GrlBliptvSource;
+typedef struct _GrlBliptvSourceClass   GrlBliptvSourceClass;
+typedef struct _GrlBliptvSourcePrivate GrlBliptvSourcePrivate;
+
+struct _GrlBliptvSource
+{
+  GrlMediaSource parent;
+
+  /*< private >*/
+  GrlBliptvSourcePrivate *priv;
+};
+
+struct _GrlBliptvSourceClass
+{
+  GrlMediaSourceClass parent_class;
+};
+
+GType grl_bliptv_source_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* _GRL_BLIPTV_H */
diff --git a/src/media/bliptv/grl-bliptv.xml b/src/media/bliptv/grl-bliptv.xml
new file mode 100644
index 0000000..0df744c
--- /dev/null
+++ b/src/media/bliptv/grl-bliptv.xml
@@ -0,0 +1,10 @@
+<plugin>
+  <info>
+    <name>Blip.tv</name>
+    <module>libgrlbliptv</module>
+    <description>A plugin for searching multimedia content using Blip.tv</description>
+    <author>Lionel Landwerlin</author>
+    <license>LGPL</license>
+    <site>http://live.gnome.org/Grilo</site>
+  </info>
+</plugin>



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