[Xfce4-commits] <thunar:jannis/thunar-vfs-thumbnailer> Squashme: Initial work on a ThunarVFS thumbnailer plugin for tumbler.

Jannis Pohlmann noreply at xfce.org
Sat Dec 19 13:54:02 CET 2009


Updating branch refs/heads/jannis/thunar-vfs-thumbnailer
         to f4115de7c75269b99ff2a78e545d1560ed6355ec (commit)
       from c44d1c8a0b83862c69cbf69f791c43672d6cfc1d (commit)

commit f4115de7c75269b99ff2a78e545d1560ed6355ec
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Sat Dec 19 13:51:59 2009 +0100

    Squashme: Initial work on a ThunarVFS thumbnailer plugin for tumbler.
    
    Much of this will have to be replaced. We also need a way for plugins to
    notify the Tumbler registry when new URI schemes and MIME types are
    supported.

 configure.in.in                                    |   51 +-
 {docs/reference => tumbler-plugins}/Makefile.am    |    6 +-
 tumbler-plugins/thunar-vfs-thumbnailer/Makefile.am |   61 ++
 .../thunar-vfs-thumbnailer-plugin.c                |   91 +++
 .../thunar-vfs-thumbnailer-provider.c              |  119 ++++
 .../thunar-vfs-thumbnailer-provider.h              |   43 ++
 .../thunar-vfs-thumbnailer.c                       |  600 ++++++++++++++++++++
 .../thunar-vfs-thumbnailer.h                       |   43 ++
 8 files changed, 992 insertions(+), 22 deletions(-)

diff --git a/configure.in.in b/configure.in.in
index 2ccfeac..8fd7e8c 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -118,16 +118,17 @@ dnl **********************************
 dnl *** Check for standard headers ***
 dnl **********************************
 AC_CHECK_HEADERS([ctype.h errno.h fcntl.h grp.h limits.h locale.h memory.h \
-                  paths.h pwd.h sched.h signal.h stdarg.h stdlib.h string.h \
-                  sys/mman.h sys/stat.h sys/time.h sys/types.h sys/uio.h \
-                  sys/wait.h time.h])
+                  paths.h pwd.h sched.h signal.h stdarg.h stdio.h stdlib.h \
+                  string.h sys/mman.h sys/stat.h sys/time.h sys/types.h \
+                  sys/uio.h sys/wait.h time.h])
 
 dnl ************************************
 dnl *** Check for standard functions ***
 dnl ************************************
 AC_FUNC_MMAP()
-AC_CHECK_FUNCS([localeconv mkdtemp pread pwrite sched_yield setgroupent \
-                setpassent strcoll strlcpy strptime symlink])
+AC_CHECK_FUNCS([localeconv mkdtemp posix_madvise pread pwrite sched_yield \
+                setgroupent setpassent setpriority strcoll strlcpy strptime \
+                symlink])
 
 dnl ******************************
 dnl *** Check for i18n support ***
@@ -157,8 +158,13 @@ dnl **********************************
 XDT_CHECK_OPTIONAL_PACKAGE([GIO_UNIX], [gio-unix-2.0],
                            [2.18.0], [gio-unix], [GIO UNIX features])
 
-dnl *******************************************************
-dnl *** Optional support for gconf (GNOME thumbnailers) ***
+dnl **********************************************************
+dnl *** Optional tumbler plugin for ThunarVFS thumbnailers ***
+dnl **********************************************************
+XDT_CHECK_OPTIONAL_PACKAGE([TUMBLER], [tumbler-1], 
+                           [0.1.0], [tumbler], 
+                           [Tumbler plugin for ThunarVFS thumbnailers])
+
 dnl **********************************
 dnl *** Optional support for D-BUS ***
 dnl **********************************
@@ -317,6 +323,8 @@ thunar/Makefile
 thunarx/Makefile
 thunarx/thunarx-2.pc
 thunarx/thunarx-config.h
+tumbler-plugins/Makefile
+tumbler-plugins/thunar-vfs-thumbnailer/Makefile
 ])
 
 dnl ***************************
@@ -326,27 +334,32 @@ echo
 echo "Build Configuration:"
 echo
 if test x"$DBUS_FOUND" = x"yes"; then
