-
-
Save Dudemanguy/d199759b46a79782cc1b301649dec8a5 to your computer and use it in GitHub Desktop.
Sends a dbus signal for generating thumbnails.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From 26e26aa7db761e3b92177907da26e752a0b8a9cc Mon Sep 17 00:00:00 2001 | |
| From: Dudemanguy <random342@airmail.cc> | |
| Date: Fri, 20 Sep 2024 12:50:10 -0500 | |
| Subject: [PATCH 1/1] glocalfileinfo: add dbus thumbnail generation requests | |
| Send a dbus signal to thumbnailing generators so they can make | |
| thumbnails if needed. | |
| Co-authored-by: ahoka <ahodesuka@users.noreply.github.com> | |
| --- | |
| gio/glocalfileinfo.c | 190 +++++++++++++++++++++++++++++++++++++++++-- | |
| 1 file changed, 181 insertions(+), 9 deletions(-) | |
| diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c | |
| index eea266813..07cc073cd 100644 | |
| --- a/gio/glocalfileinfo.c | |
| +++ b/gio/glocalfileinfo.c | |
| @@ -65,6 +65,12 @@ | |
| #include "glib-unix.h" | |
| #endif | |
| +#ifdef HAVE_DBUS1 | |
| +#include <gio/gdbusproxy.h> | |
| +#include <gio/gio.h> | |
| +#include <glib-object.h> | |
| +#endif /* HAVE_DBUS1 */ | |
| + | |
| #include "glib-private.h" | |
| #include "thumbnail-verify.h" | |
| @@ -102,6 +108,15 @@ | |
| #include "gcontenttypeprivate.h" | |
| #include "glibintl.h" | |
| +#ifdef HAVE_DBUS1 | |
| +typedef struct | |
| +{ | |
| + GMainLoop *mainloop; | |
| + guint32 handle; | |
| + gboolean success; | |
| + const char *error_message; | |
| +} ThumbnailerState; | |
| +#endif /* HAVE_DBUS1 */ | |
| #ifndef G_OS_WIN32 | |
| @@ -1417,18 +1432,145 @@ get_thumbnail_dirname_from_size (ThumbnailSize size) | |
| g_return_val_if_reached (NULL); | |
| } | |
| +#ifdef HAVE_DBUS1 | |
| +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 = NULL; | |
| + GVariant *result = NULL; | |
| + GError *error = NULL; | |
| + gchar *address = 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; | |
| + | |
| + address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, NULL); | |
| + if (!address) | |
| + { | |
| + g_warning ("generate_thumbnail (): g_dbus_address_get_for_bus_sync failed"); | |
| + goto done; | |
| + } | |
| + | |
| + connection = g_dbus_connection_new_for_address_sync ( | |
| + address, | |
| + 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, | |
| + &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 (address) | |
| + g_free (address); | |
| + | |
| + 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 /* HAVE_DBUS1 */ | |
| + | |
| /* @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, | |
| +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; | |
| @@ -1505,6 +1647,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 | |
| { | |
| @@ -1519,9 +1662,26 @@ 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 HAVE_DBUS1 | |
| + 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); | |
| + } | |
| + } | |
| +#endif /* HAVE_DBUS1 */ | |
| + } | |
| + | |
| g_free (basename); | |
| g_free (filename); | |
| g_free (uri); | |
| @@ -1918,6 +2078,16 @@ _g_local_file_info_get (const char *basename, | |
| info = g_file_info_new (); | |
| + /* Thumbnail generation requires a content-type. */ | |
| + 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); | |
| @@ -2056,7 +2226,9 @@ _g_local_file_info_get (const char *basename, | |
| query_icons = _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); | |
| icon_content_type = NULL; | |
| if (query_full_content_type || | |
| @@ -2180,7 +2352,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, | |
| @@ -2190,7 +2362,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, | |
| @@ -2200,7 +2372,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, | |
| @@ -2210,7 +2382,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, | |
| @@ -2220,7 +2392,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.56.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks, I got it to work.
For anyone else struggling to get this patch to work in Portage, or using the meson build system for some other reason, just add this patch as well and it should work: