[Xfce4-commits] [xfce/tumbler] 02/06: Load and register in tumbler a list of thumbnailers read from XDG_DATA_DIRS/thumbnailers. These "desktop" thumbnailers should have *.thumbnailer as a desktop file name and [Thumbnailer Entry] for MimeType and Exec.
noreply at xfce.org
noreply at xfce.org
Sun May 28 11:20:18 CEST 2017
This is an automated email from the git hooks/post-receive script.
a l i p u s h e d a c o m m i t t o b r a n c h m a s t e r
in repository xfce/tumbler.
commit b390c588b30ef388601640fc3853bce0eb3d8a05
Author: Ali Abdallah <aliovx at gmail.com>
Date: Sat May 27 20:26:56 2017 +0200
Load and register in tumbler a list of thumbnailers read from XDG_DATA_DIRS/thumbnailers. These "desktop" thumbnailers should have *.thumbnailer as a desktop file name and [Thumbnailer Entry] for MimeType and Exec.
---
.../desktop-thumbnailer-provider.c | 166 ++++++++--
plugins/desktop-thumbnailer/desktop-thumbnailer.c | 335 ++++++++++++++++++++-
2 files changed, 471 insertions(+), 30 deletions(-)
diff --git a/plugins/desktop-thumbnailer/desktop-thumbnailer-provider.c b/plugins/desktop-thumbnailer/desktop-thumbnailer-provider.c
index 8ea95c2..4a4e40f 100644
--- a/plugins/desktop-thumbnailer/desktop-thumbnailer-provider.c
+++ b/plugins/desktop-thumbnailer/desktop-thumbnailer-provider.c
@@ -24,6 +24,7 @@
#include <glib.h>
#include <glib-object.h>
+#include <glib/gi18n.h>
#include <tumbler/tumbler.h>
@@ -93,31 +94,162 @@ desktop_thumbnailer_provider_init (DesktopThumbnailerProvider *provider)
{
}
+static DesktopThumbnailer *
+desktop_thumbnailer_get_from_desktop_file (GFile *file,
+ GStrv uri_schemes)
+{
+ DesktopThumbnailer *thumbnailer;
+ GKeyFile *key_file;
+ GError *error = NULL;
+ gchar *filename;
+ gchar *exec;
+ gchar **mime_types;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+ /* determine the absolute filename of the input file */
+ filename = g_file_get_path (file);
+
+ /* allocate a new key file object */
+ key_file = g_key_file_new ();
+
+ /* try to load the key file data from the input file */
+ if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &error))
+ {
+ g_warning (_("Failed to load the file \"%s\": %s"), filename, error->message);
+ g_clear_error (&error);
+
+ g_key_file_free (key_file);
+ g_free (filename);
+
+ return NULL;
+ }
+
+ /* determine the Exec of the desktop thumbnailer */
+ exec = g_key_file_get_string (key_file, "Thumbnailer Entry",
+ "Exec", &error);
+ if (exec == NULL)
+ {
+ g_warning (_("Malformed file \"%s\": %s"), filename, error->message);
+ g_clear_error (&error);
+
+ g_key_file_free (key_file);
+ g_free (filename);
+
+ return NULL;
+ }
+
+ /* determine the MIME types supported by this thumbnailer */
+ mime_types = g_key_file_get_string_list (key_file, "Thumbnailer Entry",
+ "MimeType", NULL, &error);
+ if (mime_types == NULL)
+ {
+ g_warning (_("Malformed file \"%s\": %s"), filename, error->message);
+ g_clear_error (&error);
+
+ g_free (exec);
+ g_key_file_free (key_file);
+ g_free (filename);
+
+ return NULL;
+ }
+
+ thumbnailer = g_object_new (TYPE_DESKTOP_THUMBNAILER,
+ "uri-schemes", uri_schemes,
+ "mime-types", mime_types,
+ "exec", exec,
+ NULL);
+ g_key_file_free (key_file);
+ g_strfreev(mime_types);
+
+ g_print("Registered thumbailer %s\n", exec);
+ g_free(exec);
+ return thumbnailer;
+}
+
+static GList *
+desktop_thumbnailer_get_thumbnailers_from_dir (GList *thumbnailers,
+ GFile *directory,
+ GStrv uri_schemes)
+{
+ const gchar *base_name;
+ gchar *dirname;
+ GDir *dir;
+
+ /* determine the absolute path to the directory */
+ dirname = g_file_get_path (directory);
+
+ /* try to open the directory for reading */
+ dir = g_dir_open (dirname, 0, NULL);
+ if (dir == NULL)
+ {
+ g_free (dirname);
+ return thumbnailers;
+ }
+
+ /* iterate over all files in the directory */
+ for (base_name = g_dir_read_name (dir);
+ base_name != NULL;
+ base_name = g_dir_read_name (dir))
+ {
+ GFileType type;
+ GFile *file;
+ DesktopThumbnailer *thumbnailer = NULL;
+
+ /* skip files that don't end with the .thumbnailer extension */
+ if (!g_str_has_suffix (base_name, ".thumbnailer"))
+ continue;
+
+ file = g_file_get_child (directory, base_name);
+ type = g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL);
+
+ /* try to load the file if it is regular */
+ if (type == G_FILE_TYPE_REGULAR)
+ thumbnailer = desktop_thumbnailer_get_from_desktop_file (file, uri_schemes);
+
+ g_object_unref (file);
+
+ if (thumbnailer)
+ {
+ thumbnailers = g_list_append (thumbnailers, thumbnailer);
+ }
+ }
+ return thumbnailers;
+}
static GList *
desktop_thumbnailer_provider_get_thumbnailers (TumblerThumbnailerProvider *provider)
{
- /* This list is mainly from Totem. Generating a list from
- * GStreamer isn't realistic, so we have to hardcode it. */
- /* See https://git.gnome.org/browse/totem/tree/data/mime-type-list.txt */
- static const char *mime_types[] = {
- "dummy",
- NULL
- };
-
- DesktopThumbnailer *thumbnailer;
- GError *error = NULL;
- GStrv uri_schemes;
+ const gchar *const *data_dirs;
+ gchar *dirname;
+ GStrv uri_schemes;
+ GList *iter;
+ int n;
+ GList *thumbnailers = NULL;
+ GList *directories = NULL;
uri_schemes = tumbler_util_get_supported_uri_schemes ();
- thumbnailer = g_object_new (TYPE_DESKTOP_THUMBNAILER,
- "uri-schemes", uri_schemes,
- "mime-types", mime_types,
- NULL);
+ /* build $XDG_DATA_DIRS/thumbnailers dirnames and prepend them to the list */
+ data_dirs = g_get_system_data_dirs ();
- g_strfreev (uri_schemes);
+ for (n = 0; data_dirs[n] != NULL; ++n)
+ {
+ dirname = g_build_filename (data_dirs[n], "thumbnailers", NULL);
+ directories = g_list_prepend (directories, g_file_new_for_path (dirname));
+ g_free (dirname);
+ }
+
+ /* reverse the directory list so that the directories with highest
+ * priority come first */
+ directories = g_list_reverse (directories);
- return g_list_append (NULL, thumbnailer);
+ for (iter = directories; iter != NULL; iter = iter->next)
+ {
+ thumbnailers = desktop_thumbnailer_get_thumbnailers_from_dir (thumbnailers, iter->data, uri_schemes);
+ }
+
+ g_strfreev (uri_schemes);
+ return thumbnailers;
}
diff --git a/plugins/desktop-thumbnailer/desktop-thumbnailer.c b/plugins/desktop-thumbnailer/desktop-thumbnailer.c
index 7f025fe..bc8e912 100644
--- a/plugins/desktop-thumbnailer/desktop-thumbnailer.c
+++ b/plugins/desktop-thumbnailer/desktop-thumbnailer.c
@@ -1,3 +1,4 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
/*
* Copyright (c) 2017 Ali Abdallah <ali at xfce.org>
*
@@ -30,7 +31,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gio/gio.h>
-
+#include <glib/gstdio.h>
#include <tumbler/tumbler.h>
@@ -39,8 +40,20 @@
static void desktop_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer,
- GCancellable *cancellable,
- TumblerFileInfo *info);
+ GCancellable *cancellable,
+ TumblerFileInfo *info);
+
+static void desktop_thumbnailer_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void desktop_thumbnailer_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void desktop_thumbnailer_finalize(GObject *object);
@@ -52,6 +65,8 @@ struct _DesktopThumbnailerClass
struct _DesktopThumbnailer
{
TumblerAbstractThumbnailer __parent__;
+
+ gchar *exec;
};
@@ -61,6 +76,13 @@ G_DEFINE_DYNAMIC_TYPE (DesktopThumbnailer,
TUMBLER_TYPE_ABSTRACT_THUMBNAILER);
+enum
+{
+ PROP_0,
+ PROP_EXEC
+};
+
+
void
desktop_thumbnailer_register (TumblerProviderPlugin *plugin)
@@ -70,11 +92,69 @@ desktop_thumbnailer_register (TumblerProviderPlugin *plugin)
+static void desktop_thumbnailer_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ DesktopThumbnailer *thumbnailer = DESKTOP_THUMBNAILER(object);
+
+ switch(prop_id)
+ {
+ case PROP_EXEC:
+ g_value_set_string(value, thumbnailer->exec);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void desktop_thumbnailer_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ DesktopThumbnailer *thumbnailer = DESKTOP_THUMBNAILER(object);
+
+ switch(prop_id)
+ {
+ case PROP_EXEC:
+ thumbnailer->exec = g_strdup(g_value_get_string(value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
static void
desktop_thumbnailer_class_init (DesktopThumbnailerClass *klass)
{
TumblerAbstractThumbnailerClass *abstractthumbnailer_class;
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS(klass);
+ gobject_class->get_property = desktop_thumbnailer_get_property;
+ gobject_class->set_property = desktop_thumbnailer_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_EXEC,
+ g_param_spec_string("exec",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE));
+
+ gobject_class->finalize = desktop_thumbnailer_finalize;
abstractthumbnailer_class = TUMBLER_ABSTRACT_THUMBNAILER_CLASS (klass);
abstractthumbnailer_class->create = desktop_thumbnailer_create;
}
@@ -87,6 +167,11 @@ desktop_thumbnailer_class_finalize (DesktopThumbnailerClass *klass)
}
+static void
+desktop_thumbnailer_finalize(GObject *object)
+{
+
+}
static void
desktop_thumbnailer_init (DesktopThumbnailer *thumbnailer)
@@ -95,17 +180,225 @@ desktop_thumbnailer_init (DesktopThumbnailer *thumbnailer)
static void
+te_string_append_quoted (GString *string,
+ const gchar *unquoted)
+{
+ gchar *quoted;
+
+ quoted = g_shell_quote (unquoted);
+ g_string_append (string, quoted);
+ g_free (quoted);
+}
+
+
+
+static GdkPixbuf *
+desktop_thumbnailer_get_pixbuf (GInputStream *stream,
+ int dest_width,
+ int dest_height,
+ GCancellable *cancellable)
+{
+ GdkPixbuf *source;
+ gdouble hratio;
+ gdouble wratio;
+ gint source_width;
+ gint source_height;
+ GError *error = NULL;
+
+ source = gdk_pixbuf_new_from_stream (stream, cancellable, &error);
+
+ if (!source)
+ {
+ g_clear_error (&error);
+ g_print("Failed to load pixbuf");
+ return NULL;
+ }
+
+ /* determine the source pixbuf dimensions */
+ source_width = gdk_pixbuf_get_width (source);
+ source_height = gdk_pixbuf_get_height (source);
+
+
+ /* 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 gboolean
+desktop_thumbnailer_exec_parse (const gchar *exec,
+ const gchar *file_path,
+ const gchar *file_uri,
+ gint desired_size,
+ const gchar *output_file,
+ gint *argc,
+ gchar ***argv,
+ GError **error)
+{
+ const gchar *p;
+ gboolean result = FALSE;
+ GString *command_line = g_string_new (NULL);
+
+ for (p = exec; *p != '\0'; ++p)
+ {
+ if (p[0] == '%' && p[1] != '\0')
+ {
+ switch (*++p)
+ {
+ case 'u':
+ if (G_LIKELY (file_uri != NULL))
+ te_string_append_quoted (command_line, file_uri);
+ break;
+
+ case 'i':
+ if (G_LIKELY (file_path != NULL))
+ te_string_append_quoted (command_line, file_path);
+ break;
+
+ case 's':
+ g_string_append_printf(command_line, "%d", desired_size);
+ break;
+
+ case 'o':
+ if (G_LIKELY (output_file != NULL))
+ te_string_append_quoted (command_line, output_file);
+ break;
+
+ case '%':
+ g_string_append_c (command_line, '%');
+ break;
+ }
+ }
+ else
+ {
+ g_string_append_c (command_line, *p);
+ }
+ }
+
+ result = g_shell_parse_argv (command_line->str, argc, argv, error);
+
+ g_string_free (command_line, TRUE);
+ return result;
+}
+
+
+
+static GdkPixbuf *
+desktop_thumbnailer_load_thumbnail (DesktopThumbnailer *thumbnailer,
+ const gchar *uri,
+ const gchar *path,
+ gint width,
+ gint height,
+ GCancellable *cancellable)
+{
+ GFileIOStream *stream;
+ GFile *tmpfile;
+ gchar *exec;
+ gchar **cmd_argv;
+ gchar *tmpfilepath;
+ gboolean res;
+ gint cmd_argc;
+ gint size;
+ gchar *working_directory = NULL;
+ GdkPixbuf *pixbuf = NULL;
+ GError *error = NULL;
+
+ g_object_get (G_OBJECT (thumbnailer), "exec", &exec, NULL);
+
+ tmpfile = g_file_new_tmp ("tumbler-XXXXXXX.png", &stream, NULL);
+
+ if ( G_LIKELY (tmpfile) )
+ {
+ tmpfilepath = g_file_get_path (tmpfile);
+
+ size = MIN (width, height);
+
+ res = desktop_thumbnailer_exec_parse (exec,
+ path,
+ uri,
+ size,
+ tmpfilepath,
+ &cmd_argc,
+ &cmd_argv,
+ &error);
+
+ if (G_LIKELY (res))
+ {
+ working_directory = g_path_get_dirname (path);
+
+
+ res = g_spawn_sync (working_directory,
+ cmd_argv, NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL,
+ NULL, NULL,
+ NULL,
+ &error);
+
+ if (G_LIKELY (res))
+ {
+ pixbuf = desktop_thumbnailer_get_pixbuf (g_io_stream_get_input_stream(G_IO_STREAM(stream)),
+ width,
+ height,
+ cancellable);
+ g_unlink (tmpfilepath);
+ }
+
+ g_free (working_directory);
+ g_strfreev (cmd_argv);
+ }
+ else
+ {
+ g_warning (_("Malformed command line \"%s\": %s"), exec, error->message);
+ g_clear_error (&error);
+ }
+ g_free (tmpfilepath);
+ g_object_unref (tmpfile);
+ g_object_unref (stream);
+ }
+
+ g_free (exec);
+
+ return pixbuf;
+}
+
+
+
+static void
desktop_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer,
- GCancellable *cancellable,
- TumblerFileInfo *info)
+ GCancellable *cancellable,
+ TumblerFileInfo *info)
{
- TumblerThumbnail *thumbnail;
- const gchar *uri;
- GFile *file;
- GError *error = NULL;
- gchar *path;
- GdkPixbuf *pixbuf = NULL;
- TumblerImageData data;
+
+ TumblerThumbnail *thumbnail;
+ TumblerThumbnailFlavor *flavor;
+ TumblerImageData data;
+ const gchar *uri;
+ gchar *path;
+ GFile *file;
+ gint height;
+ gint width;
+ GError *error = NULL;
+ GdkPixbuf *pixbuf = NULL;
+
+ g_print("Debug \n");
g_return_if_fail (IS_DESKTOP_THUMBNAILER (thumbnailer));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
@@ -116,13 +409,23 @@ desktop_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer,
return;
uri = tumbler_file_info_get_uri (info);
- file = g_file_new_for_uri (uri);
+ file = g_file_new_for_uri (uri);
+ path = g_file_get_path (file);
thumbnail = tumbler_file_info_get_thumbnail (info);
+ g_assert (thumbnail != NULL);
+
+ flavor = tumbler_thumbnail_get_flavor (thumbnail);
+ g_assert (flavor != NULL);
+
+ tumbler_thumbnail_flavor_get_size (flavor, &width, &height);
+
+ pixbuf = desktop_thumbnailer_load_thumbnail (DESKTOP_THUMBNAILER(thumbnailer), uri, path, width, height, cancellable);
if (pixbuf != NULL)
{
+ g_print("Yay pixbuff != NULL\n");
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);
@@ -137,6 +440,8 @@ desktop_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer,
g_object_unref (pixbuf);
}
+ else
+ g_print(":(\n");
if (error != NULL)
{
@@ -148,5 +453,9 @@ desktop_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer,
g_signal_emit_by_name (thumbnailer, "ready", uri);
}
+ g_free (path);
+
g_object_unref (thumbnail);
+ g_object_unref (flavor);
+ g_object_unref (file);
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the Xfce4-commits
mailing list