static void photos_tracker_controller_cursor_next (GObject *source_object, GAsyncResult *res, gpointer user_data) { PhotosTrackerController *self = PHOTOS_TRACKER_CONTROLLER (user_data); PhotosTrackerControllerPrivate *priv = self->priv; TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR (source_object); gboolean valid; gint64 now; valid = tracker_sparql_cursor_next_finish (cursor, res, NULL); /* TODO: use GError */ if (!valid) { tracker_sparql_cursor_close (cursor); photos_tracker_controller_query_finished (self, NULL); g_object_unref (self); return; } now = g_get_monotonic_time (); photos_debug (PHOTOS_DEBUG_TRACKER, "Query Cursor: %" G_GINT64_FORMAT, (now - priv->last_query_time) / 1000000); photos_item_manager_add_item (PHOTOS_ITEM_MANAGER (priv->item_mngr), cursor); tracker_sparql_cursor_next_async (cursor, priv->cancellable, photos_tracker_controller_cursor_next, self); }
static void photos_thumbnailer_shutdown (GApplication *application) { photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Thumbnailer exiting"); G_APPLICATION_CLASS (photos_thumbnailer_parent_class)->shutdown (application); }
static void photos_thumbnailer_handle_generate_thumbnail_generate_thumbnail (GObject *source_object, GAsyncResult *res, gpointer user_data) { PhotosThumbnailer *self = PHOTOS_THUMBNAILER (source_object); g_autoptr (GDBusMethodInvocation) invocation = G_DBUS_METHOD_INVOCATION (user_data); { g_autoptr (GError) error = NULL; if (!photos_thumbnailer_generate_thumbnail_finish (self, res, &error)) { g_dbus_method_invocation_take_error (invocation, g_steal_pointer (&error)); goto out; } } photos_thumbnailer_dbus_complete_generate_thumbnail (self->skeleton, invocation); out: photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Completed GenerateThumbnail"); g_application_release (G_APPLICATION (self)); g_hash_table_remove (self->cancellables, invocation); }
static void photos_dlna_renderers_manager_renderer_new_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { PhotosDlnaRenderersManager *self = PHOTOS_DLNA_RENDERERS_MANAGER (user_data); PhotosDlnaRenderer *renderer; const gchar *object_path; GError *error = NULL; renderer = photos_dlna_renderer_new_for_bus_finish (res, &error); if (error != NULL) { g_warning ("Unable to load renderer object: %s", error->message); g_propagate_error (&self->error, error); return; } object_path = photos_dlna_renderer_get_object_path (renderer); photos_debug (PHOTOS_DEBUG_DLNA, "%s '%s' %s %s", G_STRFUNC, photos_dlna_renderer_get_friendly_name (renderer), photos_dlna_renderer_get_udn (renderer), object_path); g_hash_table_insert (self->renderers, (gpointer) object_path, renderer); g_signal_emit (self, signals[RENDERER_FOUND], 0, renderer); }
static void photos_dlna_renderers_manager_proxy_new_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { PhotosDlnaRenderersManager *self = user_data; GError *error = NULL; self->proxy = dleyna_renderer_manager_proxy_new_for_bus_finish (res, &error); if (error != NULL) { g_warning ("Unable to connect to the dLeynaRenderer.Manager DBus object: %s", error->message); g_propagate_error (&self->error, error); return; } photos_debug (PHOTOS_DEBUG_DLNA, "%s DLNA renderers manager initialized", G_STRFUNC); g_signal_connect_swapped (self->proxy, "found-renderer", G_CALLBACK (photos_dlna_renderers_manager_renderer_found_cb), self); g_signal_connect_swapped (self->proxy, "lost-renderer", G_CALLBACK (photos_dlna_renderers_manager_renderer_lost_cb), self); dleyna_renderer_manager_call_get_renderers (self->proxy, NULL, photos_dlna_renderers_manager_proxy_get_renderers_cb, self); }
static void photos_thumbnailer_startup (GApplication *application) { G_APPLICATION_CLASS (photos_thumbnailer_parent_class)->startup (application); photos_gegl_init (); photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Thumbnailer ready"); }
static void photos_import_dialog_fetch_collections_local_cursor_next (GObject *source_object, GAsyncResult *res, gpointer user_data) { PhotosImportDialog *self; g_autoptr (PhotosBaseItem) collection = NULL; TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR (source_object); gboolean success; const gchar *identifier; g_autofree gchar *identifier_time = NULL; { g_autoptr (GError) error = NULL; /* Note that tracker_sparql_cursor_next_finish can return FALSE even * without an error. */ success = tracker_sparql_cursor_next_finish (cursor, res, &error); if (error != NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Unable to fetch local collections: %s", error->message); goto out; } } self = PHOTOS_IMPORT_DIALOG (user_data); if (!success) { photos_import_dialog_initialize_index_and_popover (self); goto out; } collection = photos_item_manager_create_item (PHOTOS_ITEM_MANAGER (self->item_mngr), G_TYPE_NONE, cursor, FALSE); photos_import_dialog_add_collection (self, collection); identifier = photos_base_item_get_identifier (collection); identifier_time = g_strdup_printf ("%s%" G_GINT64_FORMAT, PHOTOS_QUERY_LOCAL_COLLECTIONS_IDENTIFIER, self->time); if (g_strcmp0 (identifier, identifier_time) == 0) { const gchar *id; id = photos_filterable_get_id (PHOTOS_FILTERABLE (collection)); photos_debug (PHOTOS_DEBUG_IMPORT, "Default collection already exists: %s", id); g_set_object (&self->default_collection, collection); } tracker_sparql_cursor_next_async (cursor, self->cancellable, photos_import_dialog_fetch_collections_local_cursor_next, self); out: return; }
static gboolean photos_thumbnailer_handle_cancel (PhotosThumbnailer *self, GDBusMethodInvocation *invocation, guint serial) { GCancellable *cancellable; GDBusConnection *connection; GDBusMethodInvocation *invocation_ongoing; GHashTableIter iter; g_return_val_if_fail (PHOTOS_IS_THUMBNAILER (self), FALSE); g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE); photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Handling Cancel for %u", serial); g_application_hold (G_APPLICATION (self)); connection = g_dbus_method_invocation_get_connection (invocation); g_hash_table_iter_init (&iter, self->cancellables); while (g_hash_table_iter_next (&iter, (gpointer *) &invocation_ongoing, (gpointer *) &cancellable)) { GDBusConnection *connection_ongoing; GDBusMessage *message_ongoing; guint32 serial_ongoing; connection_ongoing = g_dbus_method_invocation_get_connection (invocation_ongoing); message_ongoing = g_dbus_method_invocation_get_message (invocation_ongoing); serial_ongoing = g_dbus_message_get_serial (message_ongoing); if (connection == connection_ongoing && (guint32) serial == serial_ongoing) { g_cancellable_cancel (cancellable); photos_thumbnailer_dbus_complete_cancel (self->skeleton, invocation); goto out; } } g_dbus_method_invocation_return_error_literal (invocation, PHOTOS_ERROR, 0, "Invalid serial"); out: photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Completed Cancel"); g_application_release (G_APPLICATION (self)); return TRUE; }
static gboolean photos_thumbnailer_handle_generate_thumbnail (PhotosThumbnailer *self, GDBusMethodInvocation *invocation, const gchar *uri, const gchar *mime_type, const gchar *orientation, gint64 original_height, gint64 original_width, 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 (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); 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)); g_application_hold (G_APPLICATION (self)); photos_thumbnailer_generate_thumbnail_async (self, uri, mime_type, orientation, original_height, original_width, (const gchar *const *) pipeline_uris, thumbnail_path, thumbnail_size, cancellable, photos_thumbnailer_handle_generate_thumbnail_generate_thumbnail, g_object_ref (invocation)); return TRUE; }
static void photos_image_view_draw_node (PhotosImageView *self, cairo_t *cr, GdkRectangle *rect) { const Babl *format; GeglRectangle roi; cairo_surface_t *surface = NULL; guchar *buf = NULL; gint scale_factor; gint stride; gint64 end; gint64 start; scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (self)); roi.x = (gint) self->x_scaled + rect->x * scale_factor; roi.y = (gint) self->y_scaled + rect->y * scale_factor; roi.width = rect->width * scale_factor; roi.height = rect->height * scale_factor; format = babl_format ("cairo-ARGB32"); stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, roi.width); buf = g_malloc0 (stride * roi.height); start = g_get_monotonic_time (); gegl_node_blit (self->node, (gdouble) self->zoom_scaled, &roi, format, buf, GEGL_AUTO_ROWSTRIDE, GEGL_BLIT_CACHE | GEGL_BLIT_DIRTY); end = g_get_monotonic_time (); photos_debug (PHOTOS_DEBUG_GEGL, "PhotosImageView: Node Blit: %" G_GINT64_FORMAT, end - start); surface = cairo_image_surface_create_for_data (buf, CAIRO_FORMAT_ARGB32, roi.width, roi.height, stride); cairo_surface_set_device_scale (surface, (gdouble) scale_factor, (gdouble) scale_factor); cairo_set_source_surface (cr, surface, rect->x, rect->y); cairo_paint (cr); cairo_surface_destroy (surface); g_free (buf); }
static void photos_dlna_renderers_manager_renderer_lost_cb (PhotosDlnaRenderersManager *self, const gchar *object_path, gpointer *data) { PhotosDlnaRenderer *renderer; renderer = PHOTOS_DLNA_RENDERER (g_hash_table_lookup (self->renderers, object_path)); g_return_if_fail (renderer != NULL); g_hash_table_steal (self->renderers, object_path); photos_debug (PHOTOS_DEBUG_DLNA, "%s '%s' %s %s", G_STRFUNC, photos_dlna_renderer_get_friendly_name (renderer), photos_dlna_renderer_get_udn (renderer), object_path); g_signal_emit (self, signals[RENDERER_LOST], 0, renderer); g_object_unref (renderer); }
static void photos_tracker_controller_set_query_status (PhotosTrackerController *self, gboolean query_status) { PhotosTrackerControllerPrivate *priv = self->priv; gint64 now; if (priv->querying == query_status) return; now = g_get_monotonic_time (); if (query_status) priv->last_query_time = now; else { photos_debug (PHOTOS_DEBUG_TRACKER, "Query Elapsed: %" G_GINT64_FORMAT, (now - priv->last_query_time) / 1000000); priv->last_query_time = 0; } priv->querying = query_status; g_signal_emit (self, signals[QUERY_STATUS_CHANGED], 0, priv->querying); }
static void photos_thumbnailer_generate_thumbnail_pipeline (GObject *source_object, GAsyncResult *res, gpointer user_data) { GCancellable *cancellable; g_autoptr (GTask) task = G_TASK (user_data); g_autoptr (PhotosPipeline) pipeline = NULL; PhotosThumbnailerGenerateData *data; gboolean has_crop; g_autofree gchar *path = NULL; g_autofree gchar *uri = NULL; gdouble height; gdouble width; gdouble x; gdouble y; gint load_height; gint load_width; cancellable = g_task_get_cancellable (task); data = g_task_get_task_data (task); { g_autoptr (GError) error = NULL; pipeline = photos_pipeline_new_finish (res, &error); if (error != NULL) { g_task_return_error (task, g_steal_pointer (&error)); goto out; } } g_assert_null (data->pipeline); data->pipeline = g_object_ref (pipeline); uri = g_file_get_uri (data->file); has_crop = photos_pipeline_get (pipeline, "gegl:crop", "height", &height, "width", &width, "x", &x, "y", &y, NULL); if (has_crop) { if (height < 0.0 || width < 0.0 || x < 0.0 || y < 0.0) { g_warning ("Unable to crop the thumbnail for %s: Invalid parameters", uri); photos_pipeline_remove (pipeline, "gegl:crop"); has_crop = FALSE; } } if (has_crop || (0 < data->original_height && data->original_height < data->thumbnail_size && 0 < data->original_width && data->original_width < data->thumbnail_size)) { load_height = (gint) data->original_height; load_width = (gint) data->original_width; } else { load_height = data->thumbnail_size; load_width = data->thumbnail_size; } path = g_file_get_path (data->file); if (!g_file_is_native (data->file)) photos_debug (PHOTOS_DEBUG_NETWORK, "Downloading %s (%s)", uri, path); photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Loading %s at %d×%d", uri, load_width, load_height); photos_pixbuf_new_from_file_at_size_async (path, load_width, load_height, cancellable, photos_thumbnailer_generate_thumbnail_pixbuf, g_object_ref (task)); out: return; }
static void photos_thumbnailer_generate_thumbnail_process (GObject *source_object, GAsyncResult *res, gpointer user_data) { GCancellable *cancellable; g_autoptr (GFile) thumbnail_file = NULL; g_autoptr (GTask) task = G_TASK (user_data); GeglNode *pipeline_node; GeglProcessor *processor = GEGL_PROCESSOR (source_object); PhotosThumbnailerGenerateData *data; g_autofree gchar *thumbnail_dir = NULL; gdouble zoom = 0.0; gint pixbuf_height; gint pixbuf_width; gint pixbuf_zoomed_height; gint pixbuf_zoomed_width; cancellable = g_task_get_cancellable (task); data = g_task_get_task_data (task); { g_autoptr (GError) error = NULL; if (!photos_gegl_processor_process_finish (processor, res, &error)) { g_task_return_error (task, g_steal_pointer (&error)); goto out; } } g_assert_null (data->pixbuf_thumbnail); pipeline_node = photos_pipeline_get_graph (data->pipeline); data->pixbuf_thumbnail = photos_gegl_create_pixbuf_from_node (pipeline_node); pixbuf_height = gdk_pixbuf_get_height (data->pixbuf_thumbnail); pixbuf_width = gdk_pixbuf_get_width (data->pixbuf_thumbnail); if (pixbuf_height > pixbuf_width && pixbuf_height > data->thumbnail_size) { zoom = (gdouble) data->thumbnail_size / (gdouble) pixbuf_height; pixbuf_zoomed_height = data->thumbnail_size; pixbuf_zoomed_width = (gint) (zoom * (gdouble) pixbuf_width + 0.5); } else if (pixbuf_height <= pixbuf_width && pixbuf_width > data->thumbnail_size) { zoom = (gdouble) data->thumbnail_size / (gdouble) pixbuf_width; pixbuf_zoomed_height = (gint) (zoom * (gdouble) pixbuf_height + 0.5); pixbuf_zoomed_width = data->thumbnail_size; } if (zoom > 0.0) { g_autoptr (GdkPixbuf) pixbuf_scaled = NULL; photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Scaling thumbnail to %d×%d", pixbuf_zoomed_width, pixbuf_zoomed_height); pixbuf_scaled = gdk_pixbuf_scale_simple (data->pixbuf_thumbnail, pixbuf_zoomed_width, pixbuf_zoomed_height, GDK_INTERP_BILINEAR); g_set_object (&data->pixbuf_thumbnail, pixbuf_scaled); } thumbnail_dir = g_path_get_dirname (data->thumbnail_path); g_mkdir_with_parents (thumbnail_dir, 0700); thumbnail_file = g_file_new_for_path (data->thumbnail_path); photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Saving thumbnail to %s", data->thumbnail_path); g_file_replace_async (thumbnail_file, NULL, FALSE, G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, G_PRIORITY_DEFAULT, cancellable, photos_thumbnailer_generate_thumbnail_replace, g_object_ref (task)); out: return; }