summarylogtreecommitdiffstats
path: root/0002-glocalfileinfo-add-a-dbus-thumbnail-generator.patch
diff options
context:
space:
mode:
Diffstat (limited to '0002-glocalfileinfo-add-a-dbus-thumbnail-generator.patch')
-rw-r--r--0002-glocalfileinfo-add-a-dbus-thumbnail-generator.patch300
1 files changed, 300 insertions, 0 deletions
diff --git a/0002-glocalfileinfo-add-a-dbus-thumbnail-generator.patch b/0002-glocalfileinfo-add-a-dbus-thumbnail-generator.patch
new file mode 100644
index 000000000000..55167c699d43
--- /dev/null
+++ b/0002-glocalfileinfo-add-a-dbus-thumbnail-generator.patch
@@ -0,0 +1,300 @@
+From 01ce72fb8086fb6984e4409739a821408045612e Mon Sep 17 00:00:00 2001
+From: Dudemanguy <random342@airmail.cc>
+Date: Sat, 24 Feb 2024 15:07:31 -0600
+Subject: [PATCH] glocalfileinfo: add a dbus thumbnail generator
+
+---
+ gio/glocalfileinfo.c | 186 +++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 179 insertions(+), 7 deletions(-)
+
+diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
+index 4f51427f5..5e1698da0 100644
+--- a/gio/glocalfileinfo.c
++++ b/gio/glocalfileinfo.c
+@@ -68,6 +68,12 @@
+ #include "glib-private.h"
+
+ #include "thumbnail-verify.h"
++#ifdef HAVE_DBUS1
++#define FREEDESKTOP_THUMBNAILER
++#include <gio/gio.h>
++#include <gio/gdbusproxy.h>
++#include <glib-object.h>
++#endif /* HAVE_DBUS1 */
+
+ #ifdef G_OS_WIN32
+ #include <windows.h>
+@@ -109,6 +115,16 @@ struct ThumbMD5Context {
+ unsigned char in[64];
+ };
+
++#ifdef FREEDESKTOP_THUMBNAILER
++typedef struct
++{
++ GMainLoop *mainloop;
++ guint32 handle;
++ gboolean success;
++ const char *error_message;
++} ThumbnailerState;
++#endif /* FREEDESKTOP_THUMBNAILER */
++
+ #ifndef G_OS_WIN32
+
+ typedef struct {
+@@ -1419,18 +1435,137 @@ get_thumbnail_dirname_from_size (ThumbnailSize size)
+ g_return_val_if_reached (NULL);
+ }
+
++#ifdef FREEDESKTOP_THUMBNAILER
++static void
++thumbnailer_signal_cb (GDBusProxy *proxy,
++ gchar *sender_name,
++ gchar *signal_name,
++ GVariant *parameters,
++ gpointer thumbnailer_state)
++{
++ ThumbnailerState *state = (ThumbnailerState *) thumbnailer_state;
++ guint32 signal_handle;
++ const gchar **uris;
++
++
++ if (g_strcmp0 (signal_name, "Error") == 0)
++ {
++ g_variant_get (parameters, "(uasis)", &signal_handle, NULL, NULL, &state->error_message);
++ state->success = FALSE;
++ }
++ else if (g_strcmp0 (signal_name, "Ready") == 0)
++ {
++ g_variant_get (parameters, "(u^as)", &signal_handle, &uris);
++ state->success = TRUE;
++ }
++ else if (g_strcmp0 (signal_name, "Finished") == 0)
++ {
++ g_main_loop_quit (state->mainloop);
++ }
++
++}
++
++static gboolean
++generate_thumbnail(const char *uri, const char *mime_type)
++{
++ GMainContext *thread_context;
++ GDBusConnection *connection;
++ GDBusProxy *proxy;
++ GVariant *result = NULL;
++ GError *error = NULL;
++ ThumbnailerState state;
++ const gchar *uris[2] = { uri, NULL };
++ const gchar *mime_types[2] = { mime_type, NULL };
++
++ thread_context = g_main_context_new ();
++ state.mainloop = g_main_loop_new (thread_context, FALSE);
++ state.success = FALSE;
++
++ connection = g_dbus_connection_new_for_address_sync (
++ g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, NULL),
++ G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION | G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
++ NULL,
++ NULL,
++ &error);
++
++ g_main_context_push_thread_default (thread_context);
++ proxy = g_dbus_proxy_new_sync (connection,
++ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
++ NULL,
++ "org.freedesktop.thumbnails.Thumbnailer1",
++ "/org/freedesktop/thumbnails/Thumbnailer1",
++ "org.freedesktop.thumbnails.Thumbnailer1",
++ NULL, /* TODO: cancellable */
++ &error);
++ if (!proxy)
++ {
++ g_warning ("generate_thumbnail (): g_dbus_proxy_new_sync failed");
++ goto done;
++ }
++ else
++ g_debug("generate_thumbnail (): connected to D-Bus");
++
++ g_signal_connect (G_OBJECT (proxy), "g-signal",
++ G_CALLBACK (thumbnailer_signal_cb), &state);
++
++ result = g_dbus_proxy_call_sync (proxy,
++ "Queue",
++ g_variant_new("(^as^asssu)",
++ uris,
++ mime_types,
++ "normal",
++ "default",
++ 0),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ &error);
++ if (!result || error)
++ {
++ g_warning ("generate_thumbnail (): g_dbus_proxy_call_sync() failed: %s", error->message);
++ goto done;
++ }
++ g_variant_get (result, "(u)", &(state.handle));
++ g_variant_unref (result);
++ // block until the loop is terminated in thumbnailer_signal_cb ()
++ g_main_loop_run (state.mainloop);
++
++done:
++ if (proxy)
++ g_object_unref (proxy);
++
++ if (connection)
++ g_object_unref (connection);
++
++ g_main_loop_unref (state.mainloop);
++ g_main_context_pop_thread_default (thread_context);
++ g_main_context_unref (thread_context);
++
++ if (state.success)
++ {
++ g_debug ("generate_thumbnail (): Thumbnail generated for %s", uris[0]);
++ return TRUE;
++ }
++ else
++ return FALSE;
++}
++#endif /* FREEDESKTOP_THUMBNAILER */
++
++
+ /* @stat_buf is the pre-calculated result of stat(path), or %NULL if that failed. */
+ static void
+ get_thumbnail_attributes (const char *path,
+ GFileInfo *info,
+ const GLocalFileStat *stat_buf,
+- ThumbnailSize size)
++ ThumbnailSize size,
++ gboolean generate)
+ {
+ GChecksum *checksum;
+ const char *dirname;
+ char *uri;
+ char *filename = NULL;
+ char *basename;
++ const char *content_type;
+ guint32 failed_attr_id;
+ guint32 is_valid_attr_id;
+ guint32 path_attr_id;
+@@ -1507,6 +1642,7 @@ get_thumbnail_attributes (const char *path,
+ _g_file_info_set_attribute_byte_string_by_id (info, path_attr_id, filename);
+ _g_file_info_set_attribute_boolean_by_id (info, is_valid_attr_id,
+ thumbnail_verify (filename, uri, stat_buf));
++ generate = FALSE;
+ }
+ else
+ {
+@@ -1521,9 +1657,31 @@ get_thumbnail_attributes (const char *path,
+ _g_file_info_set_attribute_boolean_by_id (info, failed_attr_id, TRUE);
+ _g_file_info_set_attribute_boolean_by_id (info, is_valid_attr_id,
+ thumbnail_verify (filename, uri, stat_buf));
++ generate = FALSE;
+ }
+ }
+
++ if (generate)
++ {
++#ifdef FREEDESKTOP_THUMBNAILER
++ content_type = g_file_info_get_content_type (info);
++ if (content_type)
++ {
++ g_debug ("invoking Freedesktop Thumbnailer for %s (%s)", uri, content_type);
++ if (generate_thumbnail (uri, content_type))
++ {
++ /* Now that the thumbnail is generated, find it. */
++ get_thumbnail_attributes (path, info, stat_buf, size, FALSE);
++ }
++ /*else
++ {
++ _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED, TRUE);
++ _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID, FALSE);
++ }*/
++ }
++#endif /* FREEDESKTOP_THUMBNAILER */
++ }
++
+ g_free (basename);
+ g_free (filename);
+ g_free (uri);
+@@ -1914,6 +2072,18 @@ _g_local_file_info_get (const char *basename,
+
+ info = g_file_info_new ();
+
++ /* Thumbnail generation requires a content-type.
++ * TODO: implement g_file_attribute_matcher_add () in gfileinfo.c */
++ if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH)
++ && !_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE))
++ {
++ char *attributes = g_file_attribute_matcher_to_string (attribute_matcher);
++ char *_attributes = g_strdup_printf ("%s,standard::content-type", attributes);
++ attribute_matcher = g_file_attribute_matcher_new (_attributes);
++ g_free (attributes);
++ g_free (_attributes);
++ }
++
+ /* Make sure we don't set any unwanted attributes */
+ g_file_info_set_attribute_mask (info, attribute_matcher);
+
+@@ -2049,7 +2219,9 @@ _g_local_file_info_get (const char *basename,
+ _g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_STANDARD_ICON) ||
+ _g_file_attribute_matcher_matches_id (attribute_matcher,
+- G_FILE_ATTRIBUTE_ID_STANDARD_SYMBOLIC_ICON))
++ G_FILE_ATTRIBUTE_ID_STANDARD_SYMBOLIC_ICON) ||
++ _g_file_attribute_matcher_matches_id (attribute_matcher,
++ G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH))
+ {
+ char *content_type = get_content_type (basename, path, stat_ok ? &statbuf : NULL, is_symlink, symlink_broken, flags, FALSE);
+
+@@ -2165,7 +2337,7 @@ _g_local_file_info_get (const char *basename,
+ _g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED))
+ {
+- get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_AUTO);
++ get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_AUTO, TRUE);
+ }
+
+ if (_g_file_attribute_matcher_matches_id (attribute_matcher,
+@@ -2175,7 +2347,7 @@ _g_local_file_info_get (const char *basename,
+ _g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_NORMAL))
+ {
+- get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_NORMAL);
++ get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_NORMAL, TRUE);
+ }
+
+ if (_g_file_attribute_matcher_matches_id (attribute_matcher,
+@@ -2185,7 +2357,7 @@ _g_local_file_info_get (const char *basename,
+ _g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_LARGE))
+ {
+- get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_LARGE);
++ get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_LARGE, TRUE);
+ }
+
+ if (_g_file_attribute_matcher_matches_id (attribute_matcher,
+@@ -2195,7 +2367,7 @@ _g_local_file_info_get (const char *basename,
+ _g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_XLARGE))
+ {
+- get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_XLARGE);
++ get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_XLARGE, TRUE);
+ }
+
+ if (_g_file_attribute_matcher_matches_id (attribute_matcher,
+@@ -2205,7 +2377,7 @@ _g_local_file_info_get (const char *basename,
+ _g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_XXLARGE))
+ {
+- get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_XXLARGE);
++ get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_XXLARGE, TRUE);
+ }
+
+ vfs = g_vfs_get_default ();
+--
+2.43.2
+