[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1107654: marked as done (unblock: totem/43.2-3)



Your message dated Fri, 13 Jun 2025 13:50:14 +0000
with message-id <E1uQ4nO-00GwLu-25@respighi.debian.org>
and subject line unblock totem
has caused the Debian Bug report #1107654,
regarding unblock: totem/43.2-3
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
1107654: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1107654
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
X-Debbugs-Cc: totem@packages.debian.org
Control: affects -1 + src:totem
User: release.debian.org@packages.debian.org
Usertags: unblock

[ Reason ]
New upstream bugfix release, in particular fixing #986432

[ Impact ]
If not accepted, various bugs would be unfixed, notably:
- #986432 which makes totem unusable on 32-bit;
- totem#614 which can leak a lot of disk space in
  ~/.cache/totem/stream-buffer if I'm reading correctly

If the release team is unhappy with the size of this upstream bugfix 
release, then I think we should cherry-pick the fixes for at least those 
two bugs instead. But following upstream and getting the benefit of 
other distros' testing seems safer than doing our own thing.

[ Tests ]
Manually tested by watching some videos with and without 
TOTEM_USE_GST_GTKSINK=1 environment variable.

I tried streaming some videos over smb:// and http, but was unable to 
reproduce large temporary files appearing in 
~/.cache/totem/stream-buffer, so I cannot confirm that totem#614 is 
fixed.

Other distros are also shipping this version, e.g. it has been in Fedora 
41 and 42 for 20 days.

[ Risks ]
Key package, installed by our default desktop environment.

Adding support for falling back to gtksink is a larger change than I 
would normally expect in a stable-branch update, but it could be the 
difference between totem being usable or unusable on weaker hardware, 
and the code is not too complicated.

Similarly using GStreamer's convert-sample instead of open-coding it is 
a larger change than I would have expected, but it's a code deletion 
rather than addition, and I trust GStreamer to get this right more than 
I trust Totem.

We can revert any of these changes if they prove to be a problem.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing
      - debdiff is testing vs. experimental, what I'm proposing to
        upload to unstable is this plus a changelog entry.
        I filtered out translation updates, upstream CI changes,
        and the content of the patches that were dropped.
debdiff *.dsc | filterdiff -p1 -x.gitlab-ci.yml -x'debian/patches/*.patch' -x'po/*.po'

 NEWS                                              |   16 +
 data/appdata/org.gnome.Totem.appdata.xml.in.in    |   22 +
 data/mime-functions.sh                            |    2 
 debian/changelog                                  |   62 ++++
 debian/control                                    |    3 
 debian/patches/series                             |    9 
 meson.build                                       |   23 -
 po/LINGUAS                                        |    1 
 src/backend/bacon-video-widget.c                  |  134 ++++++++--
 src/backend/bacon-video-widget.h                  |    2 
 src/backend/meson.build                           |    4 
 src/gst/totem-gst-pixbuf-helpers.c                |  289 ----------------------
 src/icon-helpers.c                                |    2 
 src/plugins/open-directory/totem-open-directory.c |    8 
 src/plugins/pythonconsole/console.py              |    3 
 src/plugins/recent/totem-recent.c                 |    2 
 src/plugins/rotation/totem-rotation.c             |    7 
 src/plugins/save-file/totem-save-file.c           |    2 
 src/plugins/screenshot/totem-screenshot-plugin.c  |   47 ---
 src/totem-object.c                                |    9 
 src/totem-playlist.c                              |    2 
 src/totem-resources.c                             |   10 
 src/totem-resources.h                             |    3 
 src/totem-video-thumbnailer.c                     |   15 -
 src/totem.c                                       |    2 
 25 files changed, 277 insertions(+), 402 deletions(-)

diff -Nru totem-43.1/data/appdata/org.gnome.Totem.appdata.xml.in.in totem-43.2/data/appdata/org.gnome.Totem.appdata.xml.in.in
--- totem-43.1/data/appdata/org.gnome.Totem.appdata.xml.in.in	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/data/appdata/org.gnome.Totem.appdata.xml.in.in	2025-05-21 14:08:29.000000000 +0100
@@ -20,17 +20,18 @@
       and support for recording DVDs.
     </p>
   </description>
-  <url type="homepage">https://wiki.gnome.org/Apps/Videos</url>
+  <url type="homepage">https://apps.gnome.org/Totem/</url>
   <url type="bugtracker">https://gitlab.gnome.org/GNOME/totem/issues</url>
-  <url type="donation">https://www.gnome.org/friends/</url>
+  <url type="donation">https://www.gnome.org/donate/</url>
   <url type="translate">https://l10n.gnome.org/module/totem/</url>
   <url type="help">https://help.gnome.org/users/totem/stable/</url>
+  <url type="vcs-browser">https://gitlab.gnome.org/GNOME/totem</url>
   <screenshots>
     <screenshot type="default">
-      <image>https://gitlab.gnome.org/GNOME/totem/raw/HEAD/data/appdata/ss-player.png</image>
+      <image>https://gitlab.gnome.org/GNOME/totem/raw/gnome-43/data/appdata/ss-player.png</image>
     </screenshot>
     <screenshot>
-      <image>https://gitlab.gnome.org/GNOME/totem/raw/HEAD/data/appdata/ss-videos.png</image>
+      <image>https://gitlab.gnome.org/GNOME/totem/raw/gnome-43/data/appdata/ss-videos.png</image>
     </screenshot>
   </screenshots>
   <update_contact>hadess@hadess.net</update_contact>
@@ -39,6 +40,15 @@
   <translation type="gettext">totem</translation>
   <launchable type="desktop-id">@APPLICATION_ID@.desktop</launchable>
   <releases>
+    <release version="43.2" date="2025-05-21">
+      <description>
+        <p>
+          This new 43.2 version includes the use of gtksink as a video output
+          when native OpenGL support is not available, as well as many thumbnailer
+          related bug fixes, and translation updates.
+        </p>
+      </description>
+    </release>
     <release version="43.1" date="2024-10-22">
       <description>
         <p>
@@ -113,4 +123,8 @@
     <kudo>UserDocs</kudo>
   </kudos>
   <content_rating type="oars-1.1" />
+  <branding>
+    <color type="primary" scheme_preference="light">#f8e45c</color>
+    <color type="primary" scheme_preference="dark">#613583</color>
+  </branding>
 </component>
diff -Nru totem-43.1/data/mime-functions.sh totem-43.2/data/mime-functions.sh
--- totem-43.1/data/mime-functions.sh	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/data/mime-functions.sh	2025-05-21 14:08:29.000000000 +0100
@@ -8,7 +8,7 @@
 
 get_video_mimetypes ()
 {
-	MIMETYPES=`grep -v '^#' $1 | grep -v x-content/ | grep -v audio | grep -v "application/x-flac" | grep -v "text/google-video-pointer" | grep -v "application/x-quicktime-media-link" | grep -v "application/smil" | grep -v "application/smil+xml" | grep -v "application/x-smil" | grep -v "application/xspf+xml" | grep -v -E 'application/[a-z-]*ogg'`
+	MIMETYPES=`grep -v '^#' $1 | grep -v x-content/ | grep -v audio | grep -v "application/x-flac" | grep -v "text/google-video-pointer" | grep -v "application/x-quicktime-media-link" | grep -v -E 'application/.*smil.*' | grep -v "application/xspf+xml" | grep -v "mpegurl" | grep -v -E 'application/[a-z-]*ogg'`
 	MIMETYPES="$MIMETYPES audio/x-pn-realaudio"
 }
 
diff -Nru totem-43.1/debian/changelog totem-43.2/debian/changelog
--- totem-43.1/debian/changelog	2025-05-05 20:28:32.000000000 +0100
+++ totem-43.2/debian/changelog	2025-06-11 11:01:40.000000000 +0100
@@ -1,3 +1,65 @@
+totem (43.2-2) experimental; urgency=medium
+
+  * Team upload
+  * Summarize upstream changes in previous changelog entry
+  * d/control: Increase libportal build-dependency to 0.7, now required
+    upstream due to totem!390.
+    This version is already present in trixie, but not in bookworm.
+  * d/control: Explicitly build-depend on libepoxy-dev, required by the
+    GL check in totem!379
+
+ -- Simon McVittie <smcv@debian.org>  Wed, 11 Jun 2025 11:01:40 +0100
+
+totem (43.2-1) experimental; urgency=medium
+
+  * New upstream release
+    - Fix a crash on startup on 32-bit architectures
+      (Closes: #986432, totem!393 upstream)
+    - Fix memory leaks, one of which could have the side-effect of leaking
+      large amounts of disk space in ~/.cache/totem/stream-buffer
+      (totem#614, totem!409 upstream)
+    - Make the main video widget take keyboard focus when playback starts,
+      so that keyboard shortcuts like spacebar to pause work as expected
+      (totem!420 upstream)
+    - Don't crash the whole application if libportal fails to initialize:
+      use xdp_portal_initable_new() instead, which has error reporting
+      (totem!390 upstream)
+    - Match the window to the application ID so that Wayland compositors
+      will show the correct icon
+      (totem!391 upstream)
+    - Automatically fall back to plain GTK video sink if environment
+      variable TOTEM_USE_GST_GTKSINK=1 is set, if the GL driver is too old
+      to work, or if the GL driver name indicates software rendering
+      (totem!379 upstream)
+    - Use GStreamer playbin's convert-sample feature instead of
+      reimplementing equivalent functionality locally
+      (totem!261 upstream)
+    - Exclude m3u playlists from thumbnailing: they are not a video format,
+      and loading them from a sandbox with no network access will usually
+      fail anyway
+      (totem#626 upstream)
+    - Avoid a duplicate MIME-type registration for application/x-smil, etc.
+      (totem#635 upstream)
+    - Allow one thumbnailing process per CPU
+      (totem!399 upstream)
+    - Fix a deprecation warning in the pythonconsole plugin
+      (totem!400 upstream)
+    - Stop using a private gnome-shell API to show a "camera flash" effect
+      when taking screenshots: unprivileged apps are no longer allowed to
+      call into this API, so it had no practical effect
+      (totem!371 upstream)
+    - AppStream metadata improvements
+      + update URLs
+      + pin screenshots to the gnome-43 branch so they will not become
+        misleading if the UI changes in the main branch
+      + add branding colours
+    - Fix build system warnings
+    - Translation updates
+  * Remove all patches except d/p/Mark-lint-checks-as-part-of-a-suite.patch,
+    applied in new release
+
+ -- Jeremy Bícha <jbicha@ubuntu.com>  Fri, 06 Jun 2025 13:20:12 -0400
+
 totem (43.1-6) unstable; urgency=medium
 
   * Team upload
diff -Nru totem-43.1/debian/control totem-43.2/debian/control
--- totem-43.1/debian/control	2025-05-05 20:28:32.000000000 +0100
+++ totem-43.2/debian/control	2025-06-11 11:01:40.000000000 +0100
@@ -19,6 +19,7 @@
                libatk1.0-dev,
                libbluetooth-dev [linux-any],
                libcairo2-dev,
+               libepoxy-dev,
                libgdk-pixbuf-2.0-dev,
                libgirepository1.0-dev,
                libglib2.0-dev (>= 2.72.0),
@@ -29,7 +30,7 @@
                libgtk-3-dev,
                libhandy-1-dev (>= 1.5.90),
                libpeas-dev,
-               libportal-gtk3-dev,
+               libportal-gtk3-dev (>= 0.7),
                librsvg2-dev,
                libtotem-plparser-dev,
                libx11-dev (>= 2:1.8),
diff -Nru totem-43.1/debian/patches/series totem-43.2/debian/patches/series
--- totem-43.1/debian/patches/series	2025-05-05 20:28:32.000000000 +0100
+++ totem-43.2/debian/patches/series	2025-06-11 11:01:40.000000000 +0100
@@ -1,10 +1 @@
 Mark-lint-checks-as-part-of-a-suite.patch
-plugins-remove-apple-trailers-plugin.patch
-plugins-Remove-vimeo-plug-in.patch
-Update-POTFILES.in.patch
-Update-POTFILES.in-1.patch
-data-Add-new-canonical-mime-type-for-AVI-files.patch
-Fix-totem-thumbnailer-fail-due-to-OpenBLAS-pthread-e.patch
-thumbnailer-Bump-memory-usage-limit.patch
-use-appstreamcli.patch
-Fix-Thumbnailer-Gstreamer-threading.patch
diff -Nru totem-43.1/meson.build totem-43.2/meson.build
--- totem-43.1/meson.build	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/meson.build	2025-05-21 14:08:29.000000000 +0100
@@ -1,6 +1,6 @@
 project(
   'totem', 'c',
-  version: '43.1',
+  version: '43.2',
   license: 'GPL2+ with exception',
   default_options: 'buildtype=debugoptimized',
   meson_version: '>= 0.57.0'
@@ -126,17 +126,18 @@
 glib_req_version = '>= 2.72.0'
 gtk_req_version = '>= 3.22.0'
 hdy_req_version = '>= 1.5.0'
-gst_req_version = '>= 1.6.0'
+gst_req_version = '>= 1.21.1'
 grilo_req_version = '>= 0.3.0'
 peas_req_version = '>= 1.1.0'
 totem_plparser_req_version = '>= 3.26.5'
+libportal_req_version = '>= 0.7'
 
 glib_dep =  dependency('glib-2.0', version: glib_req_version)
 gobject_dep =  dependency('gobject-2.0', version: glib_req_version)
 gmodule_dep = dependency('gmodule-2.0', version: glib_req_version)
 gio_dep = dependency('gio-2.0', version: '>= 2.43.4')
 gtk_dep = dependency('gtk+-3.0', version: gtk_req_version)
-targets = gtk_dep.get_pkgconfig_variable('targets')
+targets = gtk_dep.get_variable(pkgconfig : 'targets')
 if targets.split(' ').contains('x11')
   x11_dep = dependency('x11', version: '>= 1.8')
 else
@@ -144,9 +145,9 @@
 endif
 hdy_dep = dependency('libhandy-1', version: hdy_req_version)
 gst_dep = dependency('gstreamer-1.0', version: gst_req_version)
-gst_tag_dep = dependency('gstreamer-tag-1.0', version: '>= 0.11.93')
-gst_video_dep = dependency('gstreamer-video-1.0')
-gst_pbutils_dep = dependency('gstreamer-pbutils-1.0')
+gst_tag_dep = dependency('gstreamer-tag-1.0', version: gst_req_version)
+gst_video_dep = dependency('gstreamer-video-1.0', version: gst_req_version)
+gst_pbutils_dep = dependency('gstreamer-pbutils-1.0', version: gst_req_version)
 peas_dep = dependency('libpeas-1.0', version: peas_req_version)
 peas_gtk_dep = dependency('libpeas-gtk-1.0', version: peas_req_version)
 totem_plparser_dep = dependency('totem-plparser', version: totem_plparser_req_version)
@@ -208,7 +209,7 @@
 endif
 
 # libportal support
-libportal_dep = dependency('libportal-gtk3', required: get_option('libportal'))
+libportal_dep = dependency('libportal-gtk3', version: libportal_req_version, required: get_option('libportal'))
 have_libportal = libportal_dep.found()
 
 configure_file(
@@ -220,7 +221,7 @@
 i18n = import('i18n')
 pkg = import('pkgconfig')
 
-po_dir = join_paths(meson.source_root(), 'po')
+po_dir = join_paths(meson.project_source_root(), 'po')
 
 top_inc = include_directories('.')
 
@@ -245,21 +246,21 @@
   totem_minor_version != 'rc')
 if is_stable
   meson.add_dist_script(
-    find_program('check-news.sh').path(),
+    find_program('check-news.sh').full_path(),
     '@0@'.format(meson.project_version()),
     'NEWS',
     'data/appdata/org.gnome.Totem.appdata.xml.in.in'
   )
 else
   meson.add_dist_script(
-    find_program('check-news.sh').path(),
+    find_program('check-news.sh').full_path(),
     '@0@'.format(meson.project_version()),
     'NEWS',
   )
 endif
 
 meson.add_dist_script(
-  find_program('remove-flatpak-dist.sh').path()
+  find_program('remove-flatpak-dist.sh').full_path()
 )
 
 message('Totem was configured with the following options:')
diff -Nru totem-43.1/NEWS totem-43.2/NEWS
--- totem-43.1/NEWS	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/NEWS	2025-05-21 14:08:29.000000000 +0100
@@ -1,5 +1,21 @@
 New features and significant updates in version...
 
+Major changes in 43.2:
+- Implement a gtksink video output fallback if native OpenGL support is
+  not available.
+- Fix a lot of thumbnailing failures caused by memory hungry video decoders
+- Hide the rotate menu items if rotation is not supported
+- Fix some AVI files not being associated correctly
+- Fix widget focus when starting video playback
+- Fix left-over files when streaming a video and the player is closed
+- Fix window not being matched to the application under Wayland
+- Stop using gnome-shell to flash the screenshot area, that stopped
+  working a long time ago
+- Stop thumbnailing m3u playlists
+- Remove obsolete plugins (apple-trailers, vimeo)
+- Fix a number of possible crashers
+- Translation updates
+
 Major changes in 43.1:
 - Fix scroll-by-page GTK setting breaking slider
 - Fix a number of MPRIS playback controls not working correctly
diff -Nru totem-43.1/po/LINGUAS totem-43.2/po/LINGUAS
--- totem-43.1/po/LINGUAS	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/po/LINGUAS	2025-05-21 14:08:29.000000000 +0100
@@ -90,6 +90,7 @@
 tr
 ug
 uk
+uz
 vi
 wa
 xh
diff -Nru totem-43.1/src/backend/bacon-video-widget.c totem-43.2/src/backend/bacon-video-widget.c
--- totem-43.1/src/backend/bacon-video-widget.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/backend/bacon-video-widget.c	2025-05-21 14:08:29.000000000 +0100
@@ -63,6 +63,9 @@
 /* for the cover metadata info */
 #include <gst/tag/tag.h>
 
+/* for detecting GL vendor/renderer */
+#include <epoxy/gl.h>
+
 /* system */
 #include <unistd.h>
 #include <time.h>
@@ -192,6 +195,7 @@
   gint64                       current_time;
   gdouble                      current_position;
   gboolean                     is_live;
+  gboolean                     use_gl;
 
   GstTagList                  *tagcache;
   GstTagList                  *audiotags;
@@ -282,6 +286,7 @@
 
 static void bacon_video_widget_finalize (GObject * object);
 
+static void bvw_init_video_sink (BaconVideoWidget *bvw);
 static void bvw_reconfigure_fill_timeout (BaconVideoWidget *bvw, guint msecs);
 static void bvw_stop_play_pipeline (BaconVideoWidget * bvw);
 static GError* bvw_error_from_gst_error (BaconVideoWidget *bvw, GstMessage *m);
@@ -433,6 +438,8 @@
 
   GTK_WIDGET_CLASS (parent_class)->realize (widget);
 
+  bvw_init_video_sink (bvw);
+
   window = gtk_widget_get_window (widget);
   display = gdk_window_get_display (window);
   bvw->hand_cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
@@ -3882,9 +3889,12 @@
   bvw->buffering_left = -1;
   bvw_reconfigure_fill_timeout (bvw, 0);
   g_signal_emit (bvw, bvw_signals[SIGNAL_BUFFERING], 0, 100.0);
-  g_object_set (bvw->video_sink,
-                "rotate-method", GST_VIDEO_ORIENTATION_AUTO,
-                NULL);
+
+  if (bvw->use_gl)
+    g_object_set (bvw->video_sink,
+                  "rotate-method", GST_VIDEO_ORIENTATION_AUTO,
+                  NULL);
+
   GST_DEBUG ("stopped");
 }
 
@@ -4493,6 +4503,9 @@
 {
   g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
 
+  if (!bvw->use_gl)
+    return;
+
   GST_DEBUG ("Rotating to %s (%f degrees) from %s",
 	     g_enum_to_string (BVW_TYPE_ROTATION, rotation),
 	     rotation * 90.0,
@@ -4518,6 +4531,22 @@
   return bvw->rotation;
 }
 
+/**
+ * bacon_video_widget_use_gl:
+ * @bvw: a #BaconVideoWidget
+ *
+ * Returns whether gl is used.
+ *
+ * Return value: %TRUE if gl is used, %FALSE otherwise
+ **/
+gboolean
+bacon_video_widget_use_gl (BaconVideoWidget *bvw)
+{
+  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
+
+  return bvw->use_gl;
+}
+
 /* Search for the color balance channel corresponding to type and return it. */
 static GstColorBalanceChannel *
 bvw_get_color_balance_channel (GstColorBalance * color_balance,
@@ -5492,12 +5521,7 @@
 static void
 bacon_video_widget_init (BaconVideoWidget *bvw)
 {
-  GstElement *audio_sink = NULL;
   gchar *version_str;
-  GstPlayFlags flags;
-  GstElement *glsinkbin, *audio_bin;
-  GstPad *audio_pad;
-  char *template;
 
   gtk_widget_set_can_focus (GTK_WIDGET (bvw), TRUE);
 
@@ -5538,19 +5562,84 @@
 			 GDK_BUTTON_RELEASE_MASK |
 			 GDK_KEY_PRESS_MASK);
   gtk_widget_init_template (GTK_WIDGET (bvw));
+}
+
+static inline gboolean
+bvw_gl_check (GtkWidget *widget)
+{
+  static gsize gl_works = 0;
+
+  if (is_feature_enabled ("TOTEM_USE_GST_GTKSINK")) {
+    return FALSE;
+  }
+
+  if (g_once_init_enter (&gl_works)) {
+    GError *error = NULL;
+    gsize works = 1;
+    GdkGLContext *context;
+    GdkWindow *window;
+
+    if ((window = gtk_widget_get_window (widget)) &&
+        (context = gdk_window_create_gl_context (window, &error))) {
+      const gchar *vendor, *renderer;
+
+      gdk_gl_context_make_current (context);
+
+      vendor = (const gchar *) glGetString (GL_VENDOR);
+      renderer = (const gchar *) glGetString (GL_RENDERER);
+
+      GST_INFO ("GL Vendor: %s, renderer: %s", vendor, renderer);
+
+      if (g_str_has_prefix (renderer, "llvmpipe") ||
+          g_str_has_prefix (renderer, "softpipe"))
+        GST_INFO ("Detected software GL rasterizer, falling back to gtksink");
+      else
+        works = 2;
+
+      gdk_gl_context_clear_current ();
+    }
+
+    if (error) {
+      GST_WARNING ("Could not window to create GL context, %s", error->message);
+      g_error_free (error);
+    }
+
+    g_once_init_leave (&gl_works, works);
+  }
+
+  return (gl_works > 1);
+}
+
+static void
+bvw_init_video_sink (BaconVideoWidget *bvw)
+{
+  GstElement *audio_sink = NULL;
+  GstPlayFlags flags;
+  GstElement *glsinkbin = NULL;
+  GstElement *audio_bin;
+  GstPad *audio_pad;
+  char *template;
+
+  bvw->use_gl = bvw_gl_check (GTK_WIDGET (bvw));
 
   /* Instantiate all the fallible plugins */
   bvw->play = element_make_or_warn ("playbin", "play");
   bvw->audio_pitchcontrol = element_make_or_warn ("scaletempo", "scaletempo");
-  bvw->video_sink = element_make_or_warn ("gtkglsink", "video-sink");
-  glsinkbin = element_make_or_warn ("glsinkbin", "glsinkbin");
+
+  if (bvw->use_gl) {
+    bvw->video_sink = element_make_or_warn ("gtkglsink", "video-sink");
+    glsinkbin = element_make_or_warn ("glsinkbin", "glsinkbin");
+  } else {
+    bvw->video_sink = element_make_or_warn ("gtksink", "video-sink");
+  }
+
   audio_sink = element_make_or_warn ("autoaudiosink", "audio-sink");
 
   if (!bvw->play ||
       !bvw->audio_pitchcontrol ||
       !bvw->video_sink ||
       !audio_sink ||
-      !glsinkbin) {
+      (bvw->use_gl && !glsinkbin)) {
     if (bvw->video_sink)
       g_object_ref_sink (bvw->video_sink);
     if (audio_sink)
@@ -5595,23 +5684,34 @@
   if (is_feature_enabled ("FPS_DISPLAY")) {
     GstElement *fps;
     fps = gst_element_factory_make ("fpsdisplaysink", "fpsdisplaysink");
-    g_object_set (glsinkbin, "sink", fps, NULL);
+
+    if (bvw->use_gl)
+      g_object_set (glsinkbin, "sink", fps, NULL);
+    else
+      g_object_set (bvw->play, "video-sink", fps, NULL);
+
     g_object_set (fps, "video-sink", bvw->video_sink, NULL);
   } else {
-    g_object_set (glsinkbin, "sink", bvw->video_sink, NULL);
+    if (bvw->use_gl)
+      g_object_set (glsinkbin, "sink", bvw->video_sink, NULL);
+    else
+      g_object_set (bvw->play, "video-sink", bvw->video_sink, NULL);
   }
+
   g_object_get (bvw->video_sink, "widget", &bvw->video_widget, NULL);
   gtk_widget_show (bvw->video_widget);
   gtk_stack_add_named (GTK_STACK (bvw->stack), bvw->video_widget, "video");
   g_object_unref (bvw->video_widget);
   gtk_stack_set_visible_child_name (GTK_STACK (bvw->stack), "video");
 
-  g_object_set (bvw->video_sink,
-                "rotate-method", GST_VIDEO_ORIENTATION_AUTO,
-                NULL);
+  if (bvw->use_gl)
+    g_object_set (bvw->video_sink,
+                  "rotate-method", GST_VIDEO_ORIENTATION_AUTO,
+                  NULL);
 
   /* And tell playbin */
-  g_object_set (bvw->play, "video-sink", glsinkbin, NULL);
+  if (bvw->use_gl)
+    g_object_set (bvw->play, "video-sink", glsinkbin, NULL);
 
   /* Link the audiopitch element */
   bvw->audio_capsfilter =
diff -Nru totem-43.1/src/backend/bacon-video-widget.h totem-43.2/src/backend/bacon-video-widget.h
--- totem-43.1/src/backend/bacon-video-widget.h	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/backend/bacon-video-widget.h	2025-05-21 14:08:29.000000000 +0100
@@ -282,6 +282,8 @@
 void bacon_video_widget_set_rotation		 (BaconVideoWidget *bvw,
 						  BvwRotation       rotation);
 BvwRotation bacon_video_widget_get_rotation	 (BaconVideoWidget *bvw);
+gboolean bacon_video_widget_use_gl	         (BaconVideoWidget *bvw);
+
 
 int bacon_video_widget_get_video_property        (BaconVideoWidget *bvw,
 						  BvwVideoProperty type);
diff -Nru totem-43.1/src/backend/meson.build totem-43.2/src/backend/meson.build
--- totem-43.1/src/backend/meson.build	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/backend/meson.build	2025-05-21 14:08:29.000000000 +0100
@@ -2,7 +2,7 @@
 
 gst_inspect = find_program(
   'gst-inspect-1.0',
-  join_paths(gst_dep.get_pkgconfig_variable('toolsdir'), 'gst-inspect-1.0'),
+  join_paths(gst_dep.get_variable(pkgconfig : 'toolsdir'), 'gst-inspect-1.0'),
   required: false
 )
 
@@ -23,6 +23,7 @@
 gst_good_plugins = [
   'autoaudiosink',
   'scaletempo',
+  'gtksink',
   'gtkglsink',
   'glsinkbin'
 ]
@@ -73,6 +74,7 @@
   libtotem_time_helpers_dep,
   gtk_dep,
   gmodule_dep,
+  dependency('epoxy'),
 ]
 
 libbacon_video_widget_cflags = common_flags + warn_flags + [
diff -Nru totem-43.1/src/gst/totem-gst-pixbuf-helpers.c totem-43.2/src/gst/totem-gst-pixbuf-helpers.c
--- totem-43.1/src/gst/totem-gst-pixbuf-helpers.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/gst/totem-gst-pixbuf-helpers.c	2025-05-21 14:08:29.000000000 +0100
@@ -47,290 +47,12 @@
   gst_sample_unref (GST_SAMPLE (data));
 }
 
-static gboolean
-caps_are_raw (const GstCaps * caps)
-{
-  guint i, len;
-
-  len = gst_caps_get_size (caps);
-
-  for (i = 0; i < len; i++) {
-    GstStructure *st = gst_caps_get_structure (caps, i);
-    if (gst_structure_has_name (st, "video/x-raw"))
-      return TRUE;
-  }
-
-  return FALSE;
-}
-
-static gboolean
-create_element (const gchar * factory_name, GstElement ** element,
-    GError ** err)
-{
-  *element = gst_element_factory_make (factory_name, NULL);
-  if (*element)
-    return TRUE;
-
-  if (err && *err == NULL) {
-    *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN,
-        "cannot create element '%s' - please check your GStreamer installation",
-        factory_name);
-  }
-
-  return FALSE;
-}
-
-static GstElement *
-build_convert_frame_pipeline (FrameCaptureType capture_type,
-    GstElement ** src_element,
-    GstElement ** sink_element, const GstCaps * from_caps,
-    const GstCaps * to_caps, GError ** err)
-{
-  GstElement *csp = NULL, *vscale = NULL;
-  GstElement *src = NULL, *sink = NULL, *dl = NULL, *pipeline;
-  GError *error = NULL;
-  gboolean ret;
-
-  if (!caps_are_raw (to_caps))
-    goto no_pipeline;
-
-  /* videoscale is here to correct for the pixel-aspect-ratio for us */
-  GST_DEBUG ("creating elements");
-  if (!create_element ("appsrc", &src, &error) ||
-      !create_element ("appsink", &sink, &error))
-    goto no_elements;
-  if (capture_type == FRAME_CAPTURE_TYPE_RAW) {
-      if (!create_element ("videoconvert", &csp, &error) ||
-          !create_element ("videoscale", &vscale, &error))
-        goto no_elements;
-   } else {
-     if (!create_element ("glcolorconvert", &csp, &error) ||
-         !create_element ("glcolorscale", &vscale, &error) ||
-         !create_element ("gldownload", &dl, &error))
-       goto no_elements;
-   }
-
-  pipeline = gst_pipeline_new ("videoconvert-pipeline");
-  if (pipeline == NULL)
-    goto no_pipeline;
-
-  /* Add black borders if necessary to keep the DAR */
-  if (g_object_class_find_property (G_OBJECT_GET_CLASS (vscale), "add-borders"))
-    g_object_set (vscale, "add-borders", TRUE, NULL);
-
-  GST_DEBUG ("adding elements");
-  gst_bin_add_many (GST_BIN (pipeline), src, csp, vscale, sink, dl, NULL);
-
-  /* set caps */
-  g_object_set (src, "caps", from_caps, NULL);
-  g_object_set (sink, "caps", to_caps, NULL);
-
-  if (dl)
-    ret = gst_element_link_many (src, csp, vscale, dl, sink, NULL);
-  else
-    ret = gst_element_link_many (src, csp, vscale, sink, NULL);
-  if (!ret)
-    goto link_failed;
-
-  g_object_set (src, "emit-signals", TRUE, NULL);
-  g_object_set (sink, "emit-signals", TRUE, NULL);
-
-  *src_element = src;
-  *sink_element = sink;
-
-  return pipeline;
-  /* ERRORS */
-no_elements:
-  {
-    if (src)
-      gst_object_unref (src);
-    if (csp)
-      gst_object_unref (csp);
-    if (vscale)
-      gst_object_unref (vscale);
-    if (dl)
-      gst_object_unref (dl);
-    if (sink)
-      gst_object_unref (sink);
-    GST_ERROR ("Could not convert video frame: %s", error->message);
-    if (err)
-      *err = error;
-    else
-      g_error_free (error);
-    return NULL;
-  }
-no_pipeline:
-  {
-    gst_object_unref (src);
-    gst_object_unref (csp);
-    gst_object_unref (vscale);
-    g_clear_pointer (&dl, gst_object_unref);
-    gst_object_unref (sink);
-
-    GST_ERROR ("Could not convert video frame: no pipeline (unknown error)");
-    if (err)
-      *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
-          "Could not convert video frame: no pipeline (unknown error)");
-    return NULL;
-  }
-link_failed:
-  {
-    gst_object_unref (pipeline);
-
-    GST_ERROR ("Could not convert video frame: failed to link elements");
-    if (err)
-      *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION,
-          "Could not convert video frame: failed to link elements");
-    return NULL;
-  }
-}
-
-/**
- * totem_gst_video_convert_sample:
- * @capture_type: capture type
- * @sample: a #GstSample
- * @to_caps: the #GstCaps to convert to
- * @timeout: the maximum amount of time allowed for the processing.
- * @error: pointer to a #GError. Can be %NULL.
- *
- * Converts a raw video buffer into the specified output caps.
- *
- * The output caps can be any raw video formats or any image formats (jpeg, png, ...).
- *
- * The width, height and pixel-aspect-ratio can also be specified in the output caps.
- *
- * Returns: The converted #GstSample, or %NULL if an error happened (in which case @err
- * will point to the #GError).
- */
-static GstSample *
-totem_gst_video_convert_sample (FrameCaptureType capture_type,
-				GstSample * sample, const GstCaps * to_caps,
-				GstClockTime timeout, GError ** error)
-{
-  GstMessage *msg;
-  GstBuffer *buf;
-  GstSample *result = NULL;
-  GError *err = NULL;
-  GstBus *bus;
-  GstCaps *from_caps, *to_caps_copy = NULL;
-  GstFlowReturn ret;
-  GstElement *pipeline, *src, *sink;
-  guint i, n;
-
-  g_return_val_if_fail (sample != NULL, NULL);
-  g_return_val_if_fail (to_caps != NULL, NULL);
-
-  buf = gst_sample_get_buffer (sample);
-  g_return_val_if_fail (buf != NULL, NULL);
-
-  from_caps = gst_sample_get_caps (sample);
-  g_return_val_if_fail (from_caps != NULL, NULL);
-
-  to_caps_copy = gst_caps_new_empty ();
-  n = gst_caps_get_size (to_caps);
-  for (i = 0; i < n; i++) {
-    GstStructure *s = gst_caps_get_structure (to_caps, i);
-
-    s = gst_structure_copy (s);
-    gst_structure_remove_field (s, "framerate");
-    gst_caps_append_structure (to_caps_copy, s);
-  }
-
-  pipeline =
-      build_convert_frame_pipeline (capture_type, &src, &sink, from_caps,
-      to_caps_copy, &err);
-  if (!pipeline)
-    goto no_pipeline;
-
-  /* now set the pipeline to the paused state, after we push the buffer into
-   * appsrc, this should preroll the converted buffer in appsink */
-  GST_DEBUG ("running conversion pipeline to caps %" GST_PTR_FORMAT,
-      to_caps_copy);
-  if (gst_element_set_state (pipeline,
-          GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE)
-    goto state_change_failed;
-
-  /* feed buffer in appsrc */
-  GST_DEBUG ("feeding buffer %p, size %" G_GSIZE_FORMAT ", caps %"
-      GST_PTR_FORMAT, buf, gst_buffer_get_size (buf), from_caps);
-  g_signal_emit_by_name (src, "push-buffer", buf, &ret);
-
-  /* now see what happens. We either got an error somewhere or the pipeline
-   * prerolled */
-  bus = gst_element_get_bus (pipeline);
-  msg = gst_bus_timed_pop_filtered (bus,
-      timeout, GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE);
-
-  if (msg) {
-    switch (GST_MESSAGE_TYPE (msg)) {
-      case GST_MESSAGE_ASYNC_DONE:
-      {
-        /* we're prerolled, get the frame from appsink */
-        g_signal_emit_by_name (sink, "pull-preroll", &result);
-
-        if (result) {
-          GST_DEBUG ("conversion successful: result = %p", result);
-        } else {
-          GST_ERROR ("prerolled but no result frame?!");
-        }
-        break;
-      }
-      case GST_MESSAGE_ERROR:{
-        gchar *dbg = NULL;
-
-        gst_message_parse_error (msg, &err, &dbg);
-        if (err) {
-          GST_ERROR ("Could not convert video frame: %s", err->message);
-          GST_DEBUG ("%s [debug: %s]", err->message, GST_STR_NULL (dbg));
-          if (error)
-            *error = err;
-          else
-            g_error_free (err);
-        }
-        g_free (dbg);
-        break;
-      }
-      default:{
-        g_return_val_if_reached (NULL);
-      }
-    }
-    gst_message_unref (msg);
-  } else {
-    GST_ERROR ("Could not convert video frame: timeout during conversion");
-    if (error)
-      *error = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
-          "Could not convert video frame: timeout during conversion");
-  }
-
-  gst_element_set_state (pipeline, GST_STATE_NULL);
-  gst_object_unref (bus);
-  gst_object_unref (pipeline);
-  gst_caps_unref (to_caps_copy);
-
-  return result;
-
-  /* ERRORS */
-no_pipeline:
-state_change_failed:
-  {
-    gst_caps_unref (to_caps_copy);
-
-    if (error)
-      *error = err;
-    else
-      g_error_free (err);
-
-    return NULL;
-  }
-}
-
 GdkPixbuf *
 totem_gst_playbin_get_frame (GstElement *play, GError **error)
 {
   FrameCaptureType capture_type;
   GstStructure *s;
   GstSample *sample = NULL;
-  GstSample *last_sample = NULL;
   guint bpp;
   GdkPixbuf *pixbuf = NULL;
   GstCaps *to_caps, *sample_caps;
@@ -359,19 +81,12 @@
       NULL);
 
   /* get frame */
-  g_object_get (G_OBJECT (play), "sample", &last_sample, NULL);
-  if (!last_sample) {
-    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                         "Failed to retrieve video frame");
-    return NULL;
-  }
-  sample = totem_gst_video_convert_sample (capture_type, last_sample, to_caps, 25 * GST_SECOND, error);
-  gst_sample_unref (last_sample);
+  g_signal_emit_by_name (play, "convert-sample", to_caps, &sample);
   gst_caps_unref (to_caps);
 
   if (!sample) {
     g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                         "Failed to convert video frame");
+                         "Failed to retrieve or convert video frame");
     return NULL;
   }
 
diff -Nru totem-43.1/src/icon-helpers.c totem-43.2/src/icon-helpers.c
--- totem-43.1/src/icon-helpers.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/icon-helpers.c	2025-05-21 14:08:29.000000000 +0100
@@ -30,7 +30,7 @@
 #define GNOME_DESKTOP_USE_UNSTABLE_API 1
 #include <libgnome-desktop/gnome-desktop-thumbnail.h>
 
-#define DEFAULT_MAX_THREADS   1
+#define DEFAULT_MAX_THREADS   g_get_num_processors ()
 #define THUMB_SEARCH_SIZE     256
 #define THUMB_SEARCH_HEIGHT   THUMB_SEARCH_SIZE
 #define SOURCES_MAX_HEIGHT    64
diff -Nru totem-43.1/src/plugins/open-directory/totem-open-directory.c totem-43.2/src/plugins/open-directory/totem-open-directory.c
--- totem-43.1/src/plugins/open-directory/totem-open-directory.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/plugins/open-directory/totem-open-directory.c	2025-05-21 14:08:29.000000000 +0100
@@ -135,11 +135,17 @@
 	GMenu *menu;
 	GMenuItem *item;
 	char *mrl;
+	g_autoptr(GError) error = NULL;
 
 	pi->totem = g_object_get_data (G_OBJECT (plugin), "object");
-	pi->portal = xdp_portal_new ();
+	pi->portal = xdp_portal_initable_new (&error);
 	pi->cancellable = g_cancellable_new ();
 
+	if (error) {
+		g_warning ("Failed to create XdpPortal instance: %s", error->message);
+		return;
+	}
+
 	g_signal_connect (pi->totem,
 			  "file-opened",
 			  G_CALLBACK (totem_open_directory_file_opened),
diff -Nru totem-43.1/src/plugins/pythonconsole/console.py totem-43.2/src/plugins/pythonconsole/console.py
--- totem-43.1/src/plugins/pythonconsole/console.py	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/plugins/pythonconsole/console.py	2025-05-21 14:08:29.000000000 +0100
@@ -291,7 +291,8 @@
             except SyntaxError:
                 exec(command, self.namespace) # pylint: disable=W0122
         except: # pylint: disable=W0702
-            if hasattr(sys, 'last_type') and sys.last_type == SystemExit: # pylint: disable=E1101
+            last_type, = sys.exc_info()
+            if last_type == SystemExit:
                 self.destroy()
             else:
                 traceback.print_exc()
diff -Nru totem-43.1/src/plugins/recent/totem-recent.c totem-43.2/src/plugins/recent/totem-recent.c
--- totem-43.1/src/plugins/recent/totem-recent.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/plugins/recent/totem-recent.c	2025-05-21 14:08:29.000000000 +0100
@@ -80,7 +80,7 @@
 	}
 
 	data.app_name = g_strdup (g_get_application_name ());
-	data.app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
+	data.app_exec = g_strdup ("totem %u");
 	data.groups = groups;
 	if (gtk_recent_manager_add_full (pi->recent_manager,
 					 uri, &data) == FALSE) {
diff -Nru totem-43.1/src/plugins/rotation/totem-rotation.c totem-43.2/src/plugins/rotation/totem-rotation.c
--- totem-43.1/src/plugins/rotation/totem-rotation.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/plugins/rotation/totem-rotation.c	2025-05-21 14:08:29.000000000 +0100
@@ -219,6 +219,11 @@
 
 	pi->totem = g_object_get_data (G_OBJECT (plugin), "object");
 	pi->bvw = totem_object_get_video_widget (pi->totem);
+
+	/* rotate-method is not supported by gtksink */
+	if (!bacon_video_widget_use_gl (BACON_VIDEO_WIDGET (pi->bvw)))
+		return;
+
 	pi->cancellable = g_cancellable_new ();
 
 	g_signal_connect (pi->totem,
@@ -290,5 +295,5 @@
 	g_action_map_remove_action (G_ACTION_MAP (pi->totem), "rotate-right");
 
 	pi->totem = NULL;
-	pi->bvw = NULL;
+	g_clear_object (&pi->bvw);
 }
diff -Nru totem-43.1/src/plugins/save-file/totem-save-file.c totem-43.2/src/plugins/save-file/totem-save-file.c
--- totem-43.1/src/plugins/save-file/totem-save-file.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/plugins/save-file/totem-save-file.c	2025-05-21 14:08:29.000000000 +0100
@@ -477,7 +477,7 @@
 	}
 
 	pi->totem = NULL;
-	pi->bvw = NULL;
+	g_clear_object (&pi->bvw);
 
 	g_clear_pointer (&pi->mrl, g_free);
 	g_clear_pointer (&pi->cache_mrl, g_free);
diff -Nru totem-43.1/src/plugins/screenshot/totem-screenshot-plugin.c totem-43.2/src/plugins/screenshot/totem-screenshot-plugin.c
--- totem-43.1/src/plugins/screenshot/totem-screenshot-plugin.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/plugins/screenshot/totem-screenshot-plugin.c	2025-05-21 14:08:29.000000000 +0100
@@ -152,51 +152,6 @@
 	g_object_unref (save_file);
 }
 
