From 1c78f55a08f1ed354b304e6706b825f3b5548def Mon Sep 17 00:00:00 2001 From: Peter Maatman Date: Mon, 6 Apr 2015 13:09:35 +0200 Subject: [PATCH] Fix #9659 by adding a comicbook archive plugin --- acinclude.m4 | 20 + configure.ac | 7 + plugins/Makefile.am | 1 + plugins/comicbook-thumbnailer/Makefile.am | 62 +++ .../comicbook-thumbnailer-plugin.c | 93 ++++ .../comicbook-thumbnailer-provider.c | 141 +++++++ .../comicbook-thumbnailer-provider.h | 43 ++ .../comicbook-thumbnailer/comicbook-thumbnailer.c | 468 +++++++++++++++++++++ .../comicbook-thumbnailer/comicbook-thumbnailer.h | 43 ++ 9 files changed, 878 insertions(+) create mode 100644 plugins/comicbook-thumbnailer/Makefile.am create mode 100644 plugins/comicbook-thumbnailer/comicbook-thumbnailer-plugin.c create mode 100644 plugins/comicbook-thumbnailer/comicbook-thumbnailer-provider.c create mode 100644 plugins/comicbook-thumbnailer/comicbook-thumbnailer-provider.h create mode 100644 plugins/comicbook-thumbnailer/comicbook-thumbnailer.c create mode 100644 plugins/comicbook-thumbnailer/comicbook-thumbnailer.h diff --git a/acinclude.m4 b/acinclude.m4 index 66e79d1..2d83722 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -268,6 +268,26 @@ AC_MSG_RESULT([$ac_tumbler_cover_thumbnailer]) +dnl TUMBLER_COMICBOOK_THUMBNAILER() +dnl +dnl Check whether to build and install the Comicbook Archive thumbnailer plugin. +dnl +AC_DEFUN([TUMBLER_COMICBOOK_THUMBNAILER], +[ +AC_ARG_ENABLE([comicbook-thumbnailer], [AC_HELP_STRING([--disable-comicbook-thumbnailer], [Don't build the Comicbook Archive thumbnailer plugin])], + [ac_tumbler_comicbook_thumbnailer=$enableval], [ac_tumbler_comicbook_thumbnailer=yes]) +if test x"$ac_tumbler_comicbook_thumbnailer" = x"yes"; then + dnl Check for gdk-pixbuf + PKG_CHECK_MODULES([GDK_PIXBUF], [gdk-pixbuf-2.0 >= 2.14]) +fi + +AC_MSG_CHECKING([whether to build the Comicbook Archive thumbnailer plugin]) +AM_CONDITIONAL([TUMBLER_COMICBOOK_THUMBNAILER], [test x"$ac_tumbler_comicbook_thumbnailer" = x"yes"]) +AC_MSG_RESULT([$ac_tumbler_comicbook_thumbnailer]) +]) + + + dnl TUMBLER_XDG_CACHE() dnl dnl Check whether to build and install the freedesktop.org cache plugin. diff --git a/configure.ac b/configure.ac index a8dc277..436c0c9 100644 --- a/configure.ac +++ b/configure.ac @@ -153,6 +153,7 @@ dnl ************************* dnl *** Check for plugins *** dnl ************************* TUMBLER_COVER_THUMBNAILER() +TUMBLER_COMICBOOK_THUMBNAILER() TUMBLER_FONT_THUMBNAILER() TUMBLER_JPEG_THUMBNAILER() TUMBLER_PIXBUF_THUMBNAILER() @@ -187,6 +188,7 @@ docs/reference/tumbler/Makefile docs/reference/tumbler/version.xml plugins/Makefile plugins/cover-thumbnailer/Makefile +plugins/comicbook-thumbnailer/Makefile plugins/font-thumbnailer/Makefile plugins/gst-thumbnailer/Makefile plugins/jpeg-thumbnailer/Makefile @@ -223,6 +225,11 @@ echo " * Cover thumbnailer plugin: yes" else echo " * Cover thumbnailer plugin: no" fi +if test x"$ac_tumbler_comicbook_thumbnailer" = x"yes"; then +echo " * Comicbook Archive thumbnailer plugin: yes" +else +echo " * Comicbook Archive thumbnailer plugin: no" +fi if test x"$ac_tumbler_font_thumbnailer" = x"yes"; then echo " * FreeType font thumbnailer plugin: yes" else diff --git a/plugins/Makefile.am b/plugins/Makefile.am index f2c9f5f..89d5179 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -19,6 +19,7 @@ SUBDIRS = \ cover-thumbnailer \ + comicbook-thumbnailer \ font-thumbnailer \ gst-thumbnailer \ jpeg-thumbnailer \ diff --git a/plugins/comicbook-thumbnailer/Makefile.am b/plugins/comicbook-thumbnailer/Makefile.am new file mode 100644 index 0000000..5098619 --- /dev/null +++ b/plugins/comicbook-thumbnailer/Makefile.am @@ -0,0 +1,62 @@ +# vi:set ts=8 sw=8 noet ai nocindent: +# - +# Copyright (c) 2012 Nick Schermer +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +if TUMBLER_COMICBOOK_THUMBNAILER + +tumbler_plugindir = $(libdir)/tumbler-$(TUMBLER_VERSION_API)/plugins +tumbler_plugin_LTLIBRARIES = \ + tumbler-comicbook-thumbnailer.la + +tumbler_comicbook_thumbnailer_la_SOURCES = \ + comicbook-thumbnailer-plugin.c \ + comicbook-thumbnailer-provider.c \ + comicbook-thumbnailer-provider.h \ + comicbook-thumbnailer.c \ + comicbook-thumbnailer.h + +tumbler_comicbook_thumbnailer_la_CFLAGS = \ + -I$(top_builddir) \ + -I$(top_builddir)/plugins \ + -I$(top_srcdir) \ + -I$(top_srcdir)/plugins \ + -DG_LOG_DOMAIN=\"tumbler-comicbook-thumbnailer\" \ + -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ + $(GDK_PIXBUF_CFLAGS) \ + $(GIO_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(PLATFORM_CFLAGS) \ + $(PLATFORM_CPPFLAGS) + +tumbler_comicbook_thumbnailer_la_LDFLAGS = \ + -avoid-version \ + -export-dynamic \ + -module \ + $(PLATFORM_LDFLAGS) + +tumbler_comicbook_thumbnailer_la_LIBADD = \ + $(top_builddir)/tumbler/libtumbler-$(TUMBLER_VERSION_API).la \ + $(GDK_PIXBUF_LIBS) \ + $(GIO_LIBS) \ + $(GLIB_LIBS) \ + -lm + +tumbler_comicbook_thumbnailer_la_DEPENDENCIES = \ + $(top_builddir)/tumbler/libtumbler-$(TUMBLER_VERSION_API).la + +endif diff --git a/plugins/comicbook-thumbnailer/comicbook-thumbnailer-plugin.c b/plugins/comicbook-thumbnailer/comicbook-thumbnailer-plugin.c new file mode 100644 index 0000000..78d63fb --- /dev/null +++ b/plugins/comicbook-thumbnailer/comicbook-thumbnailer-plugin.c @@ -0,0 +1,93 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann + * Copyright (c) 2011 Nick Schermer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include +#include + + + +G_MODULE_EXPORT void tumbler_plugin_initialize (TumblerProviderPlugin *plugin); +G_MODULE_EXPORT void tumbler_plugin_shutdown (void); +G_MODULE_EXPORT void tumbler_plugin_get_types (const GType **types, + gint *n_types); + + + +static GType type_list[1]; + + + +void +tumbler_plugin_initialize (TumblerProviderPlugin *plugin) +{ + const gchar *mismatch; + + /* verify that the tumbler versions are compatible */ + mismatch = tumbler_check_version (TUMBLER_MAJOR_VERSION, + TUMBLER_MINOR_VERSION, + TUMBLER_MICRO_VERSION); + if (G_UNLIKELY (mismatch != NULL)) + { + g_warning (_("Version mismatch: %s"), mismatch); + return; + } + +#ifdef DEBUG + g_print ("Initializing the Tumbler Comicbook Thumbnailer plugin\n"); +#endif + + /* register the types provided by this plugin */ + comicbook_thumbnailer_register (plugin); + comicbook_thumbnailer_provider_register (plugin); + + /* set up the plugin provider type list */ + type_list[0] = TYPE_COMICBOOK_THUMBNAILER_PROVIDER; +} + + + +void +tumbler_plugin_shutdown (void) +{ +#ifdef DEBUG + g_print ("Shutting down the Tumbler Comicbook Thumbnailer plugin\n"); +#endif +} + + + +void +tumbler_plugin_get_types (const GType **types, + gint *n_types) +{ + *types = type_list; + *n_types = G_N_ELEMENTS (type_list); +} diff --git a/plugins/comicbook-thumbnailer/comicbook-thumbnailer-provider.c b/plugins/comicbook-thumbnailer/comicbook-thumbnailer-provider.c new file mode 100644 index 0000000..a2ee46b --- /dev/null +++ b/plugins/comicbook-thumbnailer/comicbook-thumbnailer-provider.c @@ -0,0 +1,141 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2012 Nick Schermer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include +#include + + + +static void comicbook_thumbnailer_provider_thumbnailer_provider_init (TumblerThumbnailerProviderIface *iface); +static GList *comicbook_thumbnailer_provider_get_thumbnailers (TumblerThumbnailerProvider *provider); +static void comicbook_thumbnailer_provider_finalize (GObject *object); + + + +struct _ComicbookThumbnailerProviderClass +{ + GObjectClass __parent__; +}; + +struct _ComicbookThumbnailerProvider +{ + GObject __parent__; +}; + + + +G_DEFINE_DYNAMIC_TYPE_EXTENDED (ComicbookThumbnailerProvider, + comicbook_thumbnailer_provider, + G_TYPE_OBJECT, + 0, + TUMBLER_ADD_INTERFACE (TUMBLER_TYPE_THUMBNAILER_PROVIDER, + comicbook_thumbnailer_provider_thumbnailer_provider_init)); + + + +void +comicbook_thumbnailer_provider_register (TumblerProviderPlugin *plugin) +{ + comicbook_thumbnailer_provider_register_type (G_TYPE_MODULE (plugin)); +} + + + +static void +comicbook_thumbnailer_provider_class_init (ComicbookThumbnailerProviderClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = comicbook_thumbnailer_provider_finalize; +} + + + +static void +comicbook_thumbnailer_provider_class_finalize (ComicbookThumbnailerProviderClass *klass) +{ +} + + + +static void +comicbook_thumbnailer_provider_thumbnailer_provider_init (TumblerThumbnailerProviderIface *iface) +{ + iface->get_thumbnailers = comicbook_thumbnailer_provider_get_thumbnailers; +} + + + +static void +comicbook_thumbnailer_provider_init (ComicbookThumbnailerProvider *provider) +{ +} + + + +static void +comicbook_thumbnailer_provider_finalize (GObject *object) +{ + (*G_OBJECT_CLASS (comicbook_thumbnailer_provider_parent_class)->finalize) (object); +} + + + +static GList * +comicbook_thumbnailer_provider_get_thumbnailers (TumblerThumbnailerProvider *provider) +{ + ComicbookThumbnailer *thumbnailer; + GList *thumbnailers = NULL; + GStrv uri_schemes; + static const gchar *mime_types[] = + { + "application/x-cbr", + NULL + }; + + /* determine the URI schemes supported by GIO */ + uri_schemes = tumbler_util_get_supported_uri_schemes (); + + /* create the pixbuf thumbnailer */ + thumbnailer = g_object_new (TYPE_COMICBOOK_THUMBNAILER, + "uri-schemes", uri_schemes, + "mime-types", mime_types, + NULL); + + /* add the thumbnailer to the list */ + thumbnailers = g_list_append (thumbnailers, thumbnailer); + + /* free URI schemes */ + g_strfreev (uri_schemes); + + return thumbnailers; +} diff --git a/plugins/comicbook-thumbnailer/comicbook-thumbnailer-provider.h b/plugins/comicbook-thumbnailer/comicbook-thumbnailer-provider.h new file mode 100644 index 0000000..ebe1fa1 --- /dev/null +++ b/plugins/comicbook-thumbnailer/comicbook-thumbnailer-provider.h @@ -0,0 +1,43 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __COMICBOOK_THUMBNAILER_PROVIDER_H__ +#define __COMICBOOK_THUMBNAILER_PROVIDER_H__ + +#include + +G_BEGIN_DECLS + +#define TYPE_COMICBOOK_THUMBNAILER_PROVIDER (comicbook_thumbnailer_provider_get_type ()) +#define COMICBOOK_THUMBNAILER_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_COMICBOOK_THUMBNAILER_PROVIDER, ComicbookThumbnailerProvider)) +#define COMICBOOK_THUMBNAILER_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_COMICBOOK_THUMBNAILER_PROVIDER, ComicbookThumbnailerProviderClass)) +#define IS_COMICBOOK_THUMBNAILER_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_COMICBOOK_THUMBNAILER_PROVIDER)) +#define IS_COMICBOOK_THUMBNAILER_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_COMICBOOK_THUMBNAILER_PROVIDER) +#define COMICBOOK_THUMBNAILER_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_COMICBOOK_THUMBNAILER_PROVIDER, ComicbookThumbnailerProviderClass)) + +typedef struct _ComicbookThumbnailerProviderClass ComicbookThumbnailerProviderClass; +typedef struct _ComicbookThumbnailerProvider ComicbookThumbnailerProvider; + +GType comicbook_thumbnailer_provider_get_type (void) G_GNUC_CONST; +void comicbook_thumbnailer_provider_register (TumblerProviderPlugin *plugin); + +G_END_DECLS + +#endif /* !__COMICBOOK_THUMBNAILER_PROVIDER_H__ */ diff --git a/plugins/comicbook-thumbnailer/comicbook-thumbnailer.c b/plugins/comicbook-thumbnailer/comicbook-thumbnailer.c new file mode 100644 index 0000000..761ae7a --- /dev/null +++ b/plugins/comicbook-thumbnailer/comicbook-thumbnailer.c @@ -0,0 +1,468 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann + * Copyright (c) 2011 Tam Merlant + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include "comicbook-thumbnailer.h" + +static void comicbook_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer, + GCancellable *cancellable, + TumblerFileInfo *info); + + + +struct _ComicbookThumbnailerClass +{ + TumblerAbstractThumbnailerClass __parent__; +}; + +struct _ComicbookThumbnailer +{ + TumblerAbstractThumbnailer __parent__; +}; + + + +G_DEFINE_DYNAMIC_TYPE (ComicbookThumbnailer, + comicbook_thumbnailer, + TUMBLER_TYPE_ABSTRACT_THUMBNAILER); + + + +void +comicbook_thumbnailer_register (TumblerProviderPlugin *plugin) +{ + comicbook_thumbnailer_register_type (G_TYPE_MODULE (plugin)); +} + + + +static void +comicbook_thumbnailer_class_init (ComicbookThumbnailerClass *klass) +{ + TumblerAbstractThumbnailerClass *abstractthumbnailer_class; + + abstractthumbnailer_class = TUMBLER_ABSTRACT_THUMBNAILER_CLASS (klass); + abstractthumbnailer_class->create = comicbook_thumbnailer_create; +} + + + +static void +comicbook_thumbnailer_class_finalize (ComicbookThumbnailerClass *klass) +{ +} + + + +static void +comicbook_thumbnailer_init (ComicbookThumbnailer *thumbnailer) +{ +} + + + +static GdkPixbuf* +scale_pixbuf (GdkPixbuf *source, + gint dest_width, + gint dest_height) +{ + gdouble wratio; + gdouble hratio; + gint source_width; + gint source_height; + + /* determine source pixbuf dimensions */ + source_width = gdk_pixbuf_get_width (source); + source_height = gdk_pixbuf_get_height (source); + + /* don't do anything if there is no need to resize */ + if (source_width <= dest_width && source_height <= dest_height) + return g_object_ref (source); + + /* determine which axis needs to be scaled down more */ + wratio = (gdouble) source_width / (gdouble) dest_width; + hratio = (gdouble) source_height / (gdouble) dest_height; + + /* adjust the other axis */ + if (hratio > wratio) + dest_width = rint (source_width / hratio); + else + dest_height = rint (source_height / wratio); + + /* scale the pixbuf down to the desired size */ + return gdk_pixbuf_scale_simple (source, MAX (dest_width, 1), + MAX (dest_height, 1), + GDK_INTERP_BILINEAR); +} + + + +static gint +compare_main_func(gchar** a, gchar** b) +{ + gint n; + + gchar* aaa = g_utf8_collate_key_for_filename (*a, -1); + gchar* bbb = g_utf8_collate_key_for_filename (*b, -1); + n = g_strcmp0(aaa, bbb); + g_free(aaa); + g_free(bbb); + return n; +} + + + +static gint +compare_data_func(gconstpointer a, gconstpointer b) { + return compare_main_func((gchar**)a, (gchar**)b); +} + + +static GFile* +comicbook_thumbnailer_get_cover_file( TumblerAbstractThumbnailer *thumbnailer, + GFile *dir) +{ + GFileInfo *info; + GFileEnumerator *dir_contents; + GPtrArray* files; + GFile *file; + GError *error = NULL; + + dir_contents = g_file_enumerate_children( dir, + "standard::*", + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, + &error); + + if (error != NULL) + { + g_signal_emit_by_name (thumbnailer, "error", g_file_get_basename(dir), error->code, error->message); + g_error_free (error); + } + + files = g_ptr_array_new(); + for (;;) + { + info = g_file_enumerator_next_file(dir_contents, NULL, NULL); + if (info == NULL) break; + g_ptr_array_add(files, g_strdup(g_file_info_get_display_name(info))); + g_object_unref(info); + } + g_object_unref(dir_contents); + + g_ptr_array_sort(files, compare_data_func); + file = g_file_new_for_path(g_strconcat(g_file_get_path(dir), "/", g_strdup((gchar*)g_ptr_array_index(files, 0)), NULL)); + g_ptr_array_free(files, TRUE); + + return file; +} + + + +static void +comicbook_thumbnailer_delete_temp_directory(TumblerAbstractThumbnailer *thumbnailer, + GFile *dir) +{ + GFileInfo *info; + GFileEnumerator *dir_contents; + GError *error; + GFile *f; + + dir_contents = g_file_enumerate_children( dir, + "standard::*", + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, + &error); + + for (;;) + { + info = g_file_enumerator_next_file(dir_contents, NULL, NULL); + if (info == NULL) break; + f = g_file_new_for_path(g_strconcat(g_file_get_path(dir), "/", g_file_info_get_name(info), NULL)); + g_file_delete(f, NULL, NULL); + } + + g_file_delete(dir, NULL, &error); +} + + + +static GFile* +comicbook_thumbnailer_unrar(TumblerAbstractThumbnailer *thumbnailer, + GFile *file) +{ + GError *error = NULL; + gint exit_status; + gchar *dirname; + gchar *command_string; + gchar **argv; + GFile *dir; + + dirname = g_dir_make_tmp(g_strconcat(g_file_get_basename(file), "-XXXXXX", NULL), &error); + dir = g_file_new_for_path(g_strdup(dirname)); + + if (error != NULL) + { + g_signal_emit_by_name (thumbnailer, "error", dirname, error->code, error->message); + g_error_free (error); + } + + command_string = g_strconcat("/usr/bin/unrar x ", g_file_get_path(file), " ", dirname, NULL); + argv = g_strsplit(command_string, " ", 0); + + g_spawn_sync( ".", // working directory + argv, // command + NULL, // environment + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_DEFAULT, + NULL, // childsetup + NULL, // userdata + NULL, // stdout + NULL, // stderr + &exit_status, + &error); + + if (error != NULL) + { + g_signal_emit_by_name (thumbnailer, "error", command_string, error->code, error->message); + g_error_free (error); + } + + g_strfreev(argv); + g_free(dirname); + g_free(command_string); + + return dir; +} + + + +static GFile* +comicbook_thumbnailer_unzip(TumblerAbstractThumbnailer *thumbnailer, + GFile *file) +{ + GError *error = NULL; + gint exit_status; + gchar *dirname; + gchar *command_string; + gchar **argv; + GFile *dir; + + dirname = g_dir_make_tmp(g_strconcat(g_file_get_basename(file), "-XXXXXX", NULL), &error); + dir = g_file_new_for_path(g_strdup(dirname)); + + if (error != NULL) + { + g_signal_emit_by_name (thumbnailer, "error", dirname, error->code, error->message); + g_error_free (error); + } + + command_string = g_strconcat("/usr/bin/unzip ", g_file_get_path(file), " -d ", dirname, NULL); + argv = g_strsplit(command_string, " ", 0); + + g_spawn_sync( ".", // working directory + argv, // command + NULL, // environment + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_DEFAULT, + NULL, // childsetup + NULL, // userdata + NULL, // stdout + NULL, // stderr + &exit_status, + &error); + + if (error != NULL) + { + g_signal_emit_by_name (thumbnailer, "error", command_string, error->code, error->message); + g_error_free (error); + } + + g_strfreev(argv); + g_free(dirname); + g_free(command_string); + + return dir; +} + + + +static GdkPixbuf* +comicbook_thumbnailer_get_cover(TumblerAbstractThumbnailer *thumbnailer, + GFile *file) +{ + gchar *filename; + GError *error = NULL; + GFile *dir; + GFile *first_file; + GdkPixbuf* pixbuf; + + filename = g_file_get_basename(file); + + if (g_str_has_suffix(filename, "cbr")) + { + // TODO: unarchive with unrar to a temp dir + dir = comicbook_thumbnailer_unrar(thumbnailer, file); + } + else if (g_str_has_suffix(filename, "cbz")) + { + dir = comicbook_thumbnailer_unzip(thumbnailer, file); + } + else + { + dir = NULL; + } + + if (dir != NULL) + { + first_file = comicbook_thumbnailer_get_cover_file(thumbnailer, dir); + + if (error != NULL) + { + g_signal_emit_by_name (thumbnailer, "error", g_file_get_path(dir), error->code, error->message); + g_error_free (error); + } + + pixbuf = gdk_pixbuf_new_from_file(g_file_get_path(first_file), &error); + if (pixbuf == NULL) + { + g_signal_emit_by_name (thumbnailer, "error", g_file_get_basename(first_file), error->code, error->message); + g_error_free (error); + } + + /* Remove the directory now that we are done with it */ + comicbook_thumbnailer_delete_temp_directory(thumbnailer, dir); + + g_free(filename); + } + + return pixbuf; +} + + +static void +comicbook_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer, + GCancellable *cancellable, + TumblerFileInfo *info) +{ + TumblerThumbnailFlavor *flavor; + TumblerImageData data; + TumblerThumbnail *thumbnail; + const gchar *uri; + gchar *path; + GdkPixbuf *pixbuf = NULL; + GError *error = NULL; + GFile *file; + gint height; + gint width; + GdkPixbuf *scaled; + + g_return_if_fail (IS_COMICBOOK_THUMBNAILER (thumbnailer)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + g_return_if_fail (TUMBLER_IS_FILE_INFO (info)); + + /* do nothing if cancelled */ + if (g_cancellable_is_cancelled (cancellable)) + return; + + uri = tumbler_file_info_get_uri (info); + file = g_file_new_for_uri (uri); + + thumbnail = tumbler_file_info_get_thumbnail (info); + g_assert (thumbnail != NULL); + + /* get destination size */ + flavor = tumbler_thumbnail_get_flavor (thumbnail); + g_assert (flavor != NULL); + tumbler_thumbnail_flavor_get_size (flavor, &width, &height); + g_object_unref (flavor); + + /* libopencomicbook only handles local IO */ + path = g_file_get_path (file); + if (path != NULL && g_path_is_absolute (path)) + { + pixbuf = comicbook_thumbnailer_get_cover(thumbnailer, file); + + if (pixbuf == NULL) + { + g_set_error_literal (&error, TUMBLER_ERROR, TUMBLER_ERROR_NO_CONTENT, + _("Thumbnail could not be inferred from file contents")); + } + } + else + { + g_set_error_literal (&error, TUMBLER_ERROR, TUMBLER_ERROR_UNSUPPORTED, + _("Only local files are supported")); + } + + g_free (path); + g_object_unref (file); + + if (pixbuf != NULL) + { + scaled = scale_pixbuf (pixbuf, width, height); + g_object_unref (pixbuf); + pixbuf = scaled; + + data.data = gdk_pixbuf_get_pixels (pixbuf); + data.has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); + data.bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf); + data.width = gdk_pixbuf_get_width (pixbuf); + data.height = gdk_pixbuf_get_height (pixbuf); + data.rowstride = gdk_pixbuf_get_rowstride (pixbuf); + data.colorspace = (TumblerColorspace) gdk_pixbuf_get_colorspace (pixbuf); + + tumbler_thumbnail_save_image_data (thumbnail, &data, + tumbler_file_info_get_mtime (info), + NULL, &error); + } + + if (error != NULL) + { + g_signal_emit_by_name (thumbnailer, "error", uri, error->code, error->message); + g_error_free (error); + } + else + { + g_signal_emit_by_name (thumbnailer, "ready", uri); + g_object_unref (pixbuf); + } + + g_object_unref (thumbnail); +} diff --git a/plugins/comicbook-thumbnailer/comicbook-thumbnailer.h b/plugins/comicbook-thumbnailer/comicbook-thumbnailer.h new file mode 100644 index 0000000..d04c264 --- /dev/null +++ b/plugins/comicbook-thumbnailer/comicbook-thumbnailer.h @@ -0,0 +1,43 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2012 Nick Schermer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __COMICBOOK_THUMBNAILER_H__ +#define __COMICBOOK_THUMBNAILER_H__ + +#include + +G_BEGIN_DECLS + +#define TYPE_COMICBOOK_THUMBNAILER (comicbook_thumbnailer_get_type ()) +#define COMICBOOK_THUMBNAILER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_COMICBOOK_THUMBNAILER, ComicbookThumbnailer)) +#define COMICBOOK_THUMBNAILER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_COMICBOOK_THUMBNAILER, ComicbookThumbnailerClass)) +#define IS_COMICBOOK_THUMBNAILER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_COMICBOOK_THUMBNAILER)) +#define IS_COMICBOOK_THUMBNAILER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_COMICBOOK_THUMBNAILER) +#define COMICBOOK_THUMBNAILER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_COMICBOOK_THUMBNAILER, ComicbookThumbnailerClass)) + +typedef struct _ComicbookThumbnailerClass ComicbookThumbnailerClass; +typedef struct _ComicbookThumbnailer ComicbookThumbnailer; + +GType comicbook_thumbnailer_get_type (void) G_GNUC_CONST; +void comicbook_thumbnailer_register (TumblerProviderPlugin *plugin); + +G_END_DECLS + +#endif /* !__COMICBOOK_THUMBNAILER_H__ */ -- 2.3.5