Commit bfed6c0d authored by Debarshi Ray's avatar Debarshi Ray

Support fallback pipeline paths

A subsequent commit will change the location where edits are stored for
local items. In order to provide backwords compatibility with existing
edits stored at the old location, and to transparently migrate them to
the new location, it is necessary that a PhotosBaseItem sub-class be
able to return multiple pipeline locations.

All parameters that accepted a single pipeline path or URI have been
modified to accept a NULL-terminated array of paths or URIs.

The automatic mapping from an "as" GVariant to the natural GStrv C type
has been disabled for the GenerateThumbnail()[pipeline_uris] parameter
because the gdbus-codegen:ed wrapper cannot convert a NULL GStrv to its
equivalent GVariant. It uses g_variant_new_strv with the length always
set to -1, which isn't valid when the GStrv is NULL.

#87
parent a97e0ac7
......@@ -657,6 +657,8 @@ photos-thumbnailer-dbus.h photos-thumbnailer-dbus.c: photos-thumbnailer-dbus.xml
--generate-c-code photos-thumbnailer-dbus \
--interface-prefix org.gnome.Photos. \
--annotate "org.gnome.Photos.Thumbnailer" org.gtk.GDBus.C.Name ThumbnailerDBus \
--annotate "org.gnome.Photos.Thumbnailer.GenerateThumbnail()[pipeline_uris]" \
org.gtk.GDBus.C.ForceGVariant true \
$<
photos-tracker-extract-priority.h photos-tracker-extract-priority.c: photos-tracker-extract-priority.xml
......
......@@ -1575,21 +1575,21 @@ photos_base_item_load_pipeline_task_cache_populate (EggTaskCache *cache,
PhotosBaseItem *self = PHOTOS_BASE_ITEM ((gpointer) key);
PhotosBaseItemClass *class;
GCancellable *cancellable;
g_autofree gchar *uri = NULL;
g_auto (GStrv) uris = NULL;
cancellable = g_task_get_cancellable (task);
class = PHOTOS_BASE_ITEM_GET_CLASS (self);
if (class->create_pipeline_path != NULL)
if (class->create_pipeline_paths != NULL)
{
g_autofree gchar *path = NULL;
g_auto (GStrv) paths = NULL;
path = class->create_pipeline_path (self);
uri = photos_utils_convert_path_to_uri (path);
paths = photos_base_item_create_pipeline_paths (self);
uris = photos_utils_convert_paths_to_uris ((const gchar *const *) paths);
}
photos_pipeline_new_async (NULL,
uri,
(const gchar *const *) uris,
cancellable,
photos_base_item_load_pipeline_task_cache_populate_new,
g_object_ref (task));
......@@ -3133,7 +3133,7 @@ photos_base_item_can_edit (PhotosBaseItem *self)
g_return_val_if_fail (!priv->collection, FALSE);
return PHOTOS_BASE_ITEM_GET_CLASS (self)->create_pipeline_path != NULL;
return PHOTOS_BASE_ITEM_GET_CLASS (self)->create_pipeline_paths != NULL;
}
......@@ -3145,6 +3145,18 @@ photos_base_item_can_trash (PhotosBaseItem *self)
}
GStrv
photos_base_item_create_pipeline_paths (PhotosBaseItem *self)
{
GStrv paths;
g_return_val_if_fail (PHOTOS_IS_BASE_ITEM (self), NULL);
paths = PHOTOS_BASE_ITEM_GET_CLASS (self)->create_pipeline_paths (self);
return paths;
}
cairo_surface_t *
photos_base_item_create_preview (PhotosBaseItem *self,
gint size,
......
......@@ -57,7 +57,7 @@ struct _PhotosBaseItemClass
/* virtual methods */
gchar *(*create_filename_fallback) (PhotosBaseItem *self);
gchar *(*create_name_fallback) (PhotosBaseItem *self);
gchar *(*create_pipeline_path) (PhotosBaseItem *self);
GStrv (*create_pipeline_paths) (PhotosBaseItem *self);
gboolean (*create_thumbnail) (PhotosBaseItem *self, GCancellable *cancellable, GError **error);
gchar *(*create_thumbnail_path) (PhotosBaseItem *self);
gchar *(*download) (PhotosBaseItem *self, GCancellable *cancellable, GError **error);
......@@ -82,6 +82,8 @@ gboolean photos_base_item_can_edit (PhotosBaseItem *se
gboolean photos_base_item_can_trash (PhotosBaseItem *self);
GStrv photos_base_item_create_pipeline_paths (PhotosBaseItem *self) G_GNUC_WARN_UNUSED_RESULT;
cairo_surface_t *photos_base_item_create_preview (PhotosBaseItem *self,
gint size,
gint scale,
......
......@@ -251,7 +251,7 @@ photos_device_item_create_thumbnail (PhotosBaseItem *item, GCancellable *cancell
orientation,
height,
width,
"",
NULL,
thumbnail_path,
cancellable,
error))
......
......@@ -123,18 +123,22 @@ photos_local_item_get_pipeline_path (PhotosLocalItem *self)
}
static gchar *
photos_local_item_create_pipeline_path (PhotosBaseItem *item)
static GStrv
photos_local_item_create_pipeline_paths (PhotosBaseItem *item)
{
PhotosLocalItem *self = PHOTOS_LOCAL_ITEM (item);
gchar *path;
GStrv paths = NULL;
g_autofree gchar *path = NULL;
g_autofree gchar *pipeline_dir = NULL;
path = photos_local_item_get_pipeline_path (self);
pipeline_dir = g_path_get_dirname (path);
g_mkdir_with_parents (pipeline_dir, 0700);
return path;
paths = (GStrv) g_malloc0_n (2, sizeof (gchar *));
paths[0] = g_steal_pointer (&path);
return paths;
}
......@@ -144,10 +148,11 @@ photos_local_item_create_thumbnail (PhotosBaseItem *item, GCancellable *cancella
PhotosLocalItem *self = PHOTOS_LOCAL_ITEM (item);
g_autoptr (GFile) file = NULL;
GQuark orientation;
g_auto (GStrv) pipeline_paths = NULL;
g_auto (GStrv) pipeline_uris = NULL;
gboolean ret_val = FALSE;
const gchar *mime_type;
const gchar *uri;
g_autofree gchar *pipeline_path = NULL;
g_autofree gchar *pipeline_uri = NULL;
g_autofree gchar *thumbnail_path = NULL;
gint64 height;
......@@ -163,8 +168,8 @@ photos_local_item_create_thumbnail (PhotosBaseItem *item, GCancellable *cancella
width = photos_base_item_get_width (PHOTOS_BASE_ITEM (self));
thumbnail_path = photos_base_item_create_thumbnail_path (PHOTOS_BASE_ITEM (self));
pipeline_path = photos_local_item_get_pipeline_path (self);
pipeline_uri = photos_utils_convert_path_to_uri (pipeline_path);
pipeline_paths = photos_base_item_create_pipeline_paths (PHOTOS_BASE_ITEM (self));
pipeline_uris = photos_utils_convert_paths_to_uris ((const gchar *const *) pipeline_paths);
if (!photos_utils_create_thumbnail (file,
mime_type,
......@@ -172,7 +177,7 @@ photos_local_item_create_thumbnail (PhotosBaseItem *item, GCancellable *cancella
orientation,
height,
width,
pipeline_uri,
(const gchar *const *) pipeline_uris,
thumbnail_path,
cancellable,
error))
......@@ -437,7 +442,7 @@ photos_local_item_class_init (PhotosLocalItemClass *class)
object_class->dispose = photos_local_item_dispose;
base_item_class->create_filename_fallback = photos_local_item_create_filename_fallback;
base_item_class->create_name_fallback = photos_local_item_create_name_fallback;
base_item_class->create_pipeline_path = photos_local_item_create_pipeline_path;
base_item_class->create_pipeline_paths = photos_local_item_create_pipeline_paths;
base_item_class->create_thumbnail = photos_local_item_create_thumbnail;
base_item_class->download = photos_local_item_download;
base_item_class->get_source_widget = photos_local_item_get_source_widget;
......
......@@ -103,7 +103,7 @@ photos_media_server_item_create_thumbnail (PhotosBaseItem *item, GCancellable *c
orientation,
height,
width,
"",
NULL,
thumbnail_path,
cancellable,
error);
......
......@@ -35,16 +35,16 @@ struct _PhotosPipeline
{
GObject parent_instance;
GHashTable *hash;
GStrv uris;
GeglNode *graph;
gchar *snapshot;
gchar *uri;
};
enum
{
PROP_0,
PROP_PARENT,
PROP_URI
PROP_URIS
};
static void photos_pipeline_async_initable_iface_init (GAsyncInitableIface *iface);
......@@ -242,8 +242,8 @@ photos_pipeline_finalize (GObject *object)
{
PhotosPipeline *self = PHOTOS_PIPELINE (object);
g_strfreev (self->uris);
g_free (self->snapshot);
g_free (self->uri);
G_OBJECT_CLASS (photos_pipeline_parent_class)->finalize (object);
......@@ -267,8 +267,8 @@ photos_pipeline_set_property (GObject *object, guint prop_id, const GValue *valu
break;
}
case PROP_URI:
self->uri = g_value_dup_string (value);
case PROP_URIS:
self->uris = (GStrv) g_value_dup_boxed (value);
break;
default:
......@@ -307,12 +307,13 @@ photos_pipeline_class_init (PhotosPipelineClass *class)
G_PARAM_CONSTRUCT | G_PARAM_WRITABLE));
g_object_class_install_property (object_class,
PROP_URI,
g_param_spec_string ("uri",
"An URI",
"The location to save this pipeline",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
PROP_URIS,
g_param_spec_boxed ("uris",
"URIs",
"Possible locations from which to load this pipeline, and"
"afterwards it will be saved to the first non-NULL URI.",
G_TYPE_STRV,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
}
......@@ -321,10 +322,14 @@ photos_pipeline_async_initable_init_load_contents (GObject *source_object, GAsyn
{
g_autoptr (GTask) task = G_TASK (user_data);
PhotosPipeline *self;
GCancellable *cancellable;
GFile *file = G_FILE (source_object);
g_autofree gchar *contents = NULL;
const gchar *uri;
self = PHOTOS_PIPELINE (g_task_get_source_object (task));
cancellable = g_task_get_cancellable (task);
uri = (const gchar *) g_task_get_task_data (task);
{
g_autoptr (GError) error = NULL;
......@@ -333,7 +338,30 @@ photos_pipeline_async_initable_init_load_contents (GObject *source_object, GAsyn
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
goto carry_on;
g_autoptr (GFile) file_next = NULL;
guint i;
for (i = 0; self->uris[i] != NULL; i++)
{
if (g_strcmp0 (self->uris[i], uri) == 0)
break;
}
g_assert_nonnull (self->uris[i]);
i++;
if (self->uris[i] == NULL)
goto carry_on;
g_task_set_task_data (task, g_strdup (self->uris[i]), g_free);
file_next = g_file_new_for_uri (self->uris[i]);
g_file_load_contents_async (file_next,
cancellable,
photos_pipeline_async_initable_init_load_contents,
g_object_ref (task));
goto out;
}
else
{
......@@ -344,12 +372,7 @@ photos_pipeline_async_initable_init_load_contents (GObject *source_object, GAsyn
}
if (!(photos_pipeline_create_graph_from_xml (self, contents)))
{
g_autofree gchar *uri = NULL;
uri = g_file_get_uri (file);
g_warning ("Unable to deserialize from %s", uri);
}
g_warning ("Unable to deserialize from %s", uri);
carry_on:
g_task_return_boolean (task, TRUE);
......@@ -373,13 +396,15 @@ photos_pipeline_async_initable_init_async (GAsyncInitable *initable,
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, photos_pipeline_async_initable_init_async);
if (self->uri == NULL)
if (self->uris == NULL || self->uris[0] == NULL || self->uris[0][0] == '\0')
{
g_task_return_boolean (task, TRUE);
goto out;
}
file = g_file_new_for_uri (self->uri);
g_task_set_task_data (task, g_strdup (self->uris[0]), g_free);
file = g_file_new_for_uri (self->uris[0]);
g_file_load_contents_async (file,
cancellable,
photos_pipeline_async_initable_init_load_contents,
......@@ -414,7 +439,7 @@ photos_pipeline_async_initable_iface_init (GAsyncInitableIface *iface)
void
photos_pipeline_new_async (GeglNode *parent,
const gchar *uri,
const gchar *const *uris,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
......@@ -428,7 +453,7 @@ photos_pipeline_new_async (GeglNode *parent,
callback,
user_data,
"parent", parent,
"uri", uri,
"uris", uris,
NULL);
}
......@@ -634,7 +659,7 @@ photos_pipeline_save_async (PhotosPipeline *self,
*/
g_task_set_task_data (task, xml, g_free);
file = g_file_new_for_uri (self->uri);
file = g_file_new_for_uri (self->uris[0]);
len = strlen (xml);
g_file_replace_contents_async (file,
xml,
......
......@@ -30,7 +30,7 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (PhotosPipeline, photos_pipeline, PHOTOS, PIPELINE, GObject);
void photos_pipeline_new_async (GeglNode *parent,
const gchar *uri,
const gchar *const *uris,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
......
......@@ -320,7 +320,7 @@ photos_thumbnail_factory_generate_thumbnail (PhotosThumbnailFactory *self,
GQuark orientation,
gint64 original_height,
gint64 original_width,
const gchar *pipeline_uri,
const gchar *const *pipeline_uris,
const gchar *thumbnail_path,
GCancellable *cancellable,
GError **error)
......@@ -397,14 +397,20 @@ photos_thumbnail_factory_generate_thumbnail (PhotosThumbnailFactory *self,
}
else
{
GVariant *pipeline_uris_variant;
const gchar *orientation_str;
g_autofree gchar *uri = NULL;
gint thumbnail_size;
gssize n_pipeline_uris;
g_assert_true (PHOTOS_IS_THUMBNAILER_DBUS (self->thumbnailer));
uri = g_file_get_uri (file);
orientation_str = g_quark_to_string (orientation);
n_pipeline_uris = pipeline_uris == NULL ? 0 : -1;
pipeline_uris_variant = g_variant_new_strv (pipeline_uris, n_pipeline_uris);
thumbnail_size = photos_utils_get_icon_size ();
photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Calling GenerateThumbnail for %s", uri);
......@@ -414,7 +420,7 @@ photos_thumbnail_factory_generate_thumbnail (PhotosThumbnailFactory *self,
orientation_str,
original_height,
original_width,
pipeline_uri,
pipeline_uris_variant,
thumbnail_path,
thumbnail_size,
cancellable,
......
......@@ -35,7 +35,7 @@ gboolean photos_thumbnail_factory_generate_thumbnail (Photos
GQuark orientation,
gint64 original_height,
gint64 original_width,
const gchar *pipeline_uri,
const gchar *const *pipeline_uris,
const gchar *thumbnail_path,
GCancellable *cancellable,
GError **error);
......
......@@ -31,7 +31,7 @@
<arg name="orientation" type="s" direction="in" />
<arg name="original_height" type="x" direction="in" />
<arg name="original_width" type="x" direction="in" />
<arg name="pipeline_uri" type="s" direction="in" />
<arg name="pipeline_uris" type="as" direction="in" />
<arg name="thumbnail_path" type="s" direction="in" />
<arg name="thumbnail_size" type="i" direction="in" />
</method>
......
......@@ -483,7 +483,7 @@ photos_thumbnailer_generate_thumbnail_async (PhotosThumbnailer *self,
const gchar *orientation,
gint64 original_height,
gint64 original_width,
const gchar *pipeline_uri,
const gchar *const *pipeline_uris,
const gchar *thumbnail_path,
gint thumbnail_size,
GCancellable *cancellable,
......@@ -519,7 +519,7 @@ photos_thumbnailer_generate_thumbnail_async (PhotosThumbnailer *self,
g_task_set_task_data (task, data, (GDestroyNotify) photos_thumbnailer_generate_data_free);
photos_pipeline_new_async (graph,
pipeline_uri,
pipeline_uris,
cancellable,
photos_thumbnailer_generate_thumbnail_pipeline,
g_object_ref (task));
......@@ -620,24 +620,24 @@ photos_thumbnailer_handle_generate_thumbnail (PhotosThumbnailer *self,
const gchar *orientation,
gint64 original_height,
gint64 original_width,
const gchar *pipeline_uri,
GVariant *pipeline_uris_variant,
const gchar *thumbnail_path,
gint thumbnail_size)
{
g_autoptr (GCancellable) cancellable = NULL;
g_auto (GStrv) pipeline_uris = NULL;
g_return_val_if_fail (PHOTOS_IS_THUMBNAILER (self), FALSE);
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE);
g_return_val_if_fail (uri != NULL && uri[0] != '\0', FALSE);
g_return_val_if_fail (mime_type != NULL && mime_type[0] != '\0', FALSE);
g_return_val_if_fail (orientation != NULL && orientation[0] != '\0', FALSE);
g_return_val_if_fail (pipeline_uri != NULL, FALSE);
g_return_val_if_fail (g_variant_is_of_type (pipeline_uris_variant, G_VARIANT_TYPE ("as")), FALSE);
g_return_val_if_fail (thumbnail_path != NULL && thumbnail_path[0] != '\0', FALSE);
photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Handling GenerateThumbnail for %s", uri);
if (pipeline_uri[0] == '\0')
pipeline_uri = NULL;
pipeline_uris = g_variant_dup_strv (pipeline_uris_variant, NULL);
cancellable = g_cancellable_new ();
g_hash_table_insert (self->cancellables, g_object_ref (invocation), g_object_ref (cancellable));
......@@ -649,7 +649,7 @@ photos_thumbnailer_handle_generate_thumbnail (PhotosThumbnailer *self,
orientation,
original_height,
original_width,
pipeline_uri,
(const gchar *const *) pipeline_uris,
thumbnail_path,
thumbnail_size,
cancellable,
......
......@@ -372,7 +372,7 @@ photos_utils_create_thumbnail (GFile *file,
GQuark orientation,
gint64 original_height,
gint64 original_width,
const gchar *pipeline_uri,
const gchar *const *pipeline_uris,
const gchar *thumbnail_path,
GCancellable *cancellable,
GError **error)
......@@ -387,7 +387,7 @@ photos_utils_create_thumbnail (GFile *file,
orientation,
original_height,
original_width,
pipeline_uri,
pipeline_uris,
thumbnail_path,
cancellable,
error))
......
......@@ -77,7 +77,7 @@ gboolean photos_utils_create_thumbnail (GFile *file,
GQuark orientation,
gint64 original_height,
gint64 original_width,
const gchar *pipeline_uri,
const gchar *const *pipeline_uris,
const gchar *thumbnail_path,
GCancellable *cancellable,
GError **error);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment