[grilo-plugins] freebox: Add new Freebox TV source
- From: Juan A. Suarez Romero <jasuarez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grilo-plugins] freebox: Add new Freebox TV source
- Date: Sun, 9 Feb 2014 22:06:27 +0000 (UTC)
commit 7a8287c37c3da7480a4ed25fa3313900f663bdd2
Author: Bastien Nocera <hadess hadess net>
Date: Fri Dec 13 23:30:12 2013 +0100
freebox: Add new Freebox TV source
This source will show a list of TV channels available through
the Freebox server, offered by the Free ISP in France.
https://bugzilla.gnome.org/show_bug.cgi?id=720436
configure.ac | 53 ++++++
src/Makefile.am | 6 +-
src/freebox/Makefile.am | 52 ++++++
src/freebox/free.png | Bin 0 -> 11860 bytes
src/freebox/freebox-monitor.c | 162 ++++++++++++++++++
src/freebox/freebox-monitor.h | 68 ++++++++
src/freebox/freebox.gresource.xml | 6 +
src/freebox/grl-freebox.c | 330 +++++++++++++++++++++++++++++++++++++
src/freebox/grl-freebox.h | 76 +++++++++
src/freebox/grl-freebox.xml | 10 +
10 files changed, 762 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d77fdc3..6fd44c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,6 +39,9 @@ AM_PROG_CC_C_O
AC_HEADER_STDC
+m4_define([glib_required_version], [2.32.0])
+AM_PATH_GLIB_2_0(glib_required_version)
+
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# ----------------------------------------------------------
@@ -112,6 +115,9 @@ AC_DEFINE_UNQUOTED(GRL_PLUGINS_DIR, "$GRL_PLUGINS_DIR", [Plugins directory])
PKG_CHECK_MODULES([GRLNET], [${GRLNET_NAME} >= 0.2.2],
HAVE_GRLNET=yes,
HAVE_GRLNET=no)
+PKG_CHECK_MODULES([GRLPLS], [${GRLPLS_NAME} >= 0.2.0],
+ HAVE_GRLPLS=yes,
+ HAVE_GRLPLS=no)
PKG_CHECK_MODULES([GRLPLS], [${GRLPLS_NAME} >= 0.2.0],
HAVE_GRLPLS=yes,
@@ -150,6 +156,9 @@ PKG_CHECK_MODULES(GMIME, gmime-2.6,
[PKG_CHECK_MODULES(GMIME, gmime-2.4,
HAVE_GMIME=yes,
HAVE_GMIME=no)])
+
+PKG_CHECK_MODULES(AVAHI, avahi-gobject, HAVE_AVAHI=yes, HAVE_AVAHI=no)
+
# Search available Tracker version
trackerpkg="tracker-sparql-0.10"
m4_foreach([VERSION], [[0.10], [0.11], [0.12], [0.14], [0.15], [0.16], [0.17], [0.18]],
@@ -1126,6 +1135,49 @@ DEPS_TMDB_LIBS="$DEPS_LIBS $LIBSOUP_LIBS $GRLNET_LIBS $JSON_LIBS"
AC_SUBST(DEPS_TMDB_LIBS)
# ----------------------------------------------------------
+# BUILD FREEBOX PLUGIN
+# ----------------------------------------------------------
+
+AC_ARG_ENABLE(freebox,
+ AC_HELP_STRING([--enable-freebox],
+ [enable Freebox plugin (default: auto)]),
+ [
+ case "$enableval" in
+ yes)
+ if test "x$HAVE_GRLPLS" = "xno"; then
+ AC_MSG_ERROR([grilo-pls-0.2 >= 0.2.0 not found, install it or use
--disable-freebox])
+ fi
+ if test "x$HAVE_AVAHI" = "xno"; then
+ AC_MSG_ERROR([avahi not found, install it or use --disable-freebox])
+ fi
+ ;;
+ esac
+ ],
+ [
+ if test "x$HAVE_GRLPLS" = "xyes" -a "x$HAVE_AVAHI" = "xyes"; then
+ enable_freebox=yes
+ else
+ enable_freebox=no
+ fi
+ ])
+
+AM_CONDITIONAL([FREEBOX_PLUGIN], [test "x$enable_freebox" = "xyes"])
+GRL_PLUGINS_ALL="$GRL_PLUGINS_ALL freebox"
+if test "x$enable_freebox" = "xyes"
+then
+ GRL_PLUGINS_ENABLED="$GRL_PLUGINS_ENABLED freebox"
+fi
+
+FREEBOX_PLUGIN_ID="grl-freebox"
+AC_SUBST(FREEBOX_PLUGIN_ID)
+AC_DEFINE_UNQUOTED([FREEBOX_PLUGIN_ID], ["$FREEBOX_PLUGIN_ID"], [Freebox plugin ID])
+
+DEPS_FREEBOX_CFLAGS="$DEPS_CFLAGS $GRLPLS_CFLAGS $AVAHI_CFLAGS"
+AC_SUBST(DEPS_FREEBOX_CFLAGS)
+DEPS_FREEBOX_LIBS="$DEPS_LIBS $GRLPLS_LIBS $AVAHI_LIBS"
+AC_SUBST(DEPS_FREEBOX_LIBS)
+
+# ----------------------------------------------------------
# GETTEXT/INTLTOOL
# ----------------------------------------------------------
@@ -1166,6 +1218,7 @@ AC_CONFIG_FILES([
src/dmap/Makefile
src/filesystem/Makefile
src/flickr/Makefile
+ src/freebox/Makefile
src/gravatar/Makefile
src/jamendo/Makefile
src/lastfm-albumart/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 83bbca9..d4d763a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -94,8 +94,12 @@ if YOUTUBE_PLUGIN
SUBDIRS += youtube
endif
+if FREEBOX_PLUGIN
+SUBDIRS += freebox
+endif
+
DIST_SUBDIRS = \
- apple-trailers bliptv bookmarks dmap filesystem flickr gravatar jamendo \
+ apple-trailers bliptv bookmarks dmap filesystem flickr freebox gravatar jamendo \
lastfm-albumart local-metadata magnatune metadata-store optical-media \
podcasts raitv shoutcast tmdb tracker upnp vimeo youtube
diff --git a/src/freebox/Makefile.am b/src/freebox/Makefile.am
new file mode 100644
index 0000000..b91f4c8
--- /dev/null
+++ b/src/freebox/Makefile.am
@@ -0,0 +1,52 @@
+#
+# Makefile.am
+#
+# Author: Bastien Nocera <hadess hadess net>
+#
+# Copyright (C) 2013 Bastien Nocera
+
+include $(top_srcdir)/gtester.mk
+
+ext_LTLIBRARIES = libgrlfreebox.la
+
+libgrlfreebox_la_CFLAGS = \
+ $(DEPS_FREEBOX_CFLAGS) \
+ -DG_LOG_DOMAIN=\"GrlFreebox\" \
+ -DLOCALEDIR=\"$(localedir)\"
+
+libgrlfreebox_la_LIBADD = \
+ $(DEPS_FREEBOX_LIBS)
+
+libgrlfreebox_la_LDFLAGS = \
+ -no-undefined \
+ -module \
+ -avoid-version
+
+libgrlfreebox_la_SOURCES = \
+ grl-freebox.c \
+ grl-freebox.h \
+ freebox-monitor.h \
+ freebox-monitor.c \
+ freeboxresources.h \
+ freeboxresources.c
+
+freeboxresources.h: freebox.gresource.xml
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $(srcdir)/freebox.gresource.xml \
+ --target=$@ --sourcedir=$(srcdir) --c-name _grl_freebox --generate-header
+freeboxresources.c: freebox.gresource.xml freeboxresources.h free.png
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $(srcdir)/freebox.gresource.xml \
+ --target=$@ --sourcedir=$(srcdir) --c-name _grl_freebox --generate-source
+
+extdir = $(GRL_PLUGINS_DIR)
+freeboxxmldir = $(GRL_PLUGINS_DIR)
+freeboxxml_DATA = $(FREEBOX_PLUGIN_ID).xml
+
+EXTRA_DIST = $(freeboxxml_DATA) free.png freebox.gresource.xml
+
+MAINTAINERCLEANFILES = \
+ *.in \
+ *~
+
+CLEANFILES = freeboxresources.h freeboxresources.c
+
+DISTCLEANFILES = $(MAINTAINERCLEANFILES)
diff --git a/src/freebox/free.png b/src/freebox/free.png
new file mode 100644
index 0000000..b8de787
Binary files /dev/null and b/src/freebox/free.png differ
diff --git a/src/freebox/freebox-monitor.c b/src/freebox/freebox-monitor.c
new file mode 100644
index 0000000..a436bf4
--- /dev/null
+++ b/src/freebox/freebox-monitor.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2011 Intel Corp
+ * Copyright (C) 2013 Bastien Nocera <hadess hadess net>
+ *
+ * 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; either version 2 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 package; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <avahi-client/client.h>
+#include <avahi-client/lookup.h>
+#include <avahi-glib/glib-watch.h>
+#include <avahi-common/simple-watch.h>
+
+#include "freebox-monitor.h"
+
+struct _FreeboxMonitorPrivate {
+ /* Avahi <-> GLib adaptors */
+ AvahiGLibPoll *poll;
+ /* Avahi client */
+ AvahiClient *client;
+ /* Service browser */
+ AvahiServiceBrowser *browser;
+};
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), FREEBOX_TYPE_MONITOR, FreeboxMonitorPrivate))
+
+G_DEFINE_TYPE (FreeboxMonitor, freebox_monitor, G_TYPE_OBJECT);
+
+enum {
+ FOUND,
+ LOST,
+ NUM_SIGS
+};
+
+static guint signals[NUM_SIGS] = {0,};
+
+static void
+on_browse_callback (AvahiServiceBrowser *b,
+ AvahiIfIndex interface, AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void* userdata)
+{
+ FreeboxMonitor *self = FREEBOX_MONITOR (userdata);
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+ /* Emit the found signal */
+ g_signal_emit (self, signals[FOUND], 0, name);
+ break;
+ case AVAHI_BROWSER_REMOVE:
+ /* Emit the lost signal */
+ g_signal_emit (self, signals[LOST], 0, name);
+ break;
+ default:
+ /* Nothing */
+ ;
+ }
+}
+
+static void
+on_client_state_changed (AvahiClient *client, AvahiClientState state, void *user_data)
+{
+ FreeboxMonitor *self = FREEBOX_MONITOR (user_data);
+ FreeboxMonitorPrivate *priv = self->priv;
+
+ switch (state) {
+ case AVAHI_CLIENT_S_RUNNING:
+ {
+ priv->browser = avahi_service_browser_new (client,
+ AVAHI_IF_UNSPEC,
+ AVAHI_PROTO_UNSPEC,
+ "_fbx-api._tcp",
+ NULL, 0,
+ on_browse_callback, self);
+ }
+ break;
+ case AVAHI_CLIENT_S_REGISTERING:
+ case AVAHI_CLIENT_CONNECTING:
+ /* Silently do nothing */
+ break;
+ case AVAHI_CLIENT_S_COLLISION:
+ case AVAHI_CLIENT_FAILURE:
+ default:
+ g_warning ("Cannot connect to Avahi: state %d", state);
+ break;
+ }
+}
+
+static void
+freebox_monitor_finalize (GObject *object)
+{
+ FreeboxMonitorPrivate *priv = FREEBOX_MONITOR(object)->priv;
+
+ g_clear_pointer (&priv->browser, avahi_service_browser_free);
+ g_clear_pointer (&priv->client, avahi_client_free);
+ g_clear_pointer (&priv->poll, avahi_simple_poll_free);
+}
+
+static void
+freebox_monitor_class_init (FreeboxMonitorClass *klass)
+{
+ GObjectClass *o_class = (GObjectClass *)klass;
+
+ g_type_class_add_private (klass, sizeof (FreeboxMonitorPrivate));
+
+ o_class->finalize = freebox_monitor_finalize;
+
+ signals[FOUND] = g_signal_new ("found",
+ FREEBOX_TYPE_MONITOR,
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ signals[LOST] = g_signal_new ("lost",
+ FREEBOX_TYPE_MONITOR,
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+}
+
+static void
+freebox_monitor_init (FreeboxMonitor *self)
+{
+ FreeboxMonitorPrivate *priv;
+ int error;
+
+ priv = self->priv = GET_PRIVATE (self);
+
+ priv->poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
+ priv->client = avahi_client_new (avahi_glib_poll_get (priv->poll),
+ AVAHI_CLIENT_NO_FAIL,
+ on_client_state_changed,
+ self,
+ &error);
+}
+
+FreeboxMonitor *
+freebox_monitor_new (void)
+{
+ return g_object_new (FREEBOX_TYPE_MONITOR, NULL);
+}
diff --git a/src/freebox/freebox-monitor.h b/src/freebox/freebox-monitor.h
new file mode 100644
index 0000000..e2bb861
--- /dev/null
+++ b/src/freebox/freebox-monitor.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 Intel Corp
+ * Copyright (C) 2013 Bastien Nocera <hadess hadess net>
+ *
+ * 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; either version 2 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 package; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __FREEBOX_MONITOR_H__
+#define __FREEBOX_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define FREEBOX_TYPE_MONITOR (freebox_monitor_get_type())
+#define FREEBOX_MONITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ FREEBOX_TYPE_MONITOR, \
+ FreeboxMonitor))
+#define FREEBOX_MONITOR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ FREEBOX_TYPE_MONITOR, \
+ FreeboxMonitorClass))
+#define IS_FREEBOX_MONITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ FREEBOX_TYPE_MONITOR))
+#define IS_FREEBOX_MONITOR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ FREEBOX_TYPE_MONITOR))
+#define FREEBOX_MONITOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ FREEBOX_TYPE_MONITOR, \
+ FreeboxMonitorClass))
+
+typedef struct _FreeboxMonitorPrivate FreeboxMonitorPrivate;
+typedef struct _FreeboxMonitor FreeboxMonitor;
+typedef struct _FreeboxMonitorClass FreeboxMonitorClass;
+
+struct _FreeboxMonitor {
+ GObject parent;
+
+ FreeboxMonitorPrivate *priv;
+};
+
+struct _FreeboxMonitorClass {
+ GObjectClass parent_class;
+};
+
+GType freebox_monitor_get_type (void) G_GNUC_CONST;
+
+FreeboxMonitor *freebox_monitor_new (void);
+
+G_END_DECLS
+
+#endif /* __FREEBOX_MONITOR_H__ */
diff --git a/src/freebox/freebox.gresource.xml b/src/freebox/freebox.gresource.xml
new file mode 100644
index 0000000..5942941
--- /dev/null
+++ b/src/freebox/freebox.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/grilo/plugins/freebox">
+ <file compressed="false">free.png</file>
+ </gresource>
+</gresources>
diff --git a/src/freebox/grl-freebox.c b/src/freebox/grl-freebox.c
new file mode 100644
index 0000000..7d53872
--- /dev/null
+++ b/src/freebox/grl-freebox.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2013 Bastien Nocera
+ *
+ * Contact: Bastien Nocera <hadess hadess net>
+ *
+ * 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 <grilo.h>
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pls/grl-pls.h>
+
+#include "grl-freebox.h"
+#include "freebox-monitor.h"
+
+#define FREEBOX_URL "http://mafreebox.freebox.fr/freeboxtv/playlist.m3u"
+
+/* --------- Logging -------- */
+
+#define GRL_LOG_DOMAIN_DEFAULT freebox_log_domain
+GRL_LOG_DOMAIN_STATIC(freebox_log_domain);
+
+/* --- Plugin information --- */
+
+#define PLUGIN_ID FREEBOX_PLUGIN_ID
+
+#define SOURCE_ID "grl-freebox"
+#define SOURCE_NAME _("Freebox TV")
+#define SOURCE_DESC _("A source for browsing Freebox TV channels")
+
+/* --- Grilo Freebox Private --- */
+
+#define GRL_FREEBOX_SOURCE_GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((object), \
+ GRL_FREEBOX_SOURCE_TYPE, \
+ GrlFreeboxSourcePrivate))
+
+struct _GrlFreeboxSourcePrivate {
+ GrlMedia *media;
+ int last_seen_channel;
+};
+
+/* --- Data types --- */
+
+static GrlFreeboxSource *grl_freebox_source_new (void);
+
+static void grl_freebox_source_finalize (GObject *object);
+
+gboolean grl_freebox_plugin_init (GrlRegistry *registry,
+ GrlPlugin *plugin,
+ GList *configs);
+
+static const GList *grl_freebox_source_supported_keys (GrlSource *source);
+
+static void grl_freebox_source_browse (GrlSource *source,
+ GrlSourceBrowseSpec *bs);
+
+/* =================== Freebox Plugin =============== */
+
+static void
+freebox_found (FreeboxMonitor *mon,
+ const char *name,
+ GrlPlugin *plugin)
+{
+ GrlFreeboxSource *source;
+ GrlRegistry *registry;
+
+ if (g_object_get_data (G_OBJECT (plugin), "source") != NULL)
+ return;
+
+ GRL_DEBUG ("Found a Freebox: %s", name);
+
+ source = grl_freebox_source_new ();
+ registry = grl_registry_get_default ();
+
+ g_object_set_data (G_OBJECT (plugin), "source", source);
+ grl_registry_register_source (registry,
+ plugin,
+ GRL_SOURCE (source),
+ NULL);
+}
+
+static void
+freebox_lost (FreeboxMonitor *mon,
+ const char *name,
+ GrlPlugin *plugin)
+{
+ GrlFreeboxSource *source;
+ GrlRegistry *registry;
+
+ source = g_object_get_data (G_OBJECT (plugin), "source");
+ if (source == NULL)
+ return;
+
+ GRL_DEBUG ("Remove a Freebox: %s", name);
+
+ registry = grl_registry_get_default ();
+
+ grl_registry_unregister_source (registry,
+ GRL_SOURCE (source),
+ NULL);
+}
+
+gboolean
+grl_freebox_plugin_init (GrlRegistry *registry,
+ GrlPlugin *plugin,
+ GList *configs)
+{
+ FreeboxMonitor *mon;
+
+ GRL_LOG_DOMAIN_INIT (freebox_log_domain, "freebox");
+
+ GRL_DEBUG ("%s", __FUNCTION__);
+
+ /* Initialize i18n */
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ mon = freebox_monitor_new ();
+ g_signal_connect (mon, "found",
+ G_CALLBACK (freebox_found), plugin);
+ g_signal_connect (mon, "lost",
+ G_CALLBACK (freebox_lost), plugin);
+
+ return TRUE;
+}
+
+GRL_PLUGIN_REGISTER (grl_freebox_plugin_init,
+ NULL,
+ PLUGIN_ID);
+
+/* ================== Freebox GObject ================ */
+
+
+G_DEFINE_TYPE (GrlFreeboxSource,
+ grl_freebox_source,
+ GRL_TYPE_SOURCE);
+
+static GrlFreeboxSource *
+grl_freebox_source_new (void)
+{
+ GIcon *icon;
+ GFile *file;
+ GrlFreeboxSource *object;
+
+ GRL_DEBUG ("%s", __FUNCTION__);
+
+ file = g_file_new_for_uri ("resource:///org/gnome/grilo/plugins/freebox/free.png");
+ icon = g_file_icon_new (file);
+ g_object_unref (file);
+ object = g_object_new (GRL_FREEBOX_SOURCE_TYPE,
+ "source-id", SOURCE_ID,
+ "source-name", SOURCE_NAME,
+ "source-desc", SOURCE_DESC,
+ "supported-media", GRL_MEDIA_TYPE_VIDEO,
+ "source-icon", icon,
+ NULL);
+ return object;
+}
+
+static void
+grl_freebox_source_class_init (GrlFreeboxSourceClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GrlSourceClass *source_class = GRL_SOURCE_CLASS (klass);
+
+ object_class->finalize = grl_freebox_source_finalize;
+
+ source_class->supported_keys = grl_freebox_source_supported_keys;
+ source_class->browse = grl_freebox_source_browse;
+
+ g_type_class_add_private (klass, sizeof (GrlFreeboxSourcePrivate));
+}
+
+static void
+grl_freebox_source_init (GrlFreeboxSource *source)
+{
+ GrlFreeboxSourcePrivate *priv;
+
+ priv = source->priv = GRL_FREEBOX_SOURCE_GET_PRIVATE(source);
+
+ priv->media = grl_media_new ();
+ grl_media_set_url (priv->media, FREEBOX_URL);
+}
+
+static void
+grl_freebox_source_finalize (GObject *object)
+{
+ GrlFreeboxSource *source = GRL_FREEBOX_SOURCE (object);
+ GrlFreeboxSourcePrivate *priv = GRL_FREEBOX_SOURCE (source)->priv;
+
+ g_object_unref (priv->media);
+
+ G_OBJECT_CLASS (grl_freebox_source_parent_class)->finalize (object);
+}
+
+/* ================== API Implementation ================ */
+
+static const GList *
+grl_freebox_source_supported_keys (GrlSource *source)
+{
+ static GList *keys = NULL;
+ if (!keys) {
+ keys = grl_metadata_key_list_new (GRL_METADATA_KEY_ID,
+ GRL_METADATA_KEY_TITLE,
+ GRL_METADATA_KEY_URL,
+ GRL_METADATA_KEY_MIME,
+ NULL);
+ }
+ return keys;
+}
+
+static char *
+cleanup_title (const char *title)
+{
+ const char *flavours[] = {
+ " (auto)",
+ " (bas débit)",
+ " (standard)",
+ " (HD)"
+ };
+ guint i;
+ const char *s;
+
+ s = strstr (title, " - ") + strlen (" - ");
+ g_return_val_if_fail (s != NULL, NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (flavours); i++) {
+ if (g_str_has_suffix (s, flavours[i]))
+ return g_strndup (s, strlen (s) - strlen (flavours[i]));
+ }
+ return g_strdup (s);
+}
+
+static char *
+remove_flavour (const char *url)
+{
+ char *s;
+
+ s = strstr (url, "&flavour=");
+ if (s == NULL)
+ return g_strdup (url);
+ return g_strndup (url, s - url);
+}
+
+static GrlMedia *
+filter_func (GrlSource *source,
+ GrlMedia *media,
+ gpointer user_data)
+{
+ GrlFreeboxSourcePrivate *priv = GRL_FREEBOX_SOURCE (source)->priv;
+ GrlMedia *ret;
+ const gchar *title;
+ char *new_title;
+ char *url;
+ int channel_num;
+
+ title = grl_media_get_title (media);
+ if (title == NULL) {
+ g_object_unref (media);
+ return NULL;
+ }
+
+ /* Title are of the form:
+ * channel_num - Name (flavour)
+ * such as:
+ * 689 - Star gold (standard)
+ *
+ * And channel numbers are ever increasing */
+ channel_num = atoi (title);
+ if (channel_num == priv->last_seen_channel) {
+ /* Already processed this title */
+ g_object_unref (media);
+ return NULL;
+ }
+ /* if channel_num is lower than last_seen_channel,
+ * we're actually processing the playlist again,
+ * so don't skip it */
+ priv->last_seen_channel = channel_num;
+
+ new_title = cleanup_title (title);
+ url = remove_flavour (grl_media_get_url (media));
+
+ ret = grl_media_video_new ();
+ grl_media_set_url (ret, url);
+ grl_media_set_id (ret, url);
+ grl_media_set_title (ret, new_title);
+ g_free (new_title);
+ g_free (url);
+
+ g_object_unref (media);
+
+ return ret;
+}
+
+static void
+grl_freebox_source_browse (GrlSource *source,
+ GrlSourceBrowseSpec *bs)
+{
+ GrlFreeboxSourcePrivate *priv = GRL_FREEBOX_SOURCE (source)->priv;
+
+ grl_pls_browse (source,
+ priv->media,
+ bs->keys,
+ bs->options,
+ filter_func,
+ bs->callback,
+ bs->user_data);
+}
diff --git a/src/freebox/grl-freebox.h b/src/freebox/grl-freebox.h
new file mode 100644
index 0000000..6cd0de5
--- /dev/null
+++ b/src/freebox/grl-freebox.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Bastien Nocera
+ *
+ * Contact: Bastien Nocera <hadess hadess net>
+ *
+ * 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_FREEBOX_SOURCE_H_
+#define _GRL_FREEBOX_SOURCE_H_
+
+#include <grilo.h>
+
+#define GRL_FREEBOX_SOURCE_TYPE \
+ (grl_freebox_source_get_type ())
+
+#define GRL_FREEBOX_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GRL_FREEBOX_SOURCE_TYPE, \
+ GrlFreeboxSource))
+
+#define GRL_IS_FREEBOX_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GRL_FREEBOX_SOURCE_TYPE))
+
+#define GRL_FREEBOX_SOURCE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ GRL_FREEBOX_SOURCE_TYPE, \
+ GrlFreeboxSourceClass))
+
+#define GRL_IS_FREEBOX_SOURCE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass) \
+ GRL_FREEBOX_SOURCE_TYPE))
+
+#define GRL_FREEBOX_SOURCE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GRL_FREEBOX_SOURCE_TYPE, \
+ GrlFreeboxSourceClass))
+
+
+typedef struct _GrlFreeboxSource GrlFreeboxSource;
+typedef struct _GrlFreeboxSourcePrivate GrlFreeboxSourcePrivate;
+
+struct _GrlFreeboxSource {
+
+ GrlSource parent;
+
+ /*< private >*/
+ GrlFreeboxSourcePrivate *priv;
+};
+
+typedef struct _GrlFreeboxSourceClass GrlFreeboxSourceClass;
+
+struct _GrlFreeboxSourceClass {
+
+ GrlSourceClass parent_class;
+
+};
+
+GType grl_freebox_source_get_type (void);
+
+#endif /* _GRL_FREEBOX_SOURCE_H_ */
diff --git a/src/freebox/grl-freebox.xml b/src/freebox/grl-freebox.xml
new file mode 100644
index 0000000..41baf10
--- /dev/null
+++ b/src/freebox/grl-freebox.xml
@@ -0,0 +1,10 @@
+<plugin>
+ <info>
+ <name>Freebox</name>
+ <module>libgrlfreebox</module>
+ <description>A plugin for Freebox TV channels</description>
+ <author>GNOME</author>
+ <license>LGPL</license>
+ <site>http://www.gnome.org</site>
+ </info>
+</plugin>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]