-static void
-flash_area_done_cb (GObject *source_object,
-		    GAsyncResult *res,
-		    gpointer user_data)
-{
-	GVariant *variant;
-
-	variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, NULL);
-	if (variant != NULL)
-		g_variant_unref (variant);
-}
-
-static void
-flash_area (GtkWidget *widget)
-{
-	GDBusProxy *proxy;
-	GdkWindow *window;
-	int x, y, w, h;
-
-	window = gtk_widget_get_window (widget);
-	gdk_window_get_origin (window, &x, &y);
-	w = gdk_window_get_width (window);
-	h = gdk_window_get_height (window);
-
-	proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
-					       G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
-					       G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
-					       G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
-					       NULL,
-					       "org.gnome.Shell",
-					       "/org/gnome/Shell/Screenshot",
-					       "org.gnome.Shell.Screenshot",
-					       NULL, NULL);
-	if (proxy == NULL)
-		g_warning ("no proxy");
-
-	g_dbus_proxy_call (proxy, "org.gnome.Shell.Screenshot.FlashArea",
-			   g_variant_new ("(iiii)", x, y, w, h),
-			   G_DBUS_CALL_FLAGS_NO_AUTO_START,
-			   -1,
-			   NULL,
-			   flash_area_done_cb,
-			   NULL);
-}
-
 static char *
 escape_video_name (const char *orig)
 {
@@ -224,8 +179,6 @@
 		return;
 	}
 
