コード例 #1
0
/**
 * shell_get_thumbnail:
 *
 * @uri: URI of the file to thumbnail
 *
 * @mime_type: Mime-Type of the file to thumbnail
 *
 * Return value: #GdkPixbuf containing a thumbnail for file @uri
 *               if the thumbnail exists or can be generated, %NULL otherwise
 */
GdkPixbuf *
shell_get_thumbnail(const gchar *uri,
                    const gchar *mime_type)
{
    char *existing_thumbnail;
    GdkPixbuf *pixbuf = NULL;
    GError *error = NULL;
    GFile *file = NULL;
    GFileInfo *file_info = NULL;
    GTimeVal mtime_g;
    time_t mtime = 0;

    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;
    }

    if (thumbnail_factory == NULL)
      thumbnail_factory = gnome_thumbnail_factory_new (GNOME_THUMBNAIL_SIZE_NORMAL);

    existing_thumbnail = gnome_thumbnail_factory_lookup (thumbnail_factory, uri, mtime);

    if (existing_thumbnail != NULL)
      {
        pixbuf = gdk_pixbuf_new_from_file(existing_thumbnail, &error);
        if (error != NULL) 
          {
            g_warning("Could not generate a pixbuf from file %s: %s", existing_thumbnail, error->message);
            g_clear_error (&error);
          }
      }
    else if (gnome_thumbnail_factory_has_valid_failed_thumbnail (thumbnail_factory, uri, mtime))
      return NULL;
    else if (gnome_thumbnail_factory_can_thumbnail (thumbnail_factory, uri, mime_type, mtime)) 
      {
        pixbuf = gnome_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_thumbnail_factory_save_thumbnail (thumbnail_factory, pixbuf, uri, mtime);
          }          
        else 
          {
            g_warning ("Could not generate thumbnail for %s", uri);
            gnome_thumbnail_factory_create_failed_thumbnail (thumbnail_factory, uri, mtime);
          }
      }

    return pixbuf;   
}
コード例 #2
0
/* 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 (&current_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 (1000, 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_thumbnail_factory_generate_thumbnail (thumbnail_factory,
								     info->image_uri,
								     info->mime_type);

		if (pixbuf) {
			gnome_thumbnail_factory_save_thumbnail (thumbnail_factory,
								pixbuf,
								info->image_uri,
								current_orig_mtime);
			g_object_unref (pixbuf);
		} else {
			gnome_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);
	}
}