Exemplo n.º 1
0
/* thumbnail_thread is invoked as a separate thread to to make thumbnails. */
static void
thumbnail_thread_func (GTask        *task,
                       gpointer      source_object,
                       gpointer      task_data,
                       GCancellable *cancellable)
{
    CajaThumbnailInfo *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
        g_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;
            g_mutex_unlock (&thumbnails_mutex);
            return;
        }

        /* 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
        g_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_seconds (1, 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 = mate_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory,
                 info->image_uri,
                 info->mime_type);

        if (pixbuf)
        {
#ifdef DEBUG_THUMBNAILS
			g_message ("(Thumbnail Thread) Saving thumbnail: %s\n",
				   info->image_uri);
#endif
            mate_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory,
                    pixbuf,
                    info->image_uri,
                    current_orig_mtime);
            g_object_unref (pixbuf);
        }
        else
        {
#ifdef DEBUG_THUMBNAILS
			g_message ("(Thumbnail Thread) Thumbnail failed: %s\n",
				   info->image_uri);
#endif
            mate_desktop_thumbnail_factory_create_failed_thumbnail (thumbnail_factory,
                    info->image_uri,
                    current_orig_mtime);
        }
        /* We need to call caja_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);
    }
}
GdkPixbuf*
eom_thumbnail_load (EomImage *image, GError **error)
{
	GdkPixbuf *thumb = NULL;
	GFile *file;
	EomThumbData *data;
	GdkPixbuf *pixbuf;

	g_return_val_if_fail (image != NULL, NULL);
	g_return_val_if_fail (error != NULL && *error == NULL, NULL);

	file = eom_image_get_file (image);
	data = eom_thumb_data_new (file, error);
	g_object_unref (file);

	if (data == NULL)
		return NULL;

	if (!data->can_read ||
	    (data->failed_thumb_exists && mate_desktop_thumbnail_factory_has_valid_failed_thumbnail (factory, data->uri_str, data->mtime))) {
		eom_debug_message (DEBUG_THUMBNAIL, "%s: bad permissions or valid failed thumbnail present",data->uri_str);
		set_thumb_error (error, EOM_THUMB_ERROR_GENERIC, "Thumbnail creation failed");
		return NULL;
	}

	/* check if there is already a valid cached thumbnail */
	thumb = get_valid_thumbnail (data, error);

	if (thumb != NULL) {
		eom_debug_message (DEBUG_THUMBNAIL, "%s: loaded from cache",data->uri_str);
	} else if (mate_desktop_thumbnail_factory_can_thumbnail (factory, data->uri_str, data->mime_type, data->mtime)) {
		pixbuf = eom_image_get_pixbuf (image);

		if (pixbuf != NULL) {
			/* generate a thumbnail from the in-memory image,
			   if we have already loaded the image */
			eom_debug_message (DEBUG_THUMBNAIL, "%s: creating from pixbuf",data->uri_str);
			thumb = create_thumbnail_from_pixbuf (data, pixbuf, error);
			g_object_unref (pixbuf);
		} else {
			/* generate a thumbnail from the file */
			eom_debug_message (DEBUG_THUMBNAIL, "%s: creating from file",data->uri_str);
			thumb = mate_desktop_thumbnail_factory_generate_thumbnail (factory, data->uri_str, data->mime_type);
		}

		if (thumb != NULL) {
			/* Save the new thumbnail */
			mate_desktop_thumbnail_factory_save_thumbnail (factory, thumb, data->uri_str, data->mtime);
			eom_debug_message (DEBUG_THUMBNAIL, "%s: normal thumbnail saved",data->uri_str);
		} else {
			/* Save a failed thumbnail, to stop further thumbnail attempts */
			mate_desktop_thumbnail_factory_create_failed_thumbnail (factory, data->uri_str, data->mtime);
			eom_debug_message (DEBUG_THUMBNAIL, "%s: failed thumbnail saved",data->uri_str);
			set_thumb_error (error, EOM_THUMB_ERROR_GENERIC, "Thumbnail creation failed");
		}
	}

	eom_thumb_data_free (data);

	return thumb;
}