int main (int argc, char **argv) { GdkPixbuf *pixbuf; GnomeDesktopThumbnailFactory *factory; GtkWidget *window, *image; char *content_type; gtk_init (&argc, &argv); if (argc < 2) { g_print ("Usage: %s FILE...\n", argv[0]); return 1; } content_type = g_content_type_guess (argv[1], NULL, 0, NULL); factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE); pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, argv[1], content_type); g_free (content_type); if (pixbuf == NULL) { g_warning ("gnome_desktop_thumbnail_factory_generate_thumbnail() failed to generate a thumbnail for %s", argv[1]); return 1; } window = gtk_window_new (GTK_WINDOW_TOPLEVEL); image = gtk_image_new_from_pixbuf (pixbuf); gtk_container_add (GTK_CONTAINER (window), image); gtk_widget_show_all (window); gtk_main (); return 0; }
static gboolean create_thumbnail (GIOSchedulerJob *job, GCancellable *cancellable, gpointer user_data) { GSimpleAsyncResult *result = user_data; GFile *file = G_FILE (g_async_result_get_source_object (G_ASYNC_RESULT (result))); GnomeDesktopThumbnailFactory *factory; GFileInfo *info; gchar *uri; GdkPixbuf *pixbuf; guint64 mtime; uri = g_file_get_uri (file); info = g_file_query_info (file, ATTRIBUTES_FOR_THUMBNAIL, G_FILE_QUERY_INFO_NONE, NULL, NULL); /* we don't care about reporting errors here, just fail the * thumbnail. */ if (info == NULL) { g_simple_async_result_set_op_res_gboolean (result, FALSE); goto out; } mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL); pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, uri, g_file_info_get_content_type (info)); if (pixbuf != NULL) { gnome_desktop_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, (time_t) mtime); g_simple_async_result_set_op_res_gboolean (result, TRUE); } else { g_simple_async_result_set_op_res_gboolean (result, FALSE); } g_object_unref (info); g_object_unref (file); g_object_unref (factory); g_clear_object (&pixbuf); out: g_simple_async_result_complete_in_idle (result); g_object_unref (result); return FALSE; }
static void update_preview (GtkFileChooser *chooser, GnomeDesktopThumbnailFactory *thumb_factory) { gchar *uri; uri = gtk_file_chooser_get_preview_uri (chooser); if (uri) { GdkPixbuf *pixbuf = NULL; const gchar *mime_type = NULL; GFile *file; GFileInfo *file_info; GtkWidget *preview; preview = gtk_file_chooser_get_preview_widget (chooser); file = g_file_new_for_uri (uri); file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_object_unref (file); if (file_info != NULL) { mime_type = g_file_info_get_content_type (file_info); g_object_unref (file_info); } if (mime_type) { pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumb_factory, uri, mime_type); } gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT, (pixbuf != NULL)); if (pixbuf != NULL) { gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf); g_object_unref (pixbuf); } else { gtk_image_set_from_stock (GTK_IMAGE (preview), GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); } g_free (uri); } gtk_file_chooser_set_preview_widget_active (chooser, TRUE); }
/** * e_icon_factory_create_thumbnail * @filename: the file name to create the thumbnail for * * Creates system thumbnail for @filename. * * Returns: Path to system thumbnail of the file; %NULL if couldn't * create it. Free it with g_free(). **/ gchar * e_icon_factory_create_thumbnail (const gchar *filename) { #ifdef HAVE_GNOME_DESKTOP static GnomeDesktopThumbnailFactory *thumbnail_factory = NULL; struct stat file_stat; gchar *thumbnail = NULL; g_return_val_if_fail (filename != NULL, NULL); if (thumbnail_factory == NULL) { thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL); } if (g_stat (filename, &file_stat) != -1 && S_ISREG (file_stat.st_mode)) { gchar *content_type, *mime = NULL; gboolean uncertain = FALSE; content_type = g_content_type_guess (filename, NULL, 0, &uncertain); if (content_type) mime = g_content_type_get_mime_type (content_type); if (mime) { gchar *uri = g_filename_to_uri (filename, NULL, NULL); g_return_val_if_fail (uri != NULL, NULL); thumbnail = gnome_desktop_thumbnail_factory_lookup (thumbnail_factory, uri, file_stat.st_mtime); if (!thumbnail && gnome_desktop_thumbnail_factory_can_thumbnail (thumbnail_factory, uri, mime, file_stat.st_mtime)) { GdkPixbuf *pixbuf; pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory, uri, mime); if (pixbuf) { gnome_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory, pixbuf, uri, file_stat.st_mtime); g_object_unref (pixbuf); thumbnail = gnome_desktop_thumbnail_factory_lookup (thumbnail_factory, uri, file_stat.st_mtime); } } g_free (uri); } g_free (content_type); g_free (mime); } return thumbnail; #else return NULL; #endif /* HAVE_GNOME_DESKTOP */ }
static GdkPixbuf * impl_load_thumbnail (StTextureCache *cache, const char *uri, const char *mime_type, guint size, GError **error) { GnomeDesktopThumbnailFactory *thumbnail_factory; GdkPixbuf *pixbuf = NULL; GFile *file; GFileInfo *file_info; GTimeVal mtime_g; time_t mtime = 0; char *existing_thumbnail; file = g_file_new_for_uri (uri); file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_object_unref (file); if (file_info) { g_file_info_get_modification_time (file_info, &mtime_g); g_object_unref (file_info); mtime = (time_t) mtime_g.tv_sec; } thumbnail_factory = cache->priv->thumbnails; existing_thumbnail = gnome_desktop_thumbnail_factory_lookup (thumbnail_factory, uri, mtime); if (existing_thumbnail != NULL) { pixbuf = gdk_pixbuf_new_from_file_at_size (existing_thumbnail, size, size, error); g_free (existing_thumbnail); } else if (gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (thumbnail_factory, uri, mtime)) g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Has failed thumbnail"); else if (gnome_desktop_thumbnail_factory_can_thumbnail (thumbnail_factory, uri, mime_type, mtime)) { pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory, uri, mime_type); if (pixbuf) { // we need to save the thumbnail so that we don't need to generate it again in the future gnome_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory, pixbuf, uri, mtime); } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to generate thumbnail"); gnome_desktop_thumbnail_factory_create_failed_thumbnail (thumbnail_factory, uri, mtime); } } return pixbuf; }
static void create_thumbnail (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { GFile *file = G_FILE (source_object); GnomeDesktopThumbnailFactory *factory = NULL; GError *error = NULL; GFileInfo *info = NULL; gchar *uri = NULL; GdkPixbuf *pixbuf = NULL; guint64 mtime; uri = g_file_get_uri (file); info = g_file_query_info (file, ATTRIBUTES_FOR_THUMBNAIL, G_FILE_QUERY_INFO_NONE, NULL, &error); if (info == NULL) { g_task_return_error (task, error); goto out; } mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE); pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, uri, g_file_info_get_content_type (info)); if (pixbuf == NULL) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "GnomeDesktopThumbnailFactory failed"); goto out; } gnome_desktop_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, (time_t) mtime); g_task_return_boolean (task, TRUE); out: g_clear_object (&info); g_clear_object (&factory); g_clear_object (&pixbuf); g_free (uri); }
static GdkPixbuf * create_thumbnail (LoadThumbnailData *data) { GFile *file = data->font_file; GnomeDesktopThumbnailFactory *factory; gchar *uri; guint64 mtime; GdkPixbuf *pixbuf = NULL; GFileInfo *info = NULL; uri = g_file_get_uri (file); info = g_file_query_info (file, ATTRIBUTES_FOR_CREATING_THUMBNAIL, G_FILE_QUERY_INFO_NONE, NULL, NULL); /* we don't care about reporting errors here, just fail the * thumbnail. */ if (info == NULL) goto out; mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL); pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, uri, g_file_info_get_content_type (info)); if (pixbuf != NULL) gnome_desktop_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, (time_t) mtime); else gnome_desktop_thumbnail_factory_create_failed_thumbnail (factory, uri, (time_t) mtime); g_object_unref (factory); out: g_clear_object (&info); return pixbuf; }
gboolean photos_utils_create_thumbnail (GFile *file, GCancellable *cancellable, GError **error) { GnomeDesktopThumbnailFactory *factory = NULL; GFileInfo *info = NULL; const gchar *attributes = G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","G_FILE_ATTRIBUTE_TIME_MODIFIED; gboolean ret_val = FALSE; gchar *uri = NULL; GdkPixbuf *pixbuf = NULL; guint64 mtime; uri = g_file_get_uri (file); info = g_file_query_info (file, attributes, G_FILE_QUERY_INFO_NONE, cancellable, error); if (info == NULL) goto out; mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE); pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, uri, g_file_info_get_content_type (info)); if (pixbuf == NULL) { /* FIXME: use proper #defines and enumerated types */ g_set_error (error, g_quark_from_static_string ("gnome-desktop-error"), 0, "GnomeDesktopThumbnailFactory failed"); goto out; } gnome_desktop_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, (time_t) mtime); ret_val = TRUE; out: g_clear_object (&pixbuf); g_clear_object (&factory); g_clear_object (&info); g_free (uri); return ret_val; }
/* thumbnail_thread is invoked as a separate thread to to make thumbnails. */ static gpointer thumbnail_thread_start (gpointer data) { NautilusThumbnailInfo *info = NULL; GdkPixbuf *pixbuf; time_t current_orig_mtime = 0; time_t current_time; GList *node; /* We loop until there are no more thumbails to make, at which point we exit the thread. */ for (;;) { #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Locking mutex\n"); #endif pthread_mutex_lock (&thumbnails_mutex); /********************************* * MUTEX LOCKED *********************************/ /* Pop the last thumbnail we just made off the head of the list and free it. I did this here so we only have to lock the mutex once per thumbnail, rather than once before creating it and once after. Don't pop the thumbnail off the queue if the original file mtime of the request changed. Then we need to redo the thumbnail. */ if (currently_thumbnailing && currently_thumbnailing->original_file_mtime == current_orig_mtime) { g_assert (info == currently_thumbnailing); node = g_hash_table_lookup (thumbnails_to_make_hash, info->image_uri); g_assert (node != NULL); g_hash_table_remove (thumbnails_to_make_hash, info->image_uri); free_thumbnail_info (info); g_queue_delete_link ((GQueue *)&thumbnails_to_make, node); } currently_thumbnailing = NULL; /* If there are no more thumbnails to make, reset the thumbnail_thread_is_running flag, unlock the mutex, and exit the thread. */ if (g_queue_is_empty ((GQueue *)&thumbnails_to_make)) { #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Exiting\n"); #endif thumbnail_thread_is_running = FALSE; pthread_mutex_unlock (&thumbnails_mutex); pthread_exit (NULL); } /* Get the next one to make. We leave it on the list until it is created so the main thread doesn't add it again while we are creating it. */ info = g_queue_peek_head ((GQueue *)&thumbnails_to_make); currently_thumbnailing = info; current_orig_mtime = info->original_file_mtime; /********************************* * MUTEX UNLOCKED *********************************/ #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Unlocking mutex\n"); #endif pthread_mutex_unlock (&thumbnails_mutex); time (¤t_time); /* Don't try to create a thumbnail if the file was modified recently. This prevents constant re-thumbnailing of changing files. */ if (current_time < current_orig_mtime + THUMBNAIL_CREATION_DELAY_SECS && current_time >= current_orig_mtime) { #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Skipping: %s\n", info->image_uri); #endif /* Reschedule thumbnailing via a change notification */ g_timeout_add_seconds (1, thumbnail_thread_notify_file_changed, g_strdup (info->image_uri)); continue; } /* Create the thumbnail. */ #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Creating thumbnail: %s\n", info->image_uri); #endif pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory, info->image_uri, info->mime_type); if (pixbuf) { gnome_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory, pixbuf, info->image_uri, current_orig_mtime); g_object_unref (pixbuf); } else { gnome_desktop_thumbnail_factory_create_failed_thumbnail (thumbnail_factory, info->image_uri, current_orig_mtime); } /* We need to call nautilus_file_changed(), but I don't think that is thread safe. So add an idle handler and do it from the main loop. */ g_idle_add_full (G_PRIORITY_HIGH_IDLE, thumbnail_thread_notify_file_changed, g_strdup (info->image_uri), NULL); } }
static gboolean cheese_thumb_view_idle_append_item (gpointer data) { CheeseThumbViewIdleData *item = g_queue_peek_head (data); CheeseThumbView *thumb_view; CheeseThumbViewPrivate *priv; /* Disconnect the idle handler when the queue is empty. */ if (item == NULL) return FALSE; thumb_view = item->thumb_view; priv = cheese_thumb_view_get_instance_private (thumb_view); GnomeDesktopThumbnailFactory *factory = priv->factory; GFile *file = item->file; GtkTreeIter iter = item->iter; GdkPixbuf *pixbuf = NULL; GFileInfo *info; char *thumb_loc; GTimeVal mtime; char *mime_type; char *uri; char *filename; info = g_file_query_info (file, "standard::content-type,time::modified", 0, NULL, NULL); if (!info) { g_warning ("Invalid filename\n"); return TRUE; } g_file_info_get_modification_time (info, &mtime); mime_type = g_strdup (g_file_info_get_content_type (info)); uri = g_file_get_uri (file); filename = g_file_get_path (file); thumb_loc = gnome_desktop_thumbnail_factory_lookup (factory, uri, mtime.tv_sec); if (!thumb_loc) { pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, uri, mime_type); if (!pixbuf) { g_warning ("could not generate thumbnail for %s (%s)\n", filename, mime_type); } else { gnome_desktop_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, mtime.tv_sec); } } else { pixbuf = gdk_pixbuf_new_from_file (thumb_loc, NULL); if (!pixbuf) { g_warning ("could not load thumbnail %s (%s)\n", filename, mime_type); } } g_object_unref (info); g_free (thumb_loc); g_free (uri); if (!pixbuf) { gchar *escape = NULL; GError *error = NULL; escape = g_strrstr (mime_type, "/"); if (escape != NULL) *escape = '-'; pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), mime_type, 96, GTK_ICON_LOOKUP_GENERIC_FALLBACK, &error); if (error) { g_warning ("%s", error->message); return TRUE; } } else { cheese_thumbnail_add_frame (&pixbuf); } gtk_list_store_set (priv->store, &iter, THUMBNAIL_PIXBUF_COLUMN, pixbuf, -1); g_free (mime_type); g_free (filename); g_object_unref (pixbuf); g_object_unref (file); g_slice_free (CheeseThumbViewIdleData, item); g_queue_pop_head (data); return TRUE; }
/** * eog_thumbnail_load: * @image: a #EogImage * @error: location to store the error ocurring or %NULL to ignore * * Loads the thumbnail for @image. In case of error, %NULL is returned * and @error is set. * * Returns: (transfer full): a new #GdkPixbuf with the thumbnail for * @image or %NULL in case of error. **/ GdkPixbuf* eog_thumbnail_load (EogImage *image, GError **error) { GdkPixbuf *thumb = NULL; GFile *file; EogThumbData *data; GdkPixbuf *pixbuf = NULL; g_return_val_if_fail (image != NULL, NULL); g_return_val_if_fail (error != NULL && *error == NULL, NULL); file = eog_image_get_file (image); data = eog_thumb_data_new (file, error); g_object_unref (file); if (data == NULL) return NULL; if (!data->can_read || (data->failed_thumb_exists && gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (factory, data->uri_str, data->mtime))) { eog_debug_message (DEBUG_THUMBNAIL, "%s: bad permissions or valid failed thumbnail present",data->uri_str); set_thumb_error (error, EOG_THUMB_ERROR_GENERIC, "Thumbnail creation failed"); return NULL; } /* check if there is already a valid cached thumbnail */ thumb = get_valid_thumbnail (data, error); if (thumb != NULL) { eog_debug_message (DEBUG_THUMBNAIL, "%s: loaded from cache",data->uri_str); } else if (gnome_desktop_thumbnail_factory_can_thumbnail (factory, data->uri_str, data->mime_type, data->mtime)) { /* Only use the image pixbuf when it is up to date. */ if (!eog_image_is_file_changed (image)) pixbuf = eog_image_get_pixbuf (image); if (pixbuf != NULL) { /* generate a thumbnail from the in-memory image, if we have already loaded the image */ eog_debug_message (DEBUG_THUMBNAIL, "%s: creating from pixbuf",data->uri_str); thumb = create_thumbnail_from_pixbuf (data, pixbuf, error); g_object_unref (pixbuf); } else { /* generate a thumbnail from the file */ eog_debug_message (DEBUG_THUMBNAIL, "%s: creating from file",data->uri_str); thumb = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, data->uri_str, data->mime_type); } if (thumb != NULL) { /* Save the new thumbnail */ gnome_desktop_thumbnail_factory_save_thumbnail (factory, thumb, data->uri_str, data->mtime); eog_debug_message (DEBUG_THUMBNAIL, "%s: normal thumbnail saved",data->uri_str); } else { /* Save a failed thumbnail, to stop further thumbnail attempts */ gnome_desktop_thumbnail_factory_create_failed_thumbnail (factory, data->uri_str, data->mtime); eog_debug_message (DEBUG_THUMBNAIL, "%s: failed thumbnail saved",data->uri_str); set_thumb_error (error, EOG_THUMB_ERROR_GENERIC, "Thumbnail creation failed"); } } eog_thumb_data_free (data); return thumb; }