Updating branch refs/heads/jannis/thunar-vfs-thumbnailer to 8e2e0f6f94d5ea57d29f6bb3aa6e35d3dd9955d9 (commit) from 94d0db327df77c2dbfb34622cc6ae3191f76a879 (commit)
commit 8e2e0f6f94d5ea57d29f6bb3aa6e35d3dd9955d9 Author: Jannis Pohlmann <jan...@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 | 53 ++- {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, 993 insertions(+), 23 deletions(-) diff --git a/configure.in.in b/configure.in.in index 8db5cf7..4657081 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 ********************************** @@ -281,6 +287,8 @@ thunar/Makefile thunarx/Makefile thunarx/thunarx-2.pc thunarx/thunarx-config.h +tumbler-plugins/Makefile +tumbler-plugins/thunar-vfs-thumbnailer/Makefile ]) dnl *************************** @@ -290,28 +298,33 @@ 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 "* Generate Documentation: $enable_gen_doc" +echo "* Debug Support: $enable_debug" +echo "* Generate Documentation: $enable_gen_doc" 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 <jan...@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 <jan...@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 <jan...@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 <jan...@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 <jan...@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 <jan...@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__ */ _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits