diff options
Diffstat (limited to '0002-glocalfileinfo-add-a-dbus-thumbnail-generator.patch')
-rw-r--r-- | 0002-glocalfileinfo-add-a-dbus-thumbnail-generator.patch | 300 |
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 + |