aboutsummaryrefslogtreecommitdiff
path: root/fiv-browser.c
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-06-08 01:05:04 +0200
committerPřemysl Eric Janouch <p@janouch.name>2022-06-08 02:51:54 +0200
commita8f7532abdd9eade6ccc7587968e63eea3b5d159 (patch)
tree7ad4015cea3c93442c566d134118246bf8b4fe8a /fiv-browser.c
parent8dfbd0dee2a76d4cc3c8b1a339ed6d904b45fd9f (diff)
downloadfiv-a8f7532abdd9eade6ccc7587968e63eea3b5d159.tar.gz
fiv-a8f7532abdd9eade6ccc7587968e63eea3b5d159.tar.xz
fiv-a8f7532abdd9eade6ccc7587968e63eea3b5d159.zip
Employ embedded thumbnail extraction
And store all direct thumbnailer output in the browser's cache-- low-quality thumbnails will always be regenerated, as is desired, and we'll reload faster on devices where we don't store thumbnails. This change improves latency at the cost of overall efficiency, seeing as images with thumbnails will be spent cycles on twice. Keeping this out-of-process avoids undesired lock-ups. Moreover, embedded thumbnails can be fairly expensive to decode.
Diffstat (limited to 'fiv-browser.c')
-rw-r--r--fiv-browser.c51
1 files changed, 39 insertions, 12 deletions
diff --git a/fiv-browser.c b/fiv-browser.c
index 111c291..10cb17a 100644
--- a/fiv-browser.c
+++ b/fiv-browser.c
@@ -439,6 +439,9 @@ entry_add_thumbnail(gpointer data, gpointer user_data)
(intptr_t) cairo_surface_get_user_data(
cached, &fiv_browser_key_mtime_msec) == self->mtime_msec) {
self->thumbnail = cairo_surface_reference(cached);
+ // TODO(p): If this hit is low-quality, see if a high-quality thumbnail
+ // hasn't been produced without our knowledge (avoid launching a minion
+ // unnecessarily; we might also shift the concern there).
} else {
cairo_surface_t *found = fiv_thumbnail_lookup(
self->uri, self->mtime_msec, browser->item_size);
@@ -555,19 +558,31 @@ thumbnailer_reprocess_entry(FivBrowser *self, GBytes *output, Entry *entry)
{
g_clear_object(&entry->icon);
g_clear_pointer(&entry->thumbnail, cairo_surface_destroy);
- guint64 dummy;
+
+ gtk_widget_queue_resize(GTK_WIDGET(self));
+
+ guint64 flags = 0;
if (!output || !(entry->thumbnail = rescale_thumbnail(
- fiv_io_deserialize(output, &dummy), self->item_height))) {
+ fiv_io_deserialize(output, &flags), self->item_height))) {
entry_add_thumbnail(entry, self);
materialize_icon(self, entry);
- } else {
- // This choice of mtime favours unnecessary thumbnail reloading.
- cairo_surface_set_user_data(entry->thumbnail,
- &fiv_browser_key_mtime_msec, (void *) (intptr_t) entry->mtime_msec,
- NULL);
+ return;
}
+ if ((flags & FIV_IO_SERIALIZE_LOW_QUALITY)) {
+ cairo_surface_set_user_data(entry->thumbnail, &fiv_thumbnail_key_lq,
+ (void *) (intptr_t) 1, NULL);
- gtk_widget_queue_resize(GTK_WIDGET(self));
+ // TODO(p): Improve complexity; this will iterate the whole linked list.
+ self->thumbnailers_queue =
+ g_list_append(self->thumbnailers_queue, entry);
+ }
+
+ // This choice of mtime favours unnecessary thumbnail reloading.
+ cairo_surface_set_user_data(entry->thumbnail,
+ &fiv_browser_key_mtime_msec, (void *) (intptr_t) entry->mtime_msec,
+ NULL);
+ g_hash_table_insert(self->thumbnail_cache, g_strdup(entry->uri),
+ cairo_surface_reference(entry->thumbnail));
}
static void
@@ -629,11 +644,23 @@ thumbnailer_next(Thumbnailer *t)
self->thumbnailers_queue =
g_list_delete_link(self->thumbnailers_queue, self->thumbnailers_queue);
+ // Case analysis:
+ // - We haven't found any thumbnail for the entry at all
+ // (and it has a symbolic icon as a result):
+ // we want to fill the void ASAP, so go for embedded thumbnails first.
+ // - We've found one, but we're not quite happy with it:
+ // always run the full process for a high-quality wide thumbnail.
+ // - We can't end up here in any other cases.
+ const char *argv_faster[] = {PROJECT_NAME, "--extract-thumbnail",
+ "--thumbnail", fiv_thumbnail_sizes[self->item_size].thumbnail_spec_name,
+ "--", t->target->uri, NULL};
+ const char *argv_slower[] = {PROJECT_NAME,
+ "--thumbnail", fiv_thumbnail_sizes[self->item_size].thumbnail_spec_name,
+ "--", t->target->uri, NULL};
+
GError *error = NULL;
- t->minion = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error,
- PROJECT_NAME, "--thumbnail",
- fiv_thumbnail_sizes[self->item_size].thumbnail_spec_name, "--",
- t->target->uri, NULL);
+ t->minion = g_subprocess_newv(t->target->icon ? argv_faster : argv_slower,
+ G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error);
if (error) {
g_warning("%s", error->message);
g_error_free(error);