[gnome-photos] base-item: Refactor thumbnail creation for remote items
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos] base-item: Refactor thumbnail creation for remote items
- Date: Sat, 6 Jul 2013 13:27:28 +0000 (UTC)
commit 9ed0e984055387ad5c2fd465097f4d1cf4c56ca0
Author: Debarshi Ray <debarshir gnome org>
Date: Tue Jul 2 13:20:56 2013 +0200
base-item: Refactor thumbnail creation for remote items
A new pure virtual method called "create_thumbnail" has been added. It
is meant to be run in a thread and implementations should take care of
creating the thumbnail image file according to the Thumbnail Managing
Standard [1].
Currently GnomeDesktopThumbnailFactory is used for creating local
thumbnails. Thumbnailing Flickr content is yet to be implemented.
[1] http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html
Fixes: https://bugzilla.gnome.org/697675
src/photos-base-item.c | 93 ++++++++++++++++++++++++++++++++++++----
src/photos-base-item.h | 1 +
src/photos-flickr-item.c | 12 +++++
src/photos-local-item.c | 18 ++++++++
src/photos-utils.c | 105 ++++++++++++++++++---------------------------
src/photos-utils.h | 6 +--
6 files changed, 159 insertions(+), 76 deletions(-)
---
diff --git a/src/photos-base-item.c b/src/photos-base-item.c
index de8d8d4..9524291 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -47,6 +47,7 @@ struct _PhotosBaseItemPrivate
GeglNode *graph;
GeglNode *node;
GeglRectangle bbox;
+ GMutex mutex_create_thumbnail;
GMutex mutex;
PhotosCollectionIconWatcher *watcher;
TrackerSparqlCursor *cursor;
@@ -199,6 +200,73 @@ photos_base_item_check_effects_and_update_info (PhotosBaseItem *self)
static void
+photos_base_item_create_thumbnail_in_thread_func (GSimpleAsyncResult *simple,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ PhotosBaseItem *self = PHOTOS_BASE_ITEM (object);
+ PhotosBaseItemPrivate *priv = self->priv;
+ GError *error;
+ gboolean op_res;
+
+ g_mutex_lock (&priv->mutex_create_thumbnail);
+
+ error = NULL;
+ op_res = PHOTOS_BASE_ITEM_GET_CLASS (self)->create_thumbnail (self, cancellable, &error);
+ if (error != NULL)
+ g_simple_async_result_take_error (simple, error);
+
+ g_simple_async_result_set_op_res_gboolean (simple, op_res);
+
+ g_mutex_unlock (&priv->mutex_create_thumbnail);
+}
+
+
+static void
+photos_base_item_create_thumbnail_async (PhotosBaseItem *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ photos_base_item_create_thumbnail_async);
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_run_in_thread (simple,
+ photos_base_item_create_thumbnail_in_thread_func,
+ G_PRIORITY_DEFAULT,
+ cancellable);
+ g_object_unref (simple);
+}
+
+
+static gboolean
+photos_base_item_create_thumbnail_finish (PhotosBaseItem *self, GAsyncResult *res, GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ gboolean ret_val = FALSE;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (res,
+ G_OBJECT (self),
+ photos_base_item_create_thumbnail_async),
+ NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ goto out;
+
+ ret_val = g_simple_async_result_get_op_res_gboolean (simple);
+
+ out:
+ return ret_val;
+}
+
+
+static void
photos_base_item_default_set_favorite (PhotosBaseItem *self, gboolean favorite)
{
photos_utils_set_favorite (self->priv->id, favorite);
@@ -353,17 +421,20 @@ photos_base_item_thumbnail_path_info (GObject *source_object, GAsyncResult *res,
static void
-photos_base_item_queue_thumbnail_job (GObject *source_object, GAsyncResult *res, gpointer user_data)
+photos_base_item_create_thumbnail_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
- PhotosBaseItem *self = PHOTOS_BASE_ITEM (user_data);
+ PhotosBaseItem *self = PHOTOS_BASE_ITEM (source_object);
PhotosBaseItemPrivate *priv = self->priv;
- GFile *file = G_FILE (source_object);
- gboolean thumbnailed;
+ GError *error;
+ GFile *file = G_FILE (user_data);
- thumbnailed = photos_utils_queue_thumbnail_job_for_file_finish (res);
- if (!thumbnailed)
+ error = NULL;
+ photos_base_item_create_thumbnail_finish (self, res, &error);
+ if (error != NULL)
{
priv->failed_thumbnailing = TRUE;
+ g_warning ("Unable to create thumbnail: %s", error->message);
+ g_error_free (error);
goto out;
}
@@ -376,6 +447,7 @@ photos_base_item_queue_thumbnail_job (GObject *source_object, GAsyncResult *res,
g_object_ref (self));
out:
+ g_object_unref (file);
g_object_unref (self);
}
@@ -405,9 +477,10 @@ photos_base_item_file_query_info (GObject *source_object, GAsyncResult *res, gpo
else
{
priv->thumbnailed = FALSE;
- photos_utils_queue_thumbnail_job_for_file_async (file,
- photos_base_item_queue_thumbnail_job,
- g_object_ref (self));
+ photos_base_item_create_thumbnail_async (self,
+ NULL,
+ photos_base_item_create_thumbnail_cb,
+ g_object_ref (file));
}
out:
@@ -672,6 +745,7 @@ photos_base_item_finalize (GObject *object)
g_free (priv->type_description);
g_free (priv->uri);
+ g_mutex_clear (&priv->mutex_create_thumbnail);
g_mutex_clear (&priv->mutex);
G_OBJECT_CLASS (photos_base_item_parent_class)->finalize (object);
@@ -727,6 +801,7 @@ photos_base_item_init (PhotosBaseItem *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, PHOTOS_TYPE_BASE_ITEM, PhotosBaseItemPrivate);
priv = self->priv;
+ g_mutex_init (&priv->mutex_create_thumbnail);
g_mutex_init (&priv->mutex);
}
diff --git a/src/photos-base-item.h b/src/photos-base-item.h
index 1cda085..216da96 100644
--- a/src/photos-base-item.h
+++ b/src/photos-base-item.h
@@ -68,6 +68,7 @@ struct _PhotosBaseItemClass
{
GObjectClass parent_class;
+ gboolean (*create_thumbnail) (PhotosBaseItem *self, GCancellable *cancellable, GError **error);
gchar *(*download) (PhotosBaseItem *self, GCancellable *cancellable, GError **error);
void (*set_favorite) (PhotosBaseItem *self, gboolean favorite);
void (*update_type_description) (PhotosBaseItem *self);
diff --git a/src/photos-flickr-item.c b/src/photos-flickr-item.c
index f7ff18a..68af65b 100644
--- a/src/photos-flickr-item.c
+++ b/src/photos-flickr-item.c
@@ -37,6 +37,17 @@
G_DEFINE_TYPE (PhotosFlickrItem, photos_flickr_item, PHOTOS_TYPE_BASE_ITEM);
+static gboolean
+photos_flickr_item_create_thumbnail (PhotosBaseItem *item, GCancellable *cancellable, GError **error)
+{
+ g_set_error (error,
+ g_quark_from_static_string ("gnome-photos-error"),
+ 0,
+ "Thumbnailing Flickr items is unsupported");
+ return FALSE;
+}
+
+
static gchar *
photos_flickr_item_download (PhotosBaseItem *item, GCancellable *cancellable, GError **error)
{
@@ -125,6 +136,7 @@ photos_flickr_item_class_init (PhotosFlickrItemClass *class)
PhotosBaseItemClass *base_item_class = PHOTOS_BASE_ITEM_CLASS (class);
object_class->constructed= photos_flickr_item_constructed;
+ base_item_class->create_thumbnail = photos_flickr_item_create_thumbnail;
base_item_class->download = photos_flickr_item_download;
}
diff --git a/src/photos-local-item.c b/src/photos-local-item.c
index 61e3024..79e6143 100644
--- a/src/photos-local-item.c
+++ b/src/photos-local-item.c
@@ -29,11 +29,28 @@
#include <glib.h>
#include "photos-local-item.h"
+#include "photos-utils.h"
G_DEFINE_TYPE (PhotosLocalItem, photos_local_item, PHOTOS_TYPE_BASE_ITEM);
+static gboolean
+photos_local_item_create_thumbnail (PhotosBaseItem *item, GCancellable *cancellable, GError **error)
+{
+ GFile *file;
+ gboolean ret_val;
+ const gchar *uri;
+
+ uri = photos_base_item_get_uri (item);
+ file = g_file_new_for_uri (uri);
+ ret_val = photos_utils_create_thumbnail (file, cancellable, error);
+
+ g_object_unref (file);
+ return ret_val;
+}
+
+
static gchar *
photos_local_item_download (PhotosBaseItem *item, GCancellable *cancellable, GError **error)
{
@@ -89,6 +106,7 @@ photos_local_item_class_init (PhotosLocalItemClass *class)
PhotosBaseItemClass *base_item_class = PHOTOS_BASE_ITEM_CLASS (class);
object_class->constructed= photos_local_item_constructed;
+ base_item_class->create_thumbnail = photos_local_item_create_thumbnail;
base_item_class->download = photos_local_item_download;
}
diff --git a/src/photos-utils.c b/src/photos-utils.c
index 50f55d6..1aefdb9 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -217,74 +217,66 @@ photos_utils_create_symbolic_icon (const gchar *name, gint base_size)
}
-const gchar *
-photos_utils_dot_dir (void)
+gboolean
+photos_utils_create_thumbnail (GFile *file, GCancellable *cancellable, GError **error)
{
- const gchar *config_dir;
+ 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;
- if (dot_dir == NULL)
+ 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)
{
- config_dir = g_get_user_config_dir ();
- dot_dir = g_build_filename (config_dir, PACKAGE_TARNAME, 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;
}
- if (g_file_test (dot_dir, G_FILE_TEST_IS_DIR))
- goto out;
-
- g_mkdir_with_parents (dot_dir, 0700);
+ gnome_desktop_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, (time_t) mtime);
+ ret_val = TRUE;
out:
- return dot_dir;
+ g_clear_object (&pixbuf);
+ g_clear_object (&factory);
+ g_clear_object (&info);
+ g_free (uri);
+ return ret_val;
}
-static gboolean
-photos_utils_create_thumbnail (GIOSchedulerJob *job, GCancellable *cancellable, gpointer user_data)
+const gchar *
+photos_utils_dot_dir (void)
{
- GSimpleAsyncResult *result = user_data;
- GFile *file = G_FILE (g_async_result_get_source_object (G_ASYNC_RESULT (result)));
- GnomeDesktopThumbnailFactory *factory;
- GFileInfo *info;
- const gchar *attributes = G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","G_FILE_ATTRIBUTE_TIME_MODIFIED;
- gchar *uri;
- GdkPixbuf *pixbuf;
- guint64 mtime;
-
- uri = g_file_get_uri (file);
- info = g_file_query_info (file, attributes, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ const gchar *config_dir;
- /* we don't care about reporting errors here, just fail the
- * thumbnail.
- */
- if (info == NULL)
+ if (dot_dir == NULL)
{
- g_simple_async_result_set_op_res_gboolean (result, FALSE);
- goto out;
+ config_dir = g_get_user_config_dir ();
+ dot_dir = g_build_filename (config_dir, PACKAGE_TARNAME, NULL);
}
- 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)
- {
- 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);
+ if (g_file_test (dot_dir, G_FILE_TEST_IS_DIR))
+ goto out;
- g_object_unref (info);
- g_object_unref (file);
- g_object_unref (factory);
- g_clear_object (&pixbuf);
+ g_mkdir_with_parents (dot_dir, 0700);
out:
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
-
- return FALSE;
+ return dot_dir;
}
@@ -612,19 +604,6 @@ photos_utils_icon_from_rdf_type (const gchar *type)
}
-void
-photos_utils_queue_thumbnail_job_for_file_async (GFile *file, GAsyncReadyCallback callback, gpointer
user_data)
-{
- GSimpleAsyncResult *result;
-
- result = g_simple_async_result_new (G_OBJECT (file),
- callback,
- user_data,
- photos_utils_queue_thumbnail_job_for_file_async);
- g_io_scheduler_push_job (photos_utils_create_thumbnail, result, NULL, G_PRIORITY_DEFAULT, NULL);
-}
-
-
gboolean
photos_utils_queue_thumbnail_job_for_file_finish (GAsyncResult *res)
{
diff --git a/src/photos-utils.h b/src/photos-utils.h
index 89b28d5..05e5d41 100644
--- a/src/photos-utils.h
+++ b/src/photos-utils.h
@@ -40,6 +40,8 @@ GdkPixbuf *photos_utils_create_pixbuf_from_node (GeglNode *node);
GIcon *photos_utils_create_symbolic_icon (const gchar *name, gint base_size);
+gboolean photos_utils_create_thumbnail (GFile *file, GCancellable *cancellable, GError
**error);
+
const gchar *photos_utils_dot_dir (void);
GdkPixbuf *photos_utils_embed_image_in_frame (GdkPixbuf *source_image,
@@ -65,10 +67,6 @@ GList *photos_utils_get_urns_from_paths (GList *paths, GtkTree
GIcon *photos_utils_icon_from_rdf_type (const gchar *type);
-void photos_utils_queue_thumbnail_job_for_file_async (GFile *file,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
gboolean photos_utils_queue_thumbnail_job_for_file_finish (GAsyncResult *res);
void photos_utils_set_edited_name (const gchar *urn, const gchar *title);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]