[gnome-software/1843-gs-screenshot-support-videos-as-screenshot] gs-screenshot-image: Show also 'video' screenshots
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/1843-gs-screenshot-support-videos-as-screenshot] gs-screenshot-image: Show also 'video' screenshots
- Date: Tue, 9 Aug 2022 13:56:36 +0000 (UTC)
commit bea2adf8d86bc83348b586f71d1a63e7edad5a1b
Author: Milan Crha <mcrha redhat com>
Date: Tue Aug 9 15:55:09 2022 +0200
gs-screenshot-image: Show also 'video' screenshots
This allows to show also video screenshots, not only static images.
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/merge_requests/1451
src/gs-screenshot-image.c | 190 +++++++++++++++++++++++++++++++++------------
src/gs-screenshot-image.ui | 13 ++++
2 files changed, 153 insertions(+), 50 deletions(-)
---
diff --git a/src/gs-screenshot-image.c b/src/gs-screenshot-image.c
index 946ab0984..2a36ae403 100644
--- a/src/gs-screenshot-image.c
+++ b/src/gs-screenshot-image.c
@@ -27,13 +27,12 @@ struct _GsScreenshotImage
GtkWidget *box_error;
GtkWidget *image1;
GtkWidget *image2;
+ GtkWidget *video;
GtkWidget *label_error;
GSettings *settings;
SoupSession *session;
SoupMessage *message;
-#if SOUP_CHECK_VERSION(3, 0, 0)
GCancellable *cancellable;
-#endif
gchar *filename;
const gchar *current_image;
guint width;
@@ -104,32 +103,38 @@ gs_screenshot_image_set_error (GsScreenshotImage *ssimg, const gchar *message)
static void
as_screenshot_show_image (GsScreenshotImage *ssimg)
{
- g_autoptr(GdkPixbuf) pixbuf = NULL;
-
- /* no need to composite */
- if (ssimg->width == G_MAXUINT || ssimg->height == G_MAXUINT) {
- pixbuf = gdk_pixbuf_new_from_file (ssimg->filename, NULL);
+ if (as_screenshot_get_media_kind (ssimg->screenshot) == AS_SCREENSHOT_MEDIA_KIND_VIDEO) {
+ gtk_video_set_filename (GTK_VIDEO (ssimg->video), ssimg->filename);
+ ssimg->current_image = "video";
+ gtk_stack_set_visible_child_name (GTK_STACK (ssimg->stack), ssimg->current_image);
} else {
- /* this is always going to have alpha */
- pixbuf = gdk_pixbuf_new_from_file_at_scale (ssimg->filename,
- (gint) (ssimg->width * ssimg->scale),
- (gint) (ssimg->height * ssimg->scale),
- FALSE, NULL);
- }
-
- /* show icon */
- if (g_strcmp0 (ssimg->current_image, "image1") == 0) {
- if (pixbuf != NULL) {
- gtk_picture_set_pixbuf (GTK_PICTURE (ssimg->image2), pixbuf);
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+
+ /* no need to composite */
+ if (ssimg->width == G_MAXUINT || ssimg->height == G_MAXUINT) {
+ pixbuf = gdk_pixbuf_new_from_file (ssimg->filename, NULL);
+ } else {
+ /* this is always going to have alpha */
+ pixbuf = gdk_pixbuf_new_from_file_at_scale (ssimg->filename,
+ (gint) (ssimg->width * ssimg->scale),
+ (gint) (ssimg->height * ssimg->scale),
+ FALSE, NULL);
}
- gtk_stack_set_visible_child_name (GTK_STACK (ssimg->stack), "image2");
- ssimg->current_image = "image2";
- } else {
- if (pixbuf != NULL) {
- gtk_picture_set_pixbuf (GTK_PICTURE (ssimg->image1), pixbuf);
+
+ /* show icon */
+ if (g_strcmp0 (ssimg->current_image, "image1") == 0) {
+ if (pixbuf != NULL) {
+ gtk_picture_set_pixbuf (GTK_PICTURE (ssimg->image2), pixbuf);
+ }
+ gtk_stack_set_visible_child_name (GTK_STACK (ssimg->stack), "image2");
+ ssimg->current_image = "image2";
+ } else {
+ if (pixbuf != NULL) {
+ gtk_picture_set_pixbuf (GTK_PICTURE (ssimg->image1), pixbuf);
+ }
+ gtk_stack_set_visible_child_name (GTK_STACK (ssimg->stack), "image1");
+ ssimg->current_image = "image1";
}
- gtk_stack_set_visible_child_name (GTK_STACK (ssimg->stack), "image1");
- ssimg->current_image = "image1";
}
gtk_widget_show (GTK_WIDGET (ssimg));
@@ -243,6 +248,11 @@ gs_screenshot_image_show_blurred (GsScreenshotImage *ssimg,
if (pb == NULL)
return;
+ if (g_strcmp0 (ssimg->current_image, "video") == 0) {
+ ssimg->current_image = "image1";
+ gtk_stack_set_visible_child_name (GTK_STACK (ssimg->stack), ssimg->current_image);
+ }
+
if (g_strcmp0 (ssimg->current_image, "image1") == 0) {
gtk_picture_set_pixbuf (GTK_PICTURE (ssimg->image1), pb);
} else {
@@ -542,11 +552,84 @@ gs_screenshot_show_spinner_cb (gpointer user_data)
return FALSE;
}
+static const gchar *
+gs_screenshot_image_get_url (GsScreenshotImage *ssimg)
+{
+ const gchar *url = NULL;
+
+ /* load an image according to the scale factor */
+ ssimg->scale = (guint) gtk_widget_get_scale_factor (GTK_WIDGET (ssimg));
+
+ if (as_screenshot_get_media_kind (ssimg->screenshot) == AS_SCREENSHOT_MEDIA_KIND_VIDEO) {
+ GPtrArray *videos;
+ AsVideo *best_video = NULL;
+ gint64 best_size = G_MAXINT64;
+ gint64 wh = (gint64) ssimg->width * ssimg->scale * ssimg->height * ssimg->scale;
+
+ videos = as_screenshot_get_videos (ssimg->screenshot);
+ for (guint i = 0; videos != NULL && i < videos->len; i++) {
+ AsVideo *adept = g_ptr_array_index (videos, i);
+ gint64 tmp;
+
+ tmp = ABS (wh - (gint64) (as_video_get_width (adept) * as_video_get_height (adept)));
+ if (tmp < best_size) {
+ best_size = tmp;
+ best_video = adept;
+ if (!tmp)
+ break;
+ }
+ }
+
+ if (best_video)
+ url = as_video_get_url (best_video);
+ } else if (as_screenshot_get_media_kind (ssimg->screenshot) == AS_SCREENSHOT_MEDIA_KIND_IMAGE) {
+ AsImage *im;
+
+ im = as_screenshot_get_image (ssimg->screenshot,
+ ssimg->width * ssimg->scale,
+ ssimg->height * ssimg->scale);
+
+ /* if we've failed to load a HiDPI image, fallback to LoDPI */
+ if (im == NULL && ssimg->scale > 1) {
+ ssimg->scale = 1;
+ im = as_screenshot_get_image (ssimg->screenshot,
+ ssimg->width,
+ ssimg->height);
+ }
+
+ if (im)
+ url = as_image_get_url (im);
+ }
+
+ return url;
+}
+
+static void
+gs_screenshot_video_downloaded_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GsScreenshotImage) ssimg = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (gs_download_file_finish (ssimg->session, result, &error)) {
+ gs_screenshot_image_stop_spinner (ssimg);
+ as_screenshot_show_image (ssimg);
+
+ g_clear_object (&ssimg->cancellable);
+ } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_debug ("Failed to download screenshot video: %s", error->message);
+ /* Reset the width request, thus the image shrinks when the window width is small */
+ gtk_widget_set_size_request (ssimg->stack, -1, (gint) ssimg->height);
+ gs_screenshot_image_stop_spinner (ssimg);
+ gs_screenshot_image_set_error (ssimg, _("Screenshot not found"));
+ }
+}
+
void
gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
GCancellable *cancellable)
{
- AsImage *im = NULL;
const gchar *url;
g_autofree gchar *basename = NULL;
g_autofree gchar *cache_kind = NULL;
@@ -563,20 +646,8 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
/* Reset the width request, thus the image shrinks when the window width is small */
gtk_widget_set_size_request (ssimg->stack, -1, (gint) ssimg->height);
- /* load an image according to the scale factor */
- ssimg->scale = (guint) gtk_widget_get_scale_factor (GTK_WIDGET (ssimg));
- im = as_screenshot_get_image (ssimg->screenshot,
- ssimg->width * ssimg->scale,
- ssimg->height * ssimg->scale);
-
- /* if we've failed to load a HiDPI image, fallback to LoDPI */
- if (im == NULL && ssimg->scale > 1) {
- ssimg->scale = 1;
- im = as_screenshot_get_image (ssimg->screenshot,
- ssimg->width,
- ssimg->height);
- }
- if (im == NULL) {
+ url = gs_screenshot_image_get_url (ssimg);
+ if (url == NULL) {
/* TRANSLATORS: this is when we request a screenshot size that
* the generator did not create or the parser did not add */
gs_screenshot_image_set_error (ssimg, _("Screenshot size not found"));
@@ -584,7 +655,6 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
}
/* check if the URL points to a local file */
- url = as_image_get_url (im);
if (g_str_has_prefix (url, "file://")) {
g_free (ssimg->filename);
ssimg->filename = g_strdup (url + 7);
@@ -629,11 +699,13 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
/* if we're not showing a full-size image, we try loading a blurred
* smaller version of it straight away */
if (!ssimg->showing_image &&
+ as_screenshot_get_media_kind (ssimg->screenshot) == AS_SCREENSHOT_MEDIA_KIND_IMAGE &&
ssimg->width > AS_IMAGE_THUMBNAIL_WIDTH &&
ssimg->height > AS_IMAGE_THUMBNAIL_HEIGHT) {
const gchar *url_thumb;
g_autofree gchar *basename_thumb = NULL;
g_autofree gchar *cache_kind_thumb = NULL;
+ AsImage *im;
im = as_screenshot_get_image (ssimg->screenshot,
AS_IMAGE_THUMBNAIL_WIDTH * ssimg->scale,
AS_IMAGE_THUMBNAIL_HEIGHT * ssimg->scale);
@@ -684,11 +756,13 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
}
/* cancel any previous messages */
- if (ssimg->message != NULL) {
-#if SOUP_CHECK_VERSION(3, 0, 0)
+ if (ssimg->cancellable != NULL) {
g_cancellable_cancel (ssimg->cancellable);
g_clear_object (&ssimg->cancellable);
-#else
+ }
+
+ if (ssimg->message != NULL) {
+#if !SOUP_CHECK_VERSION(3, 0, 0)
soup_session_cancel_message (ssimg->session,
ssimg->message,
SOUP_STATUS_CANCELLED);
@@ -696,6 +770,22 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
g_clear_object (&ssimg->message);
}
+ if (as_screenshot_get_media_kind (ssimg->screenshot) == AS_SCREENSHOT_MEDIA_KIND_VIDEO) {
+ g_autofree gchar *uri_str = g_uri_to_string (base_uri);
+ g_autoptr(GFile) output_file = NULL;
+
+ ssimg->cancellable = g_cancellable_new ();
+ output_file = g_file_new_for_path (ssimg->filename);
+
+ /* Make sure the spinner takes approximately the size the screenshot will use */
+ gtk_widget_set_size_request (ssimg->stack, (gint) ssimg->width, (gint) ssimg->height);
+
+ gs_download_file_async (ssimg->session, uri_str, output_file, G_PRIORITY_DEFAULT, NULL, NULL,
+ ssimg->cancellable, gs_screenshot_video_downloaded_cb, g_object_ref
(ssimg));
+
+ return;
+ }
+
#if SOUP_CHECK_VERSION(3, 0, 0)
ssimg->message = soup_message_new_from_uri (SOUP_METHOD_GET, base_uri);
#else
@@ -717,9 +807,6 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
gs_screenshot_soup_msg_set_modified_request (ssimg->message, file);
}
- /* Make sure the spinner takes approximately the size the screenshot will use */
- gtk_widget_set_size_request (ssimg->stack, (gint) ssimg->width, (gint) ssimg->height);
-
ssimg->load_timeout_id = g_timeout_add_seconds (SPINNER_TIMEOUT_SECS,
gs_screenshot_show_spinner_cb, ssimg);
@@ -764,11 +851,13 @@ gs_screenshot_image_dispose (GObject *object)
ssimg->load_timeout_id = 0;
}
- if (ssimg->message != NULL) {
-#if SOUP_CHECK_VERSION(3, 0, 0)
+ if (ssimg->cancellable != NULL) {
g_cancellable_cancel (ssimg->cancellable);
g_clear_object (&ssimg->cancellable);
-#else
+ }
+
+ if (ssimg->message != NULL) {
+#if !SOUP_CHECK_VERSION(3, 0, 0)
soup_session_cancel_message (ssimg->session,
ssimg->message,
SOUP_STATUS_CANCELLED);
@@ -836,6 +925,7 @@ gs_screenshot_image_class_init (GsScreenshotImageClass *klass)
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, stack);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, image1);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, image2);
+ gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, video);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, box_error);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, label_error);
diff --git a/src/gs-screenshot-image.ui b/src/gs-screenshot-image.ui
index 2606be51d..a108ba77e 100644
--- a/src/gs-screenshot-image.ui
+++ b/src/gs-screenshot-image.ui
@@ -55,6 +55,19 @@
</object>
</child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">video</property>
+ <property name="child">
+ <object class="GtkVideo" id="video">
+ <style>
+ <class name="video"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+
<child>
<object class="GtkStackPage">
<property name="name">error</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]