-echo "* D-BUS support:             yes"
+echo "* D-BUS support:                             yes"
+else
+echo "* D-BUS support:                             no"
+fi
+if test x"$TUMBLER_FOUND" = x"yes"; then
+echo "* Tumbler plugin for ThunarVFS thumbnailers: yes"
 else
-echo "* D-BUS support:             no"
+echo "* Tumbler plugin for ThunarVFS thumbnailers: no"
 fi
 if test x"$GIO_UNIX_FOUND" = x"yes"; then
-echo "* GIO UNIX features:         yes"
+echo "* GIO UNIX features:                         yes"
 else
-echo "* GIO UNIX features:         no"
+echo "* GIO UNIX features:                         no"
 fi
 if test x"$LIBSTARTUP_NOTIFICATION_FOUND" = x"yes"; then
-echo "* Startup Notification:      yes"
+echo "* Startup Notification:                      yes"
 else
-echo "* Startup Notification:      no"
+echo "* Startup Notification:                      no"
 fi
-echo "* Debug Support:             $enable_debug"
+echo "* Debug Support:                             $enable_debug"
 echo
 echo "Additional Plugins:"
 echo
-echo "* Advanced Properties:       $ac_bm_thunar_plugin_apr"
-echo "* Simple Builting Renamers:  $ac_bm_thunar_plugin_sbr"
-echo "* Trash Panel Applet:        $ac_bm_thunar_plugin_tpa"
-echo "* User Customizable Actions: $ac_bm_thunar_plugin_uca"
-echo "* Wallpaper support:         $ac_bm_thunar_plugin_wallpaper"
+echo "* Advanced Properties:                       $ac_bm_thunar_plugin_apr"
+echo "* Simple Builting Renamers:                  $ac_bm_thunar_plugin_sbr"
+echo "* Trash Panel Applet:                        $ac_bm_thunar_plugin_tpa"
+echo "* User Customizable Actions:                 $ac_bm_thunar_plugin_uca"
+echo "* Wallpaper support:                         $ac_bm_thunar_plugin_wallpaper"
 echo
diff --git a/docs/reference/Makefile.am b/tumbler-plugins/Makefile.am
similarity index 61%
copy from docs/reference/Makefile.am
copy to tumbler-plugins/Makefile.am
index d95c60c..d507cb4 100644
--- a/docs/reference/Makefile.am
+++ b/tumbler-plugins/Makefile.am
@@ -1,6 +1,6 @@
-# $Id$
-
+if HAVE_TUMBLER
 SUBDIRS =								\