-	flash_area (GTK_WIDGET (pi->bvw));
-
 	pixbuf = bacon_video_widget_get_current_frame (pi->bvw);
 	if (pixbuf == NULL) {
 		totem_object_show_error (pi->totem, _("Videos could not get a screenshot of the video."), _("This is not supposed to happen; please file a bug report."));
diff -Nru totem-43.1/src/totem.c totem-43.2/src/totem.c
--- totem-43.1/src/totem.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/totem.c	2025-05-21 14:08:29.000000000 +0100
@@ -47,7 +47,7 @@
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 	textdomain (GETTEXT_PACKAGE);
 
-	g_set_prgname ("totem");
+	g_set_prgname (APPLICATION_ID);
 #if DEVELOPMENT_VERSION
 	g_set_application_name (_("Videos Preview"));
 #else
diff -Nru totem-43.1/src/totem-object.c totem-43.2/src/totem-object.c
--- totem-43.1/src/totem-object.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/totem-object.c	2025-05-21 14:08:29.000000000 +0100
@@ -268,8 +268,6 @@
 
 	totem_callback_connect (totem);
 
-	gtk_widget_grab_focus (GTK_WIDGET (totem->bvw));
-
 	/* The prefs after the video widget is connected */
 	totem->prefs = totem_preferences_dialog_new (totem);
 	gtk_window_set_transient_for (GTK_WINDOW (totem->prefs), GTK_WINDOW(totem->win));
@@ -1077,6 +1075,8 @@
 		gtk_widget_show (totem->subtitles_button);
 		gtk_widget_hide (totem->add_button);
 		gtk_widget_hide (totem->main_menu_button);
+
+		gtk_widget_grab_focus (GTK_WIDGET (totem->bvw));
 		show_popup (totem);
 	} else if (g_strcmp0 (page_id, "grilo") == 0) {
 		totem_grilo_start (TOTEM_GRILO (totem->grilo));
@@ -1379,8 +1379,11 @@
 	if (totem == NULL)
 		exit (0);
 
-	if (totem->bvw)
+	if (totem->bvw) {
 		totem_object_save_size (totem);
+		bacon_video_widget_close (totem->bvw);
+		g_clear_object (&totem->bvw);
+	}
 
 	if (totem->win != NULL) {
 		gtk_widget_hide (totem->win);
diff -Nru totem-43.1/src/totem-playlist.c totem-43.2/src/totem-playlist.c
--- totem-43.1/src/totem-playlist.c	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/totem-playlist.c	2025-05-21 14:08:29.000000000 +0100
@@ -1744,7 +1744,7 @@
 	 * hence the "steal" in the API name */
 	gtk_list_store_set (GTK_LIST_STORE (playlist->model),
 			    &iter,
-			    STARTTIME_COL, 0,
+			    STARTTIME_COL, (gint64) 0,
 			    -1);
 
 	return starttime;
diff -Nru totem-43.1/src/totem-resources.c totem-43.2/src/totem-resources.c
--- totem-43.1/src/totem-resources.c	2025-06-11 11:27:22.000000000 +0100
+++ totem-43.2/src/totem-resources.c	2025-05-21 14:08:29.000000000 +0100
@@ -49,7 +49,7 @@
 static gboolean finished = TRUE;
 
 static void
-set_resource_limits (const char *input)
+set_resource_limits (const char *input, gboolean verbose)
 {
 #ifdef G_OS_UNIX
 	struct rlimit limit;
@@ -81,6 +81,10 @@
 	limit.rlim_cur = MAX_HELPER_SECONDS;
 	limit.rlim_max = MAX_HELPER_SECONDS;
 	setrlimit (RLIMIT_CPU, &limit);
+
+	if (verbose)
+		g_message ("Setting limit to %lu MB RAM usage and %d seconds CPU time",
+			   max / 1024 / 1024, MAX_HELPER_SECONDS);
 #else
 #warning unimplemented
 #endif
@@ -108,9 +112,9 @@
 }
 
 void
-totem_resources_monitor_start (const char *input, gint wall_clock_time)
+totem_resources_monitor_start (const char *input, gint wall_clock_time, gboolean verbose)
 {
-	set_resource_limits (input);
+	set_resource_limits (input, verbose);
 
 	if (wall_clock_time < 0)
 		return;
diff -Nru totem-43.1/src/totem-resources.h totem-43.2/src/totem-resources.h
--- totem-43.1/src/totem-resources.h	2024-10-22 17:04:07.000000000 +0100
+++ totem-43.2/src/totem-resources.h	2025-05-21 14:08:29.000000000 +0100
@@ -28,6 +28,7 @@
 #include <glib.h>
 
 void totem_resources_monitor_start	(const char *input,
-					 gint wall_clock_time);
+					 gint wall_clock_time,
+					 gboolean verbose);
 void totem_resources_monitor_stop	(void);
 
diff -Nru totem-43.1/src/totem-video-thumbnailer.c totem-43.2/src/totem-video-thumbnailer.c
--- totem-43.1/src/totem-video-thumbnailer.c	2025-06-11 11:27:22.000000000 +0100
+++ totem-43.2/src/totem-video-thumbnailer.c	2025-05-21 14:08:29.000000000 +0100
@@ -377,6 +377,9 @@
 	return async_received;
 }
 
+/* Manually set number of worker threads for decoders in order to reduce memory
+ * usage on setups with many cores, see
+ * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4423 */
 static void
 element_setup_cb (GstElement * playbin, GstElement * element, gpointer udata)
 {
@@ -637,14 +640,8 @@
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 	textdomain (GETTEXT_PACKAGE);
 
-	/* Limit the number of BLAS threads to avoid reaching our RLIMIT_DATA
-	 * address space max size safeguard for the thumbnailer.
-	 * This as GStreamer plugins call into OpenBLAS for linear algebra
-	 * which automatically spawns as many threads as there are CPU cores
-	 * and allocates static buffers for each of them.
-	 * Thus our 512MB address space limit is too short for the video
-	 * file size plus the currently 128 MB per OpenBLAS thread
-	 * when we reach 4 CPU cores. */
+	/* Limit the number of OpenBLAS threads to avoid reaching our RLIMIT_DATA
+	 * address space max size safeguard for the thumbnailer. */
 	g_setenv("OMP_NUM_THREADS", "1", TRUE);
 
 	/* Call before the global thread pool is setup */
@@ -695,7 +692,7 @@
 	PRINT_PROGRESS (6.0);
 
 	if (time_limit != FALSE)
-		totem_resources_monitor_start (input, 0);
+		totem_resources_monitor_start (input, 0, verbose);
 
 	PROGRESS_DEBUG("About to open video file");
 

--- End Message ---
--- Begin Message ---
Unblocked.

--- End Message ---

Reply to: