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;
}
Beispiel #10
0
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);
}
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}