-	thunarx
+	thunar-vfs-thumbnailer
+endif
 
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/tumbler-plugins/thunar-vfs-thumbnailer/Makefile.am b/tumbler-plugins/thunar-vfs-thumbnailer/Makefile.am
new file mode 100644
index 0000000..ae12f35
--- /dev/null
+++ b/tumbler-plugins/thunar-vfs-thumbnailer/Makefile.am
@@ -0,0 +1,61 @@
+# vi:set ts=8 sw=8 noet ai nocindent:
+# -
+# Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+# 
+# 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 HAVE_TUMBLER
+
+tumbler_plugindir = $(libdir)/tumbler-1/plugins
+tumbler_plugin_LTLIBRARIES =						\
+	thunar-vfs-thumbnailer.la
+
+thunar_vfs_thumbnailer_la_SOURCES =					\
+	thunar-vfs-thumbnailer-plugin.c					\
+	thunar-vfs-thumbnailer-provider.c				\
+	thunar-vfs-thumbnailer-provider.h				\
+	thunar-vfs-thumbnailer.c					\
+	thunar-vfs-thumbnailer.h
+
+thunar_vfs_thumbnailer_la_CFLAGS =					\
+	-I$(top_builddir)						\
+	-I$(top_builddir)/plugins					\
+	-I$(top_srcdir)							\
+	-I$(top_srcdir)/plugins						\
+	-DG_LOG_DOMAIN=\"thunar-vfs-thumbnailer\"			\
+	-DLIBEXECDIR=\"$(libexecdir)\"					\
+	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"				\
+	$(GDK_PIXBUF_CFLAGS)						\
+	$(GIO_CFLAGS)							\
+	$(GLIB_CFLAGS)							\
+	$(LIBXFCE4UTIL_CFLAGS)						\
+	$(TUMBLER_CFLAGS)						\
+	$(PLATFORM_CPPFLAGS)
+
+thunar_vfs_thumbnailer_la_LDFLAGS =					\
+	-avoid-version							\
+	-export-dynamic							\
+	-module								\
+	$(PLATFORM_LDFLAGS)
+
+thunar_vfs_thumbnailer_la_LIBADD =					\
+	$(GDK_PIXBUF_LIBS)						\
+	$(GIO_LIBS)							\
+	$(GLIB_LIBS)							\
+	$(LIBXFCE4UTIL_LIBS)						\
+	$(TUMBLER_LIBS)
+
+endif
diff --git a/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-plugin.c b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-plugin.c
new file mode 100644
index 0000000..9c858bb
--- /dev/null
+++ b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-plugin.c
@@ -0,0 +1,91 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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 <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#include <tumbler/tumbler.h>
+
+#include <thunar-vfs-thumbnailer-provider.h>
+#include <thunar-vfs-thumbnailer.h>
+
+
+
+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_message (_("Initializing the ThunarVFS Thumbnailer plugin"));
+#endif
+
+  /* register the types provided by this plugin */
+  thunar_vfs_thumbnailer_register (plugin);
+  thunar_vfs_thumbnailer_provider_register (plugin);
+
+  /* set up the plugin provider type list */
+  type_list[0] = TYPE_THUNAR_VFS_THUMBNAILER_PROVIDER;
+}
+
+
+
+void
+tumbler_plugin_shutdown (void)
+{
+#ifdef DEBUG
+  g_message (_("Shutting down the ThunarVFS Thumbnailer plugin"));
+#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/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-provider.c b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-provider.c
new file mode 100644
index 0000000..86cd591
--- /dev/null
+++ b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-provider.c
@@ -0,0 +1,119 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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 <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include <tumbler/tumbler.h>
+
+#include <thunar-vfs-thumbnailer-provider.h>
+#include <thunar-vfs-thumbnailer.h>
+
+
+
+static void   thunar_vfs_thumbnailer_provider_thumbnailer_provider_init (TumblerThumbnailerProviderIface *iface);
+static GList *thunar_vfs_thumbnailer_provider_get_thumbnailers          (TumblerThumbnailerProvider      *provider);
+
+
+
+struct _ThunarVfsThumbnailerProviderClass
+{
+  GObjectClass __parent__;
+};
+
+struct _ThunarVfsThumbnailerProvider
+{
+  GObject __parent__;
+};
+
+
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (ThunarVfsThumbnailerProvider,
+                                thunar_vfs_thumbnailer_provider,
+                                G_TYPE_OBJECT,
+                                0,
+                                TUMBLER_ADD_INTERFACE (TUMBLER_TYPE_THUMBNAILER_PROVIDER,
+                                                       thunar_vfs_thumbnailer_provider_thumbnailer_provider_init));
+
+
+
+void
+thunar_vfs_thumbnailer_provider_register (TumblerProviderPlugin *plugin)
+{
+  thunar_vfs_thumbnailer_provider_register_type (G_TYPE_MODULE (plugin));
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_provider_class_init (ThunarVfsThumbnailerProviderClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_provider_class_finalize (ThunarVfsThumbnailerProviderClass *klass)
+{
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_provider_thumbnailer_provider_init (TumblerThumbnailerProviderIface *iface)
+{
+  iface->get_thumbnailers = thunar_vfs_thumbnailer_provider_get_thumbnailers;
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_provider_init (ThunarVfsThumbnailerProvider *provider)
+{
+}
+
+
+
+static GList *
+thunar_vfs_thumbnailer_provider_get_thumbnailers (TumblerThumbnailerProvider *provider)
+{
+  ThunarVfsThumbnailer *thumbnailer;
+  GList                *thumbnailers = NULL;
+  const gchar          *uri_schemes[] = { NULL, };
+  const gchar          *mime_types[] = { NULL, };
+
+  /* create the pixbuf thumbnailer */
+  thumbnailer = g_object_new (TYPE_THUNAR_VFS_THUMBNAILER, "mime-types", mime_types,
+                              "uri-schemes", uri_schemes, NULL);
+
+  /* add the thumbnailer to the list */
+  thumbnailers = g_list_append (thumbnailers, thumbnailer);
+
+  return thumbnailers;
+}
diff --git a/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-provider.h b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-provider.h
new file mode 100644
index 0000000..ce51fbf
--- /dev/null
+++ b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer-provider.h
@@ -0,0 +1,43 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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 __THUNAR_VFS_THUMBNAILER_PROVIDER_H__
+#define __THUNAR_VFS_THUMBNAILER_PROVIDER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS;
+
+#define TYPE_THUNAR_VFS_THUMBNAILER_PROVIDER            (thunar_vfs_thumbnailer_provider_get_type ())
+#define THUNAR_VFS_THUMBNAILER_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_THUNAR_VFS_THUMBNAILER_PROVIDER, ThunarVfsThumbnailerProvider))
+#define THUNAR_VFS_THUMBNAILER_PROVIDER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_THUNAR_VFS_THUMBNAILER_PROVIDER, ThunarVfsThumbnailerProviderClass))
+#define IS_THUNAR_VFS_THUMBNAILER_PROVIDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_THUNAR_VFS_THUMBNAILER_PROVIDER))
+#define IS_THUNAR_VFS_THUMBNAILER_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_THUNAR_VFS_THUMBNAILER_PROVIDER)
+#define THUNAR_VFS_THUMBNAILER_PROVIDER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_THUNAR_VFS_THUMBNAILER_PROVIDER, ThunarVfsThumbnailerProviderClass))
+
+typedef struct _ThunarVfsThumbnailerProviderClass ThunarVfsThumbnailerProviderClass;
+typedef struct _ThunarVfsThumbnailerProvider      ThunarVfsThumbnailerProvider;
+
+GType thunar_vfs_thumbnailer_provider_get_type (void) G_GNUC_CONST;
+void  thunar_vfs_thumbnailer_provider_register (TumblerProviderPlugin *plugin);
+
+G_END_DECLS;
+
+#endif /* !__THUNAR_VFS_THUMBNAILER_PROVIDER_H__ */
diff --git a/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer.c b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer.c
new file mode 100644
index 0000000..ec68987
--- /dev/null
+++ b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer.c
@@ -0,0 +1,600 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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 <config.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <math.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gio/gio.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include <tumbler/tumbler.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include <thunar-vfs-thumbnailer.h>
+
+
+
+/* use g_open(), g_rename() and g_unlink() on win32 */
+#if defined(G_OS_WIN32)
+#include <glib/gstdio.h>
+#else
+#define g_open(filename, flags, mode) (open ((filename), (flags), (mode)))
+#define g_rename(oldfilename, newfilename) (rename ((oldfilename), (newfilename)))
+#define g_unlink(filename) (unlink ((filename)))
+#endif
+
+
+
+/* thumbnailers cache support */
+#define CACHE_MAJOR_VERSION (1)
+#define CACHE_MINOR_VERSION (0)
+#define CACHE_READ32(cache, offset) (GUINT32_FROM_BE (*((guint32 *) ((cache) + (offset)))))
+
+/* fallback cache if the loading fails */
+static const guint32 CACHE_FALLBACK[4] =
+{
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+  CACHE_MAJOR_VERSION,
+  CACHE_MINOR_VERSION,
+  0,
+  0,
+#else
+  GUINT32_SWAP_LE_BE_CONSTANT (CACHE_MAJOR_VERSION),
+  GUINT32_SWAP_LE_BE_CONSTANT (CACHE_MINOR_VERSION),
+  GUINT32_SWAP_LE_BE_CONSTANT (0),
+  GUINT32_SWAP_LE_BE_CONSTANT (0),
+#endif
+};
+
+
+
+static void     thunar_vfs_thumbnailer_finalize            (GObject                    *object);
+static void     thunar_vfs_thumbnailer_cache_load          (ThunarVfsThumbnailer       *thumbnailer);
+static void     thunar_vfs_thumbnailer_cache_unload        (ThunarVfsThumbnailer       *thumbnailer);
+static void     thunar_vfs_thumbnailer_cache_monitor       (GFileMonitor               *monitor,
+                                                            GFile                      *file,
+                                                            GFile                      *other_file,
+                                                            GFileMonitorEvent           event,
+                                                            gpointer                    user_data);
+static void     thunar_vfs_thumbnailer_cache_update        (ThunarVfsThumbnailer       *thumbnailer);
+static gboolean thunar_vfs_thumbnailer_cache_timer         (gpointer                    user_data);
+static void     thunar_vfs_thumbnailer_cache_timer_destroy (gpointer                    user_data);
+static void     thunar_vfs_thumbnailer_cache_watch         (GPid                        pid,
+                                                            gint                        status,
+                                                            gpointer                    user_data);
+static void     thunar_vfs_thumbnailer_cache_watch_destroy (gpointer                    user_data);
+static void     thunar_vfs_thumbnailer_create              (TumblerAbstractThumbnailer *thumbnailer,
+                                                            GCancellable               *cancellable,
+                                                            TumblerFileInfo            *info);
+
+
+
+struct _ThunarVfsThumbnailerClass
+{
+  TumblerAbstractThumbnailerClass __parent__;
+};
+
+struct _ThunarVfsThumbnailer
+{
+  TumblerAbstractThumbnailer __parent__;
+
+  gchar        *cache;
+  guint         cache_size;
+  GMutex       *cache_lock;
+  guint         cache_timer_id;
+  guint         cache_watch_id;
+  guint         cache_was_mapped : 1;
+
+  GFileMonitor *cache_monitor;
+  GFile        *cache_file;
+};
+
+
+
+G_DEFINE_DYNAMIC_TYPE (ThunarVfsThumbnailer, 
+                       thunar_vfs_thumbnailer,
+                       TUMBLER_TYPE_ABSTRACT_THUMBNAILER);
+
+
+
+void
+thunar_vfs_thumbnailer_register (TumblerProviderPlugin *plugin)
+{
+  thunar_vfs_thumbnailer_register_type (G_TYPE_MODULE (plugin));
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_class_init (ThunarVfsThumbnailerClass *klass)
+{
+  TumblerAbstractThumbnailerClass *abstractthumbnailer_class;
+  GObjectClass                    *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = thunar_vfs_thumbnailer_finalize;
+
+  abstractthumbnailer_class = TUMBLER_ABSTRACT_THUMBNAILER_CLASS (klass);
+  abstractthumbnailer_class->create = thunar_vfs_thumbnailer_create;
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_class_finalize (ThunarVfsThumbnailerClass *klass)
+{
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_init (ThunarVfsThumbnailer *thumbnailer)
+{
+  gchar *cache_path;
+
+  /* allocate the cache mutex */
+  thumbnailer->cache_lock = g_mutex_new ();
+
+  /* determine the thumbnailers cache file */
+  cache_path = xfce_resource_save_location (XFCE_RESOURCE_CACHE, 
+                                            "Thunar/thumbnailers.cache", FALSE);
+  thumbnailer->cache_file = g_file_new_for_path (cache_path);
+
+  /* monitor the thumbnailers.cache file for changes */
+  thumbnailer->cache_monitor = g_file_monitor (thumbnailer->cache_file, 
+                                               G_FILE_MONITOR_NONE, NULL, NULL);
+  g_signal_connect (thumbnailer->cache_monitor, "changed", 
+                    G_CALLBACK (thunar_vfs_thumbnailer_cache_monitor), thumbnailer);
+
+  /* initially load the thumbnailers.cache file */
+  thunar_vfs_thumbnailer_cache_load (thumbnailer);
+
+  /* schedule a timer to update the thumbnailers.cache every 5 minutes */
+  thumbnailer->cache_timer_id = 
+    g_timeout_add_full (G_PRIORITY_LOW, 5 * 60 * 1000, 
+                        thunar_vfs_thumbnailer_cache_timer, thumbnailer, 
+                        thunar_vfs_thumbnailer_cache_timer_destroy);
+
+  g_free (cache_path);
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_finalize (GObject *object)
+{
+  ThunarVfsThumbnailer *thumbnailer = THUNAR_VFS_THUMBNAILER (object);
+
+  /* be sure to unload the cache file */
+  thunar_vfs_thumbnailer_cache_unload (thumbnailer);
+
+  /* stop any pending cache sources */
+  if (G_LIKELY (thumbnailer->cache_timer_id != 0))
+    g_source_remove (thumbnailer->cache_timer_id);
+  if (G_UNLIKELY (thumbnailer->cache_watch_id != 0))
+    g_source_remove (thumbnailer->cache_watch_id);
+
+  /* unregister from and release the monitor */
+  g_signal_handlers_disconnect_matched (thumbnailer->cache_monitor, G_SIGNAL_MATCH_DATA,
+                                        0, 0, NULL, NULL, thumbnailer);
+  g_object_unref (thumbnailer->cache_monitor);
+
+  /* release the cache lock */
+  g_mutex_free (thumbnailer->cache_lock);
+
+  g_object_unref (thumbnailer->cache_file);
+
+  (*G_OBJECT_CLASS (thunar_vfs_thumbnailer_parent_class)->finalize) (object);
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_cache_load (ThunarVfsThumbnailer *thumbnailer)
+{
+  struct stat statb;
+  gssize      m;
+  gchar      *cache_path;
+  gsize       n;
+  gint        fd;
+
+  g_return_if_fail (IS_THUNAR_VFS_THUMBNAILER (thumbnailer));
+  g_return_if_fail (G_IS_FILE (thumbnailer->cache_file));
+  g_return_if_fail (thumbnailer->cache == NULL);
+
+  cache_path = g_file_get_path (thumbnailer->cache_file);
+
+  /* try to open the thumbnailers.cache file */
+  fd = g_open (cache_path, O_RDONLY, 0000);
+  if (G_LIKELY (fd >= 0))
+    {
+      /* stat the file to get proper size info */
+      if (fstat (fd, &statb) == 0 && statb.st_size >= 16)
+        {
+          /* remember the size of the cache */
+          thumbnailer->cache_size = statb.st_size;
+
+#ifdef HAVE_MMAP
+          /* try to mmap() the file into memory */
+          thumbnailer->cache = mmap (NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+          if (G_LIKELY (thumbnailer->cache != MAP_FAILED))
+            {
+              /* remember that mmap() succeed */
+              thumbnailer->cache_was_mapped = TRUE;
+
+#ifdef HAVE_POSIX_MADVISE
+              /* tell the system that we'll use this buffer quite often */
+              posix_madvise (thumbnailer->cache, statb.st_size, POSIX_MADV_WILLNEED);
+#endif
+            }
+          else
+#endif
+            {
+              /* remember that mmap() failed */
+              thumbnailer->cache_was_mapped = FALSE;
+
+              /* allocate memory for the cache */
+              thumbnailer->cache = g_malloc (statb.st_size);
+
+              /* read the cache file */
+              for (n = 0; n < statb.st_size; n += m)
+                {
+                  /* read the next chunk */
+                  m = read (fd, thumbnailer->cache + n, statb.st_size - n);
+                  if (G_UNLIKELY (m <= 0))
+                    {
+                      /* reset the cache */
+                      g_free (thumbnailer->cache);
+                      thumbnailer->cache = NULL;
+                      break;
+                    }
+                }
+            }
+        }
+
+      /* close the file handle */
+      close (fd);
+    }
+
+  /* check if the cache was loaded successfully */
+  if (G_LIKELY (thumbnailer->cache != NULL))
+    {
+      /* check that we actually support the file version */
+      if (CACHE_READ32 (thumbnailer->cache, 0) != CACHE_MAJOR_VERSION 
+          || CACHE_READ32 (thumbnailer->cache, 4) != CACHE_MINOR_VERSION)
+        {
+          thunar_vfs_thumbnailer_cache_unload (thumbnailer);
+        }
+    }
+  else
+    {
+      /* run the thunar-update-thunar-vfs-thumbnailers-cache-1 utility */
+      thunar_vfs_thumbnailer_cache_update (thumbnailer);
+    }
+
+  /* use the fallback cache if the loading failed */
+  if (G_UNLIKELY (thumbnailer->cache == NULL))
+    {
+      thumbnailer->cache = (gchar *) CACHE_FALLBACK;
+      thumbnailer->cache_size = 16;
+    }
+
+  g_free (cache_path);
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_cache_unload (ThunarVfsThumbnailer *thumbnailer)
+{
+  g_return_if_fail (IS_THUNAR_VFS_THUMBNAILER (thumbnailer));
+  g_return_if_fail (thumbnailer->cache != NULL);
+
+  /* check if any cache is loaded (and not using the fallback cache) */
+  if (thumbnailer->cache != (gchar *) CACHE_FALLBACK)
+    {
+#ifdef HAVE_MMAP
+      /* check if mmap() succeed */
+      if (thumbnailer->cache_was_mapped)
+        {
+          /* just unmap the memory */
+          munmap (thumbnailer->cache, thumbnailer->cache_size);
+        }
+      else
+#endif
+        {
+          /* need to release the memory */
+          g_free (thumbnailer->cache);
+        }
+    }
+
+  /* reset the cache pointer */
+  thumbnailer->cache = NULL;
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_cache_monitor (GFileMonitor      *monitor,
+                                      GFile             *file,
+                                      GFile             *other_file,
+                                      GFileMonitorEvent  event,
+                                      gpointer           user_data)
+{
+  ThunarVfsThumbnailer *thumbnailer = THUNAR_VFS_THUMBNAILER (user_data);
+
+  g_return_if_fail (IS_THUNAR_VFS_THUMBNAILER (thumbnailer));
+  g_return_if_fail (thumbnailer->cache_monitor == monitor);
+  g_return_if_fail (G_IS_FILE_MONITOR (monitor));
+
+  /* check the event */
+  if (G_UNLIKELY (event == G_FILE_MONITOR_EVENT_DELETED))
+    {
+      /* some idiot deleted the cache file, regenerate it */
+      thunar_vfs_thumbnailer_cache_update (thumbnailer);
+    }
+  else
+    {
+      /* the thumbnailers.cache file was changed, reload it */
+      g_mutex_lock (thumbnailer->cache_lock);
+      thunar_vfs_thumbnailer_cache_unload (thumbnailer);
+      thunar_vfs_thumbnailer_cache_load (thumbnailer);
+      g_mutex_unlock (thumbnailer->cache_lock);
+    }
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_cache_update (ThunarVfsThumbnailer *thumbnailer)
+{
+  gchar *argv[2] = { LIBEXECDIR G_DIR_SEPARATOR_S "/thunar-update-thunar-vfs-thumbnailers-cache-1", NULL };
+  GPid   pid;
+
+  g_return_if_fail (IS_THUNAR_VFS_THUMBNAILER (thumbnailer));
+
+  /* check if we're already updating the cache */
+  if (G_LIKELY (thumbnailer->cache_watch_id == 0))
+    {
+      /* try to spawn the command */
+      if (g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL))
+        {
+          /* add a child watch for the updater process */
+          thumbnailer->cache_watch_id = 
+            g_child_watch_add_full (G_PRIORITY_LOW, pid, thunar_vfs_thumbnailer_cache_watch,
+                                    thumbnailer, thunar_vfs_thumbnailer_cache_watch_destroy);
+
+#ifdef HAVE_SETPRIORITY
+          /* decrease the priority of the updater process */
+          setpriority (PRIO_PROCESS, pid, 10);
+#endif
+        }
+    }
+}
+
+
+
+
+static gboolean
+thunar_vfs_thumbnailer_cache_timer (gpointer user_data)
+{
+  /* run the thunar-update-thunar-vfs-thumbnailers-cache-1 utility... */
+  thunar_vfs_thumbnailer_cache_update (THUNAR_VFS_THUMBNAILER (user_data));
+
+  /* ...and keep the timer running */
+  return TRUE;
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_cache_timer_destroy (gpointer user_data)
+{
+  THUNAR_VFS_THUMBNAILER (user_data)->cache_timer_id = 0;
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_cache_watch (GPid     pid,
+                                    gint     status,
+                                    gpointer user_data)
+{
+  ThunarVfsThumbnailer *thumbnailer = THUNAR_VFS_THUMBNAILER (user_data);
+
+  g_return_if_fail (IS_THUNAR_VFS_THUMBNAILER (thumbnailer));
+
+  /* a return value of 33 means that the thumbnailers.cache was updated by the
+   * thunar-update-thunar-vfs-thumbnailers-cache-1 utility and must be reloaded.
+   */
+  if (WIFEXITED (status) && WEXITSTATUS (status) == 33)
+    {
+      /* TODO schedule a "changed" event for the thumbnailers.cache */
+      g_file_monitor_emit_event (thumbnailer->cache_monitor, thumbnailer->cache_file, 
+                                 NULL, G_FILE_MONITOR_EVENT_CHANGED);
+    }
+
+  /* close the PID (win32) */
+  g_spawn_close_pid (pid);
+}
+
+
+
+static void
+thunar_vfs_thumbnailer_cache_watch_destroy (gpointer user_data)
+{
+  THUNAR_VFS_THUMBNAILER (user_data)->cache_watch_id = 0;
+}
+
+
+
+static GdkPixbuf *
+generate_pixbuf (GdkPixbuf              *source,
+                 TumblerThumbnailFlavor *flavor)
+{
+  gdouble    hratio;
+  gdouble    wratio;
+  gint       dest_width;
+  gint       dest_height;
+  gint       source_width;
+  gint       source_height;
+
+  /* determine the source pixbuf dimensions */
+  source_width = gdk_pixbuf_get_width (source);
+  source_height = gdk_pixbuf_get_height (source);
+
+  /* determine the desired size for this flavor */
+  tumbler_thumbnail_flavor_get_size (flavor, &dest_width, &dest_height);
+
+  /* return the same pixbuf if no scaling is required */
+  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 void
+thunar_vfs_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer,
+                               GCancellable               *cancellable,
+                               TumblerFileInfo            *info)
+{
+  TumblerThumbnailFlavor *flavor;
+  GFileInputStream       *stream;
+  TumblerImageData        data;
+  TumblerThumbnail       *thumbnail;
+  const gchar            *uri;
+  GdkPixbuf              *source_pixbuf;
+  GdkPixbuf              *pixbuf;
+  GError                 *error = NULL;
+  GFile                  *file;
+
+  g_return_if_fail (IS_THUNAR_VFS_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);
+
+  /* try to open the source file for reading */
+  file = g_file_new_for_uri (uri);
+  stream = g_file_read (file, NULL, &error);
+  g_object_unref (file);
+
+  if (stream == NULL)
+    {
+      g_signal_emit_by_name (thumbnailer, "error", uri, error->code, error->message);
+      g_error_free (error);
+      return;
+    }
+
+  source_pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), 
+                                              cancellable, &error);
+  g_object_unref (stream);
+
+  if (source_pixbuf == NULL)
+    {
+      g_signal_emit_by_name (thumbnailer, "error", uri, error->code, error->message);
+      g_error_free (error);
+      return;
+    }
+
+  thumbnail = tumbler_file_info_get_thumbnail (info);
+
+  g_assert (thumbnail != NULL);
+
+  /* generate a pixbuf for the thumbnail */
+  flavor = tumbler_thumbnail_get_flavor (thumbnail);
+  pixbuf = generate_pixbuf (source_pixbuf, flavor);
+  g_object_unref (flavor);
+
+  g_assert (pixbuf != NULL);
+
+  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 (thumbnail);
+  g_object_unref (pixbuf);
+  g_object_unref (source_pixbuf);
+}
diff --git a/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer.h b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer.h
new file mode 100644
index 0000000..47de127
--- /dev/null
+++ b/tumbler-plugins/thunar-vfs-thumbnailer/thunar-vfs-thumbnailer.h
@@ -0,0 +1,43 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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 __THUNAR_VFS_THUMBNAILER_H__
+#define __THUNAR_VFS_THUMBNAILER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS;
+
+#define TYPE_THUNAR_VFS_THUMBNAILER            (thunar_vfs_thumbnailer_get_type ())
+#define THUNAR_VFS_THUMBNAILER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_THUNAR_VFS_THUMBNAILER, ThunarVfsThumbnailer))
+#define THUNAR_VFS_THUMBNAILER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_THUNAR_VFS_THUMBNAILER, ThunarVfsThumbnailerClass))
+#define IS_THUNAR_VFS_THUMBNAILER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_THUNAR_VFS_THUMBNAILER))
+#define IS_THUNAR_VFS_THUMBNAILER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_THUNAR_VFS_THUMBNAILER)
+#define THUNAR_VFS_THUMBNAILER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_THUNAR_VFS_THUMBNAILER, ThunarVfsThumbnailerClass))
+
+typedef struct _ThunarVfsThumbnailerClass   ThunarVfsThumbnailerClass;
+typedef struct _ThunarVfsThumbnailer        ThunarVfsThumbnailer;
+
+GType thunar_vfs_thumbnailer_get_type (void) G_GNUC_CONST;
+void  thunar_vfs_thumbnailer_register (TumblerProviderPlugin *plugin);
+
+G_END_DECLS;
+
+#endif /* !__THUNAR_VFS_THUMBNAILER_H__ */



More information about the Xfce4-commits mailing list