[totem/wip/hadess/glsink: 9/13] backend: Port to gtkglsink




commit c13d2fd323a3d5b8b095db2c33d9aef81af04cd2
Author: Bastien Nocera <hadess hadess net>
Date:   Thu Jan 27 14:12:47 2022 +0100

    backend: Port to gtkglsink
    
    Replace the clutter-gtk based video widget with a native GL GStreamer
    widget, "gtkglsink".
    
    - Display aspect-ratio support for non-square pixels was removed. While
      it still worked correctly (you can try setting your display's resolution
      to a different aspect ratio), things like text and icons, and everything
      else in every application and the shell chrome would have been looked
      broken, including the video player. Except the video in the video player.
    - Video aspect ratio, pillar-boxing, letter-boxing and automatic rotation
      is now handled in the GStreamer widget
    - The placeholder logos, when playing files with unsupported video, or
      no video tracks have been changed.
    - Handling of mouse events has been simplified
    
    Some functionality could not be brought forward at this time:
    - Crop-zooming (available using the R/T keys) isn't implemented yet
    - Gestures support, which never worked properly anyway, wasn't
      reimplemented

 data/controls.ui                      |   5 +
 docs/reference/meson.build            |   4 -
 meson.build                           |   1 -
 src/backend/bacon-video-widget.c      | 570 ++++++----------------------------
 src/backend/bacon-video-widget.h      |  11 +-
 src/backend/bvw-test.c                |   6 +-
 src/backend/meson.build               |   8 -
 src/meson.build                       |   4 -
 src/plugins/rotation/totem-rotation.c |   5 -
 src/totem-object.c                    |  95 ++++--
 src/totem-private.h                   |   6 +-
 11 files changed, 178 insertions(+), 537 deletions(-)
---
diff --git a/data/controls.ui b/data/controls.ui
index a7ebe9468..a9b1b59e4 100644
--- a/data/controls.ui
+++ b/data/controls.ui
@@ -9,6 +9,11 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="border_width">0</property>
+        <property name="opacity">0.86</property>
+        <style>
+          <class name="osd"/>
+          <class name="bottom"/>
+        </style>
         <child>
           <object class="GtkToolItem" id="controls_toolbutton">
             <property name="visible">True</property>
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index 6eec8d9d1..0aab998d7 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -2,15 +2,11 @@ doc_module = meson.project_name()
 
 private_headers = [
   'bacon-time-label.h',
-  'bacon-video-controls-actor.h',
-  'bacon-video-spinner-actor.h',
   'bacon-video-widget-gst-missing-plugins.h',
   'bacon-video-widget-properties.h',
-  'clock.h',
   'gd-tagged-entry.h',
   'icon-helpers.h',
   'screenshot-filename-builder.h',
-  'totem-aspect-frame.h',
   'totem-gallery-progress.h',
   'totem-gallery.h',
   'totem-grilo.h',
diff --git a/meson.build b/meson.build
index 802b51fd5..5c47a380c 100644
--- a/meson.build
+++ b/meson.build
@@ -150,7 +150,6 @@ gst_pbutils_dep = dependency('gstreamer-pbutils-1.0')
 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)
-clutter_gtk_dep = dependency('clutter-gtk-1.0', version: '>= 1.8.1')
 m_dep = cc.find_library('m', required: true)
 
 libgd = subproject(
diff --git a/src/backend/bacon-video-widget.c b/src/backend/bacon-video-widget.c
index 6320919a3..e7070d25d 100644
--- a/src/backend/bacon-video-widget.c
+++ b/src/backend/bacon-video-widget.c
@@ -63,9 +63,6 @@
 /* for the cover metadata info */
 #include <gst/tag/tag.h>
 
-#include <clutter-gst/clutter-gst.h>
-#include "totem-aspect-frame.h"
-
 /* system */
 #include <unistd.h>
 #include <time.h>
@@ -83,8 +80,6 @@
 #include "totem-gst-pixbuf-helpers.h"
 #include "bacon-video-widget.h"
 #include "bacon-video-widget-gst-missing-plugins.h"
-#include "bacon-video-controls-actor.h"
-#include "bacon-video-spinner-actor.h"
 #include "bacon-video-widget-enums.h"
 
 #define DEFAULT_USER_AGENT "Videos/"VERSION
@@ -162,7 +157,7 @@ static const gchar *video_props_str[4] = {
 
 struct _BaconVideoWidget
 {
-  GtkClutterEmbed              parent;
+  GtkOverlay                   parent;
 
   char                        *user_agent;
 
@@ -178,8 +173,6 @@ struct _BaconVideoWidget
   guint                        update_id;
   guint                        fill_id;
 
-  GdkPixbuf                   *logo_pixbuf;
-
   gboolean                     media_has_video;
   gboolean                     media_has_audio;
   gint                         seekable; /* -1 = don't know, FALSE = no */
@@ -197,15 +190,7 @@ struct _BaconVideoWidget
 
   gboolean                     got_redirect;
 
-  ClutterActor                *stage;
-  ClutterActor                *texture;
-  ClutterActor                *frame;
-  ClutterActor                *header_controls;
-  ClutterActor                *controls;
-  ClutterActor                *spinner;
-
-  ClutterActor                *logo_frame;
-  ClutterContent              *logo;
+  GtkWidget                   *stack;
 
   GdkCursor                   *cursor;
 
@@ -230,10 +215,6 @@ struct _BaconVideoWidget
   
   gint                         video_width; /* Movie width */
   gint                         video_height; /* Movie height */
-  gint                         movie_par_n; /* Movie pixel aspect ratio numerator */
-  gint                         movie_par_d; /* Movie pixel aspect ratio denominator */
-  gint                         video_width_pixels; /* Scaled movie width */
-  gint                         video_height_pixels; /* Scaled movie height */
   gint                         video_fps_n;
   gint                         video_fps_d;
 
@@ -279,7 +260,7 @@ struct _BaconVideoWidget
   float                        rate;
 };
 
-G_DEFINE_TYPE_WITH_CODE (BaconVideoWidget, bacon_video_widget, GTK_CLUTTER_TYPE_EMBED,
+G_DEFINE_TYPE_WITH_CODE (BaconVideoWidget, bacon_video_widget, GTK_TYPE_OVERLAY,
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
                                                bacon_video_widget_initable_iface_init))
 
@@ -398,182 +379,6 @@ bvw_check_if_video_decoder_is_missing (BaconVideoWidget * bvw)
   }
 }
 
-static void
-set_display_pixel_aspect_ratio (GdkMonitor *monitor,
-                               GValue    *value)
-{
-  static const gint par[][2] = {
-    {1, 1},                     /* regular screen */
-    {16, 15},                   /* PAL TV */
-    {11, 10},                   /* 525 line Rec.601 video */
-    {54, 59},                   /* 625 line Rec.601 video */
-    {64, 45},                   /* 1280x1024 on 16:9 display */
-    {5, 3},                     /* 1280x1024 on 4:3 display */
-    {4, 3}                      /* 800x600 on 16:9 display */
-  };
-  guint i;
-  gint par_index;
-  gdouble ratio;
-  gdouble delta;
-  GdkRectangle rect;
-
-#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
-
-  /* first calculate the "real" ratio based on the X values;
-   * which is the "physical" w/h divided by the w/h in pixels of the display */
-  gdk_monitor_get_geometry (monitor, &rect);
-
-  ratio = (gdouble) (gdk_monitor_get_width_mm (monitor) * rect.height) /
-    (gdk_monitor_get_height_mm (monitor) * rect.width);
-
-  GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
-  /* now find the one from par[][2] with the lowest delta to the real one */
-  delta = DELTA (0);
-  par_index = 0;
-
-  for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
-    gdouble this_delta = DELTA (i);
-
-    if (this_delta < delta) {
-      par_index = i;
-      delta = this_delta;
-    }
-  }
-
-  GST_DEBUG ("Decided on index %d (%d/%d)", par_index,
-            par[par_index][0], par[par_index][1]);
-  gst_value_set_fraction (value, par[par_index][0], par[par_index][1]);
-}
-
-static void
-get_media_size (BaconVideoWidget *bvw, gint *width, gint *height)
-{
-  if (bvw->media_has_video) {
-    GValue disp_par = {0, };
-    guint movie_par_n, movie_par_d, disp_par_n, disp_par_d, num, den;
-
-    /* Create and init the fraction value */
-    g_value_init (&disp_par, GST_TYPE_FRACTION);
-
-    /* Square pixel is our default */
-    gst_value_set_fraction (&disp_par, 1, 1);
-
-    /* Now try getting display's pixel aspect ratio */
-    if (gtk_widget_get_realized (GTK_WIDGET (bvw))) {
-      GdkDisplay *display;
-      GdkWindow *window;
-      GdkMonitor *monitor;
-
-      display = gtk_widget_get_display (GTK_WIDGET (bvw));
-      window = gtk_widget_get_window (GTK_WIDGET (bvw));
-      if (window)
-        monitor = gdk_display_get_monitor_at_window (display, window);
-      else
-        monitor = gdk_display_get_primary_monitor (display);
-      set_display_pixel_aspect_ratio (monitor, &disp_par);
-    }
-
-    disp_par_n = gst_value_get_fraction_numerator (&disp_par);
-    disp_par_d = gst_value_get_fraction_denominator (&disp_par);
-
-    GST_DEBUG ("display PAR is %d/%d", disp_par_n, disp_par_d);
-
-    /* If movie pixel aspect ratio is enforced, use that */
-    if (bvw->ratio_type != BVW_RATIO_AUTO) {
-      switch (bvw->ratio_type) {
-        case BVW_RATIO_SQUARE:
-          movie_par_n = 1;
-          movie_par_d = 1;
-          break;
-        case BVW_RATIO_FOURBYTHREE:
-          movie_par_n = 4 * bvw->video_height;
-          movie_par_d = 3 * bvw->video_width;
-          break;
-        case BVW_RATIO_ANAMORPHIC:
-          movie_par_n = 16 * bvw->video_height;
-          movie_par_d = 9 * bvw->video_width;
-          break;
-        case BVW_RATIO_DVB:
-          movie_par_n = 20 * bvw->video_height;
-          movie_par_d = 9 * bvw->video_width;
-          break;
-        /* handle these to avoid compiler warnings */
-        case BVW_RATIO_AUTO:
-        default:
-          movie_par_n = 0;
-          movie_par_d = 0;
-          g_assert_not_reached ();
-      }
-    } else {
-      /* Use the movie pixel aspect ratio if any */
-      movie_par_n = bvw->movie_par_n;
-      movie_par_d = bvw->movie_par_d;
-    }
-
-    GST_DEBUG ("movie PAR is %d/%d", movie_par_n, movie_par_d);
-
-    if (bvw->video_width == 0 || bvw->video_height == 0) {
-      GST_DEBUG ("width and/or height 0, assuming 1/1 ratio");
-      num = 1;
-      den = 1;
-    } else if (!gst_video_calculate_display_ratio (&num, &den,
-        bvw->video_width, bvw->video_height,
-        movie_par_n, movie_par_d, disp_par_n, disp_par_d)) {
-      GST_WARNING ("overflow calculating display aspect ratio!");
-      num = 1;   /* FIXME: what values to use here? */
-      den = 1;
-    }
-
-    GST_DEBUG ("calculated scaling ratio %d/%d for video %dx%d", num, den,
-        bvw->video_width, bvw->video_height);
-
-    /* now find a width x height that respects this display ratio.
-     * prefer those that have one of w/h the same as the incoming video
-     * using wd / hd = num / den */
-
-    /* start with same height, because of interlaced video */
-    /* check hd / den is an integer scale factor, and scale wd with the PAR */
-    if (bvw->video_height % den == 0) {
-      GST_DEBUG ("keeping video height");
-      bvw->video_width_pixels =
-          (guint) gst_util_uint64_scale (bvw->video_height, num, den);
-      bvw->video_height_pixels = bvw->video_height;
-    } else if (bvw->video_width % num == 0) {
-      GST_DEBUG ("keeping video width");
-      bvw->video_width_pixels = bvw->video_width;
-      bvw->video_height_pixels =
-          (guint) gst_util_uint64_scale (bvw->video_width, den, num);
-    } else {
-      GST_DEBUG ("approximating while keeping video height");
-      bvw->video_width_pixels =
-          (guint) gst_util_uint64_scale (bvw->video_height, num, den);
-      bvw->video_height_pixels = bvw->video_height;
-    }
-    GST_DEBUG ("scaling to %dx%d", bvw->video_width_pixels,
-        bvw->video_height_pixels);
-
-    *width = bvw->video_width_pixels;
-    *height = bvw->video_height_pixels;
-
-    /* Free the PAR fraction */
-    g_value_unset (&disp_par);
-  }
-  else {
-    if (bvw->logo_pixbuf) {
-      *width = gdk_pixbuf_get_width (bvw->logo_pixbuf);
-      *height = gdk_pixbuf_get_height (bvw->logo_pixbuf);
-      if (*width == *height) {
-       /* The icons will be square, so lie so we get a 16:9
-        * ratio */
-       *width = (int) ((float) *height / 9. * 16.);
-      }
-    } else {
-      *width = 0;
-      *height = 0;
-    }
-  }
-}
-
 static gboolean
 leave_notify_cb (GtkWidget        *widget,
                 GdkEventCrossing *event,
@@ -604,22 +409,6 @@ leave_notify_cb (GtkWidget        *widget,
   return res;
 }
 
-static void
-bvw_set_logo (BaconVideoWidget *bvw, const gchar *name)
-{
-  GtkIconTheme *theme;
-  GError *error = NULL;
-
-  theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (bvw)));
-  bvw->logo_pixbuf = gtk_icon_theme_load_icon (theme, name, LOGO_SIZE, 0, &error);
-
-  if (error) {
-    g_warning ("An error occurred trying to open logo %s: %s", name, error->message);
-    g_error_free (error);
-    return;
-  }
-}
-
 static void
 bacon_video_widget_realize (GtkWidget * widget)
 {
@@ -630,8 +419,6 @@ bacon_video_widget_realize (GtkWidget * widget)
 
   gtk_widget_set_realized (widget, TRUE);
 
-  bvw_set_logo (bvw, APPLICATION_ID);
-
   /* setup the toplevel, ready to be resized */
   toplevel = gtk_widget_get_toplevel (widget);
   gtk_window_set_geometry_hints (GTK_WINDOW (toplevel), widget, NULL, 0);
@@ -668,37 +455,10 @@ set_current_actor (BaconVideoWidget *bvw)
 {
   gboolean draw_logo;
 
-  if (bvw->stage == NULL)
-    return;
-
-  /* If there's only audio draw the logo as well. */
+  /* If there's only audio draw the logo */
   draw_logo = bvw->media_has_audio && !bvw->media_has_video;
-
-  if (draw_logo) {
-    if (bvw->logo_pixbuf != NULL) {
-      gboolean ret;
-      GError *err = NULL;
-
-      ret = clutter_image_set_data (CLUTTER_IMAGE (bvw->logo),
-                                   gdk_pixbuf_get_pixels (bvw->logo_pixbuf),
-                                   gdk_pixbuf_get_has_alpha (bvw->logo_pixbuf) ? COGL_PIXEL_FORMAT_RGBA_8888 
: COGL_PIXEL_FORMAT_RGB_888,
-                                   gdk_pixbuf_get_width (bvw->logo_pixbuf),
-                                   gdk_pixbuf_get_height (bvw->logo_pixbuf),
-                                   gdk_pixbuf_get_rowstride (bvw->logo_pixbuf),
-                                   &err);
-      if (ret == FALSE) {
-       g_warning ("clutter_image_set_data() failed %s", err->message);
-       g_error_free (err);
-      } else {
-       clutter_actor_show (CLUTTER_ACTOR (bvw->logo_frame));
-       clutter_actor_hide (CLUTTER_ACTOR (bvw->frame));
-       return;
-      }
-    }
-  }
-
-  clutter_actor_show (CLUTTER_ACTOR (bvw->frame));
-  clutter_actor_hide (CLUTTER_ACTOR (bvw->logo_frame));
+  gtk_stack_set_visible_child_name (GTK_STACK (bvw->stack),
+                                   draw_logo ? "logo" : "video");
 }
 
 static void
@@ -755,6 +515,7 @@ set_controls_visibility (BaconVideoWidget *bvw,
                         gboolean          visible,
                         gboolean          animate)
 {
+#if 0
   guint8 opacity = visible ? OVERLAY_OPACITY : 0;
   gint header_controls_height;
   gfloat header_controls_y;
@@ -781,6 +542,7 @@ set_controls_visibility (BaconVideoWidget *bvw,
 
   bvw->reveal_controls = visible;
   g_object_notify (G_OBJECT (bvw), "reveal-controls");
+#endif
 }
 
 static void
@@ -807,6 +569,7 @@ ignore_event (BaconVideoWidget *bvw,
              int               x,
              int               y)
 {
+#if 0
   ClutterActor *actor;
 
   actor = clutter_stage_get_actor_at_pos (CLUTTER_STAGE (bvw->stage), CLUTTER_PICK_REACTIVE, x, y);
@@ -814,7 +577,7 @@ ignore_event (BaconVideoWidget *bvw,
   /* Eat the GTK+ event if we're not clicking on the video itself */
   if (actor == bvw->controls)
     return TRUE;
-
+#endif
   return FALSE;
 }
 
@@ -910,7 +673,7 @@ bacon_video_widget_handle_scroll (GtkWidget        *widget,
   gdouble delta_y;
 
   g_return_val_if_fail (bvw->play != NULL, FALSE);
-
+#if 0
   if (event->direction != GDK_SCROLL_SMOOTH)
     return GDK_EVENT_PROPAGATE;
 
@@ -933,7 +696,7 @@ bacon_video_widget_handle_scroll (GtkWidget        *widget,
     if (bacon_video_widget_can_set_volume (bvw))
       g_signal_emit (G_OBJECT (bvw), bvw_signals[SIGNAL_VOLUME_CHANGE_REQUESTED], 0, forward);
   }
-
+#endif
   return GDK_EVENT_STOP;
 }
 
@@ -980,8 +743,6 @@ bacon_video_widget_class_init (BaconVideoWidgetClass * klass)
   GObjectClass *object_class;
   GtkWidgetClass *widget_class;
 
-  clutter_gst_init (NULL, NULL);
-
   object_class = (GObjectClass *) klass;
   widget_class = (GtkWidgetClass *) klass;
 
@@ -1395,14 +1156,13 @@ bacon_video_widget_init (BaconVideoWidget * bvw)
   g_type_class_ref (BVW_TYPE_DVD_EVENT);
   g_type_class_ref (BVW_TYPE_ROTATION);
 
-  g_object_set (G_OBJECT (bvw), "use-layout-size", TRUE, NULL);
+  //g_object_set (G_OBJECT (bvw), "use-layout-size", TRUE, NULL);
 
   bvw->update_id = 0;
   bvw->tagcache = NULL;
   bvw->audiotags = NULL;
   bvw->videotags = NULL;
   bvw->volume = -1.0;
-  bvw->movie_par_n = bvw->movie_par_d = 1;
   bvw->rate = FORWARD_RATE;
 
   bvw->tag_update_queue = g_async_queue_new_full ((GDestroyNotify) update_tags_delayed_data_destroy);
@@ -1455,15 +1215,7 @@ bvw_handle_application_message (BaconVideoWidget *bvw, GstMessage *msg)
     bvw_update_stream_info (bvw);
   }
   else if (strcmp (msg_name, "video-size") == 0) {
-    int w, h;
-
     g_signal_emit (bvw, bvw_signals[SIGNAL_GOT_METADATA], 0, NULL);
-
-    /* This is necessary for the pixel-aspect-ratio of the
-     * display to be taken into account. */
-    get_media_size (bvw, &w, &h);
-    clutter_actor_set_size (bvw->texture, w, h);
-
     set_current_actor (bvw);
   } else {
     g_debug ("Unhandled application message %s", msg_name);
@@ -1976,37 +1728,6 @@ bvw_check_missing_plugins_on_preroll (BaconVideoWidget * bvw)
   return bvw_emit_missing_plugins_signal (bvw, TRUE); 
 }
 
-static void
-update_orientation_from_video (BaconVideoWidget *bvw)
-{
-  BvwRotation rotation = BVW_ROTATION_R_ZERO;
-  char *orientation_str = NULL;
-  gboolean ret;
-  gdouble angle;
-
-  /* Don't change the rotation if explicitely set */
-  if (bvw->rotation != BVW_ROTATION_R_ZERO)
-    return;
-
-  ret = gst_tag_list_get_string_index (bvw->tagcache,
-                                      GST_TAG_IMAGE_ORIENTATION, 0, &orientation_str);
-  if (!ret || !orientation_str || g_str_equal (orientation_str, "rotate-0"))
-    rotation = BVW_ROTATION_R_ZERO;
-  else if (g_str_equal (orientation_str, "rotate-90"))
-    rotation = BVW_ROTATION_R_90R;
-  else if (g_str_equal (orientation_str, "rotate-180"))
-    rotation = BVW_ROTATION_R_180;
-  else if (g_str_equal (orientation_str, "rotate-270"))
-    rotation = BVW_ROTATION_R_90L;
-  else
-    g_warning ("Unhandled orientation value: '%s'", orientation_str);
-
-  g_free (orientation_str);
-
-  angle = rotation * 90.0;
-  totem_aspect_frame_set_rotation (TOTEM_ASPECT_FRAME (bvw->frame), angle);
-}
-
 static void
 bvw_update_tags (BaconVideoWidget * bvw, GstTagList *tag_list, const gchar *type)
 {
@@ -2048,8 +1769,6 @@ bvw_update_tags (BaconVideoWidget * bvw, GstTagList *tag_list, const gchar *type
 
   g_signal_emit (bvw, bvw_signals[SIGNAL_GOT_METADATA], 0);
 
-  update_orientation_from_video (bvw);
-
   set_current_actor (bvw);
 }
 
@@ -2214,15 +1933,6 @@ bvw_handle_buffering_message (GstMessage * message, BaconVideoWidget *bvw)
   gst_message_parse_buffering (message, &percent);
   g_signal_emit (bvw, bvw_signals[SIGNAL_BUFFERING], 0, (gdouble) percent / 100.0);
 
-  if (percent >= 100) {
-    clutter_actor_hide (bvw->spinner);
-    /* Reset */
-    g_object_set (G_OBJECT (bvw->spinner), "percent", 0.0, NULL);
-  } else {
-    clutter_actor_show (bvw->spinner);
-    g_object_set (G_OBJECT (bvw->spinner), "percent", (float) percent, NULL);
-  }
-
   if (percent >= 100) {
     /* a 100% message means buffering is done */
     bvw->buffering = FALSE;
@@ -2833,29 +2543,12 @@ caps_set (GObject * obj,
   /* Get video decoder caps */
   s = gst_caps_get_structure (caps, 0);
   if (s) {
-    const GValue *movie_par;
-
     /* We need at least width/height and framerate */
-    if (!(gst_structure_get_fraction (s, "framerate", &bvw->video_fps_n, 
+    if (!(gst_structure_get_fraction (s, "framerate", &bvw->video_fps_n,
           &bvw->video_fps_d) &&
           gst_structure_get_int (s, "width", &bvw->video_width) &&
           gst_structure_get_int (s, "height", &bvw->video_height)))
       return;
-    
-    /* Get the movie PAR if available */
-    movie_par = gst_structure_get_value (s, "pixel-aspect-ratio");
-    if (movie_par) {
-      bvw->movie_par_n = gst_value_get_fraction_numerator (movie_par);
-      bvw->movie_par_d = gst_value_get_fraction_denominator (movie_par);
-    }
-    else {
-      /* Square pixels */
-      bvw->movie_par_n = 1;
-      bvw->movie_par_d = 1;
-    }
-    
-    /* Now set for real */
-    bacon_video_widget_set_aspect_ratio (bvw, bvw->ratio_type);
   }
 
   gst_caps_unref (caps);
@@ -3732,6 +3425,7 @@ void
 bacon_video_widget_unmark_popup_busy (BaconVideoWidget *bvw,
                                      const char       *reason)
 {
+#if 0
   g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
 
   g_hash_table_remove (bvw->busy_popup_ht, reason);
@@ -3743,40 +3437,7 @@ bacon_video_widget_unmark_popup_busy (BaconVideoWidget *bvw,
     GST_DEBUG ("Will hide popup soon");
     schedule_hiding_popup (bvw);
   }
-}
-
-/**
- * bacon_video_widget_get_controls_object:
- * @bvw: a #BaconVideoWidget
- *
- * Get the widget which displays the video controls.
- *
- * Returns: (transfer none): controls widget
- * Since: 3.12
- */
-GObject *
-bacon_video_widget_get_controls_object (BaconVideoWidget *bvw)
-{
-  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), NULL);
-
-  return G_OBJECT (bvw->controls);
-}
-
-/**
- * bacon_video_widget_get_header_controls_object:
- * @bvw: a #BaconVideoWidget
- *
- * Get the widget which displays the video header controls.
- *
- * Returns: (transfer none): header controls widget
- * Since: 3.20
- */
-GObject *
-bacon_video_widget_get_header_controls_object (BaconVideoWidget *bvw)
-{
-  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), NULL);
-
-  return G_OBJECT (gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (bvw->header_controls)));
+#endif
 }
 
 /* =========================================== */
@@ -4328,10 +3989,10 @@ bvw_stop_play_pipeline (BaconVideoWidget * bvw)
   g_clear_pointer (&bvw->download_filename, g_free);
   bvw->buffering_left = -1;
   bvw_reconfigure_fill_timeout (bvw, 0);
-  bvw->movie_par_n = bvw->movie_par_d = 1;
-  clutter_actor_hide (bvw->spinner);
-  g_object_set (G_OBJECT (bvw->spinner), "percent", 0.0, NULL);
-  totem_aspect_frame_set_internal_rotation (TOTEM_ASPECT_FRAME (bvw->frame), 0.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);
   GST_DEBUG ("stopped");
 }
 
@@ -4804,18 +4465,41 @@ bacon_video_widget_get_volume (BaconVideoWidget * bvw)
  **/
 void
 bacon_video_widget_set_aspect_ratio (BaconVideoWidget *bvw,
-                                BvwAspectRatio ratio)
+                                     BvwAspectRatio ratio)
 {
-  GstMessage *msg;
-
   g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
 
   bvw->ratio_type = ratio;
-  msg = gst_message_new_application (GST_OBJECT (bvw->play),
-      gst_structure_new ("video-size", "width", G_TYPE_INT,
-          bvw->video_width, "height", G_TYPE_INT,
-          bvw->video_height, NULL));
-  gst_element_post_message (bvw->play, msg);
+
+  switch (bvw->ratio_type) {
+  case BVW_RATIO_SQUARE:
+    g_object_set (bvw->video_sink,
+                 "video-aspect-ratio-override", 1, 1,
+                 NULL);
+    break;
+  case BVW_RATIO_FOURBYTHREE:
+    g_object_set (bvw->video_sink,
+                 "video-aspect-ratio-override", 4, 3,
+                 NULL);
+    break;
+  case BVW_RATIO_ANAMORPHIC:
+    g_object_set (bvw->video_sink,
+                 "video-aspect-ratio-override", 16, 9,
+                 NULL);
+    break;
+  case BVW_RATIO_DVB:
+    g_object_set (bvw->video_sink,
+                 "video-aspect-ratio-override", 20, 9,
+                 NULL);
+    break;
+    /* handle these to avoid compiler warnings */
+  case BVW_RATIO_AUTO:
+  default:
+    g_object_set (bvw->video_sink,
+                 "video-aspect-ratio-override", 0, 1,
+                 NULL);
+    break;
+  }
 }
 
 /**
@@ -4848,11 +4532,7 @@ bacon_video_widget_set_zoom (BaconVideoWidget *bvw,
 {
   g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
 
-  if (bvw->frame == NULL)
-    return;
-
-  totem_aspect_frame_set_expand (TOTEM_ASPECT_FRAME (bvw->frame),
-                             (mode == BVW_ZOOM_EXPAND));
+  g_debug ("%s not implemented", G_STRFUNC);
 }
 
 /**
@@ -4868,10 +4548,10 @@ bacon_video_widget_get_zoom (BaconVideoWidget *bvw)
 {
   gboolean expand;
 
-  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 1.0);
+  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), BVW_ZOOM_NONE);
 
-  expand = totem_aspect_frame_get_expand (TOTEM_ASPECT_FRAME (bvw->frame));
-  return expand ? BVW_ZOOM_EXPAND : BVW_ZOOM_NONE;
+  g_debug ("%s not implemented", G_STRFUNC);
+  return BVW_ZOOM_NONE;
 }
 
 /**
@@ -4885,22 +4565,15 @@ void
 bacon_video_widget_set_rotation (BaconVideoWidget *bvw,
                                 BvwRotation       rotation)
 {
-  gfloat angle;
-
   g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
 
-  if (bvw->frame == NULL)
-    return;
-
   GST_DEBUG ("Rotating to %s (%f degrees) from %s",
             g_enum_to_string (BVW_TYPE_ROTATION, rotation),
             rotation * 90.0,
             g_enum_to_string (BVW_TYPE_ROTATION, bvw->rotation));
 
   bvw->rotation = rotation;
-
-  angle = rotation * 90.0;
-  totem_aspect_frame_set_rotation (TOTEM_ASPECT_FRAME (bvw->frame), angle);
+  g_object_set (bvw->video_sink, "rotate-method", rotation, NULL);
 }
 
 /**
@@ -5861,59 +5534,6 @@ bvw_set_playback_direction (BaconVideoWidget *bvw, gboolean forward)
   return retval;
 }
 
-static gboolean
-navigation_event (ClutterActor *actor,
-                  ClutterEvent *event,
-                  BaconVideoWidget *bvw)
-{
-  ClutterGstFrame *frame =
-    clutter_gst_video_sink_get_frame (CLUTTER_GST_VIDEO_SINK (bvw->video_sink));
-  gfloat actor_width, actor_height;
-  gfloat x, y;
-
-  if (frame == NULL)
-    return CLUTTER_EVENT_PROPAGATE;
-
-  /* Get event coordinates into the actor's coordinates. */
-  clutter_event_get_coords (event, &x, &y);
-  clutter_actor_transform_stage_point (actor, x, y, &x, &y);
-
-  clutter_actor_get_size (actor, &actor_width, &actor_height);
-
-  /* Convert event's coordinates into the frame's coordinates. */
-  x = x * frame->resolution.width / actor_width;
-  y = y * frame->resolution.height / actor_height;
-
-  if (event->type == CLUTTER_MOTION) {
-    gst_navigation_send_mouse_event (GST_NAVIGATION (bvw->video_sink),
-                                     "mouse-move", 0, x, y);
-  } else if (event->type == CLUTTER_BUTTON_PRESS ||
-             event->type == CLUTTER_BUTTON_RELEASE) {
-    ClutterButtonEvent *bevent = (ClutterButtonEvent *) event;
-    const char *type = (event->type == CLUTTER_BUTTON_PRESS) ?
-      "mouse-button-press" : "mouse-button-release";
-    gst_navigation_send_mouse_event (GST_NAVIGATION (bvw->video_sink), type,
-                                     bevent->button, x, y);
-  }
-
-  return CLUTTER_EVENT_PROPAGATE;
-}
-
-static void
-listen_navigation_events (ClutterActor *actor,
-                          BaconVideoWidget *bvw)
-{
-  const char * const events[] = {
-    "button-press-event",
-    "button-release-event",
-    "motion-event"
-  };
-  guint i;
-
-  for (i = 0; i < G_N_ELEMENTS (events); i++)
-    g_signal_connect (actor, events[i], G_CALLBACK (navigation_event), bvw);
-}
-
 static GstElement *
 element_make_or_warn (const char *plugin,
                      const char *name)
@@ -5934,8 +5554,9 @@ bacon_video_widget_initable_init (GInitable     *initable,
   GstElement *audio_sink = NULL;
   gchar *version_str;
   GstPlayFlags flags;
-  ClutterActor *layout;
-  GstElement *audio_bin;
+  GtkWidget *tmp;
+  //ClutterActor *layout;
+  GstElement *glsinkbin, *audio_bin;
   GstPad *audio_pad;
   GObject *item;
   char *template;
@@ -5955,10 +5576,19 @@ bacon_video_widget_initable_init (GInitable     *initable,
 
   gst_pb_utils_init ();
 
+  gtk_widget_set_events (GTK_WIDGET (bvw),
+                        gtk_widget_get_events (GTK_WIDGET (bvw)) |
+                        GDK_POINTER_MOTION_MASK |
+                        GDK_BUTTON_MOTION_MASK |
+                        GDK_BUTTON_PRESS_MASK |
+                        GDK_BUTTON_RELEASE_MASK |
+                        GDK_KEY_PRESS_MASK);
+
   /* 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 = GST_ELEMENT (clutter_gst_video_sink_new ());
+  bvw->video_sink = element_make_or_warn ("gtkglsink", "video-sink");
+  glsinkbin = element_make_or_warn ("glsinkbin", "glsinkbin");
   audio_sink = element_make_or_warn ("autoaudiosink", "audio-sink");
 
   if (!bvw->play ||
@@ -6000,43 +5630,26 @@ bacon_video_widget_initable_init (GInitable     *initable,
 
   bvw->cursor_shown = TRUE;
 
-  bvw->stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (bvw));
-  clutter_actor_set_text_direction (bvw->stage,
-                                   CLUTTER_TEXT_DIRECTION_LTR);
-  clutter_actor_set_layout_manager (bvw->stage,
-                                    clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_FILL, 
CLUTTER_BIN_ALIGNMENT_FILL));
-  clutter_actor_set_name (bvw->stage, "stage");
-  clutter_actor_set_background_color (bvw->stage, CLUTTER_COLOR_Black);
-
-  /* Video sink, with aspect frame */
-  bvw->texture = g_object_new (CLUTTER_TYPE_ACTOR,
-                                     "content", g_object_new (CLUTTER_GST_TYPE_CONTENT,
-                                                              "sink", bvw->video_sink,
-                                                              NULL),
-                                    "name", "texture",
-                                    "reactive", TRUE,
-                                    NULL);
-  listen_navigation_events (bvw->texture, bvw);
-
-  /* The logo */
-  bvw->logo_frame = clutter_actor_new ();
-  clutter_actor_set_name (bvw->logo_frame, "logo-frame");
-  bvw->logo = clutter_image_new ();
-  clutter_actor_set_content (bvw->logo_frame, bvw->logo);
-  clutter_actor_set_content_gravity (bvw->logo_frame, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
-  clutter_actor_add_child (bvw->stage, bvw->logo_frame);
-  clutter_actor_hide (CLUTTER_ACTOR (bvw->logo_frame));
-
-  /* The video */
-  bvw->frame = totem_aspect_frame_new ();
-  clutter_actor_set_name (bvw->frame, "frame");
-  totem_aspect_frame_set_child (TOTEM_ASPECT_FRAME (bvw->frame), bvw->texture);
-
-  clutter_actor_add_child (bvw->stage, bvw->frame);
+  /* Create video output widget and logo */
+  bvw->stack = gtk_stack_new ();
+  gtk_container_add (GTK_CONTAINER (bvw), bvw->stack);
+  gtk_widget_show (bvw->stack);
 
-  clutter_actor_set_child_above_sibling (bvw->stage,
-                                        bvw->logo_frame,
-                                        bvw->frame);
+  g_object_set (glsinkbin, "sink", bvw->video_sink, NULL);
+  g_object_get (bvw->video_sink, "widget", &tmp, NULL);
+  gtk_stack_add_named (GTK_STACK (bvw->stack), tmp, "video");
+  gtk_widget_show (tmp);
+  g_object_unref (tmp);
+
+  tmp = gtk_image_new_from_icon_name ("video-x-generic-symbolic", GTK_ICON_SIZE_DIALOG);
+  gtk_image_set_pixel_size (GTK_IMAGE (tmp), LOGO_SIZE);
+  gtk_stack_add_named (GTK_STACK (bvw->stack), tmp, "logo");
+  gtk_widget_show (tmp);
+
+  g_object_set (bvw->video_sink,
+                "rotate-method", GST_VIDEO_ORIENTATION_AUTO,
+                NULL);
+#if 0
 
   /* The spinner */
   bvw->spinner = bacon_video_spinner_actor_new ();
@@ -6084,9 +5697,9 @@ bacon_video_widget_initable_init (GInitable     *initable,
   item = g_object_get_data (G_OBJECT (bvw->controls), "volume_button");
   g_signal_connect (item, "scroll-event",
                    G_CALLBACK (bacon_video_widget_handle_scroll), bvw);
-
+#endif
   /* And tell playbin */
-  g_object_set (bvw->play, "video-sink", bvw->video_sink, NULL);
+  g_object_set (bvw->play, "video-sink", glsinkbin, NULL);
 
   /* Link the audiopitch element */
   bvw->audio_capsfilter =
@@ -6236,7 +5849,8 @@ bacon_video_widget_set_fullscreen (BaconVideoWidget *bvw,
 {
   g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
 
-  g_object_set (bvw->header_controls, "visible", fullscreen, NULL);
+  //FIXME
+  //g_object_set (bvw->header_controls, "visible", fullscreen, NULL);
 }
 
 /*
diff --git a/src/backend/bacon-video-widget.h b/src/backend/bacon-video-widget.h
index 734dbdbe9..4b90bf0cc 100644
--- a/src/backend/bacon-video-widget.h
+++ b/src/backend/bacon-video-widget.h
@@ -27,14 +27,10 @@
 
 #pragma once
 
-#include <clutter-gtk/clutter-gtk.h>
-
-#ifndef glib_autoptr_clear_GtkClutterEmbed
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkClutterEmbed, g_object_unref)
-#endif
+#include <gtk/gtk.h>
 
 #define BACON_TYPE_VIDEO_WIDGET                     (bacon_video_widget_get_type ())
-G_DECLARE_FINAL_TYPE(BaconVideoWidget, bacon_video_widget, BACON, VIDEO_WIDGET, GtkClutterEmbed)
+G_DECLARE_FINAL_TYPE(BaconVideoWidget, bacon_video_widget, BACON, VIDEO_WIDGET, GtkOverlay)
 #define BVW_ERROR bacon_video_widget_error_quark ()
 
 /**
@@ -422,6 +418,3 @@ void bacon_video_widget_mark_popup_busy           (BaconVideoWidget *bvw,
                                                   const char       *reason);
 void bacon_video_widget_unmark_popup_busy         (BaconVideoWidget *bvw,
                                                   const char       *reason);
-
-GObject * bacon_video_widget_get_controls_object  (BaconVideoWidget *bvw);
-GObject * bacon_video_widget_get_header_controls_object (BaconVideoWidget *bvw);
diff --git a/src/backend/bvw-test.c b/src/backend/bvw-test.c
index 60c173234..97ff7d934 100644
--- a/src/backend/bvw-test.c
+++ b/src/backend/bvw-test.c
@@ -85,9 +85,6 @@ int main
        XInitThreads ();
 #endif
 
-       if (gtk_clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
-               g_assert_not_reached ();
-
        context = g_option_context_new ("- Play audio and video inside a web browser");
        baconoptiongroup = bacon_video_widget_get_option_group();
        g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE);
@@ -123,6 +120,7 @@ int main
        g_signal_connect (G_OBJECT (bvw), "got-redirect", G_CALLBACK (on_redirect), NULL);
        g_signal_connect (G_OBJECT (bvw), "error", G_CALLBACK (error_cb), NULL);
 
+#if 0
        box = g_object_get_data (bacon_video_widget_get_controls_object (BACON_VIDEO_WIDGET (bvw)), 
"controls_box");
 
        /* Previous */
@@ -150,7 +148,7 @@ int main
        gtk_button_set_image (GTK_BUTTON (item), image);
 
        gtk_widget_show_all (GTK_WIDGET (box));
-
+#endif
        gtk_container_add (GTK_CONTAINER (win),bvw);
 
        gtk_widget_realize (GTK_WIDGET (win));
diff --git a/src/backend/meson.build b/src/backend/meson.build
index c6df9b150..effdfe60e 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -35,12 +35,8 @@ endforeach
 
 sources = files(
   'bacon-time-label.c',
-  'bacon-video-controls-actor.c',
-  'bacon-video-spinner-actor.c',
   'bacon-video-widget-gst-missing-plugins.c',
   'bacon-video-widget.c',
-  'clock.c',
-  'totem-aspect-frame.c'
 )
 
 enum_headers = files('bacon-video-widget.h')
@@ -62,10 +58,6 @@ libbacon_video_widget_deps = [
   gst_tag_dep,
   dependency('gstreamer-audio-1.0'),
   gst_video_dep,
-  dependency('clutter-1.0', version: '>= 1.17.3'),
-  dependency('clutter-gst-3.0', version: '>= 2.99.2'),
-  clutter_gtk_dep,
-  dependency('cairo', version: '>= 1.14.0'),
   dependency('gsettings-desktop-schemas'),
   m_dep,
   libtotem_gst_helpers_dep,
diff --git a/src/meson.build b/src/meson.build
index b74fc1a6c..bc371baf3 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -6,12 +6,8 @@ subdir('backend')
 
 enum_headers = files(
   'backend/bacon-time-label.h',
-  'backend/bacon-video-controls-actor.h',
-  'backend/bacon-video-spinner-actor.h',
   'backend/bacon-video-widget-gst-missing-plugins.h',
   'backend/bacon-video-widget.h',
-  'backend/clock.h',
-  'backend/totem-aspect-frame.h',
   'icon-helpers.h',
   'totem-grilo.h',
   'totem-interface.h',
diff --git a/src/plugins/rotation/totem-rotation.c b/src/plugins/rotation/totem-rotation.c
index 3402de98c..087915a09 100644
--- a/src/plugins/rotation/totem-rotation.c
+++ b/src/plugins/rotation/totem-rotation.c
@@ -160,8 +160,6 @@ update_state (TotemRotationPlugin *pi,
        TotemRotationPluginPrivate *priv = pi->priv;
 
        if (mrl == NULL) {
-               bacon_video_widget_set_rotation (BACON_VIDEO_WIDGET (priv->bvw),
-                                        BVW_ROTATION_R_ZERO);
                g_simple_action_set_enabled (priv->rotate_left_action, FALSE);
                g_simple_action_set_enabled (priv->rotate_right_action, FALSE);
        } else {
@@ -298,9 +296,6 @@ impl_deactivate (PeasActivatable *plugin)
        g_action_map_remove_action (G_ACTION_MAP (priv->totem), "rotate-left");
        g_action_map_remove_action (G_ACTION_MAP (priv->totem), "rotate-right");
 
-       bacon_video_widget_set_rotation (BACON_VIDEO_WIDGET (priv->bvw),
-                                        BVW_ROTATION_R_ZERO);
-
        priv->totem = NULL;
        priv->bvw = NULL;
 }
diff --git a/src/totem-object.c b/src/totem-object.c
index bd8fde913..217cbc169 100644
--- a/src/totem-object.c
+++ b/src/totem-object.c
@@ -206,11 +206,30 @@ totem_object_app_activate (GApplication *app)
 
        totem->controls_visibility = TOTEM_CONTROLS_UNDEFINED;
 
-       totem->seek = g_object_get_data (totem->controls, "seek_scale");
+       totem->controls = gtk_builder_new ();
+       const char *objects[] = { "toolbar", NULL };
+       GError *error = NULL;
+        if (gtk_builder_add_objects_from_file (totem->controls, DATADIR "/totem/controls.ui", (gchar **) 
objects, &error) == 0)
+               g_assert_not_reached ();
+       gtk_grid_attach (GTK_GRID (totem->bvw_grid),
+                        GTK_WIDGET (gtk_builder_get_object (totem->controls, "toolbar")),
+                        0, 4, 3, 1);
+       gtk_widget_set_hexpand (GTK_WIDGET (gtk_builder_get_object (totem->controls, "toolbar")), TRUE);
+       gtk_widget_set_vexpand (GTK_WIDGET (gtk_builder_get_object (totem->controls, "toolbar")), TRUE);
+       gtk_widget_set_valign (GTK_WIDGET (gtk_builder_get_object (totem->controls, "toolbar")), 
GTK_ALIGN_END);
+
+       //FIXME SPINNER should replace the play button, controls popup when needed
+       totem->spinner = gtk_spinner_new ();
+       //totem->spinner = gtk_label_new ("<span size='xx-large'>100%</span>");
+       gtk_grid_attach (GTK_GRID (totem->bvw_grid), totem->spinner, 1, 2, 1, 1);
+       gtk_widget_set_vexpand (totem->spinner, TRUE);
+       gtk_widget_set_hexpand (totem->spinner, TRUE);
+
+       totem->seek = GTK_WIDGET (gtk_builder_get_object (totem->controls, "seek_scale"));
        totem->seekadj = gtk_range_get_adjustment (GTK_RANGE (totem->seek));
-       totem->volume = g_object_get_data (totem->controls, "volume_button");
-       totem->time_label = g_object_get_data (totem->controls, "time_label");
-       totem->time_rem_label = g_object_get_data (totem->controls, "time_rem_label");
+       totem->volume = GTK_WIDGET (gtk_builder_get_object (totem->controls, "volume_button"));
+       totem->time_label = BACON_TIME_LABEL (gtk_builder_get_object (totem->controls, "time_label"));
+       totem->time_rem_label = BACON_TIME_LABEL (gtk_builder_get_object (totem->controls, "time_rem_label"));
        totem->pause_start = optionstate.pause;
 
        totem_callback_connect (totem);
@@ -503,9 +522,6 @@ totem_object_class_init (TotemObjectClass *klass)
 static void
 totem_object_init (TotemObject *totem)
 {
-       if (gtk_clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
-               g_warning ("gtk-clutter failed to initialise, expect problems from here on.");
-
        totem->settings = g_settings_new (TOTEM_GSETTINGS_SCHEMA);
 
        g_application_add_main_option_entries (G_APPLICATION (totem), all_options);
@@ -1633,8 +1649,9 @@ window_state_event_cb (GtkWidget           *window,
                show_controls (totem, TRUE);
        }
 
-       bacon_video_widget_set_fullscreen (totem->bvw,
-                                          totem->controls_visibility == TOTEM_CONTROLS_FULLSCREEN);
+       g_object_set (totem->fullscreen_header,
+                     "visible", totem->controls_visibility == TOTEM_CONTROLS_FULLSCREEN,
+                     NULL);
 
        action = g_action_map_lookup_action (G_ACTION_MAP (totem), "fullscreen");
        g_simple_action_set_state (G_SIMPLE_ACTION (action),
@@ -1855,7 +1872,7 @@ totem_object_set_mrl (TotemObject *totem,
                /* Subtitle selection */
                totem_object_set_sensitivity2 ("select-subtitle", FALSE);
 
-               /* Set the logo */
+               /* Set the label */
                update_mrl_label (totem, NULL);
 
                g_object_notify (G_OBJECT (totem), "playing");
@@ -2474,9 +2491,30 @@ on_error_event (BaconVideoWidget *bvw, char *message,
 }
 
 static void
-on_buffering_event (BaconVideoWidget *bvw, gdouble percentage, TotemObject *totem)
+on_buffering_event (BaconVideoWidget *bvw, gdouble percent, TotemObject *totem)
 {
-       //FIXME show that somehow
+       if (percent >= 1.0) {
+               gtk_spinner_stop (GTK_SPINNER (totem->spinner));
+               gtk_widget_hide (totem->spinner);
+               //gtk_label_set_markup (GTK_LABEL (totem->spinner), "");
+       } else {
+               g_autofree char *text = NULL;
+
+               text = g_strdup_printf ("<span size='xx-large'>%.2f%%</span>", percent * 100);
+               //gtk_label_set_markup (GTK_LABEL (totem->spinner), text);
+               gtk_widget_show (totem->spinner);
+               gtk_spinner_start (GTK_SPINNER (totem->spinner));
+       }
+}
+
+static gboolean
+fill_up (gpointer user_data)
+{
+       static gfloat percent = 0.0;
+       TotemObject *totem = user_data;
+       on_buffering_event (totem->bvw, percent, totem);
+       percent += 0.01;
+       return G_SOURCE_CONTINUE;
 }
 
 static void
@@ -3811,6 +3849,7 @@ create_control_button (TotemObject *totem,
        gtk_button_set_image (GTK_BUTTON (button), image);
        gtk_widget_set_valign (GTK_WIDGET (button), GTK_ALIGN_CENTER);
        gtk_style_context_add_class (gtk_widget_get_style_context (button), "image-button");
+       g_message ("action_name: %s", action_name);
        if (g_str_equal (action_name, "app.play")) {
                g_object_set (G_OBJECT (image),
                              "margin-start", 16,
@@ -3843,7 +3882,7 @@ totem_callback_connect (TotemObject *totem)
                                   g_variant_new_boolean (totem_playlist_get_repeat (totem->playlist)));
 
        /* Controls */
-       box = g_object_get_data (totem->controls, "controls_box");
+       box = GTK_BOX (gtk_builder_get_object (totem->controls, "controls_box"));
        gtk_widget_insert_action_group (GTK_WIDGET (box), "app", G_ACTION_GROUP (totem));
 
        /* Previous */
@@ -3856,6 +3895,7 @@ totem_callback_connect (TotemObject *totem)
        item = create_control_button (totem, "app.play",
                                      "media-playback-start-symbolic",
                                      _("Play / Pause"));
+       g_assert (item);
        gtk_box_pack_start (box, item, FALSE, FALSE, 0);
 
        /* Next */
@@ -3880,7 +3920,7 @@ totem_callback_connect (TotemObject *totem)
                          G_CALLBACK (volume_button_menu_shown_cb), totem);
 
        /* Go button */
-       item = g_object_get_data (totem->controls, "go_button");
+       item = GTK_WIDGET (gtk_builder_get_object (totem->controls, "go_button"));
        menu = (GMenuModel *) gtk_builder_get_object (totem->xml, "gomenu");
        gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (item), menu);
        popover = gtk_menu_button_get_popover (GTK_MENU_BUTTON (item));
@@ -4029,13 +4069,12 @@ grilo_widget_setup (TotemObject *totem)
 }
 
 static void
-add_fullscreen_toolbar (TotemObject *totem)
+add_fullscreen_toolbar (TotemObject *totem,
+                       GtkWidget   *container)
 {
-       GtkWidget *container, *item;
+       GtkWidget *item;
        GMenuModel *menu;
 
-       container = GTK_WIDGET (bacon_video_widget_get_header_controls_object (totem->bvw));
-
        totem->fullscreen_header = g_object_new (TOTEM_TYPE_MAIN_TOOLBAR,
                                                 "show-search-button", FALSE,
                                                 "show-select-button", FALSE,
@@ -4068,8 +4107,12 @@ add_fullscreen_toolbar (TotemObject *totem)
                          G_CALLBACK (popup_menu_shown_cb), totem);
        totem->fullscreen_gear_button = item;
 
-       gtk_container_add (GTK_CONTAINER (container), totem->fullscreen_header);
+       gtk_grid_attach (GTK_GRID (container), totem->fullscreen_header, 0, 0, 3, 1);
+       gtk_widget_set_halign (totem->fullscreen_header, GTK_ALIGN_FILL);
+       gtk_widget_set_hexpand (totem->fullscreen_header, TRUE);
+       gtk_widget_set_opacity (totem->fullscreen_header, 0.86);
        gtk_widget_show_all (totem->fullscreen_header);
+       gtk_widget_hide (totem->fullscreen_header);
 }
 
 void
@@ -4092,8 +4135,8 @@ video_widget_create (TotemObject *totem)
        window = gtk_widget_get_window (totem->win);
 
        fullscreen = window && ((gdk_window_get_state (window) & GDK_WINDOW_STATE_FULLSCREEN) != 0);
-       bacon_video_widget_set_fullscreen (totem->bvw, fullscreen);
-       totem->controls = bacon_video_widget_get_controls_object (totem->bvw);
+       //FIXME doesn't exist yet
+       //g_object_set (totem->fullscreen_header, "visible", fullscreen, NULL);
 
        g_signal_connect_after (G_OBJECT (totem->bvw),
                        "button-press-event",
@@ -4148,7 +4191,15 @@ video_widget_create (TotemObject *totem)
        gtk_container_add (container,
                        GTK_WIDGET (totem->bvw));
 
-       add_fullscreen_toolbar (totem);
+       //FIXME
+       totem->bvw_grid = gtk_grid_new ();
+       gtk_overlay_add_overlay (GTK_OVERLAY (totem->bvw), totem->bvw_grid);
+       gtk_widget_set_halign (totem->bvw_grid, GTK_ALIGN_FILL);
+       gtk_widget_set_valign (totem->bvw_grid, GTK_ALIGN_FILL);
+       gtk_widget_show (totem->bvw_grid);
+       add_fullscreen_toolbar (totem, totem->bvw_grid);
+
+       //g_timeout_add (250, fill_up, totem);
 
        /* Events for the widget video window as well */
        gtk_widget_add_events (GTK_WIDGET (totem->bvw),
diff --git a/src/totem-private.h b/src/totem-private.h
index de6edb42d..867ba3757 100644
--- a/src/totem-private.h
+++ b/src/totem-private.h
@@ -46,7 +46,7 @@
                widget = GTK_WIDGET (gtk_builder_get_object (xml, name));       \
                gtk_widget_set_sensitive (widget, state);                       \
        }
-#define totem_controls_set_sensitivity(name, state) gtk_widget_set_sensitive (g_object_get_data 
(totem->controls, name), state)
+#define totem_controls_set_sensitivity(name, state) gtk_widget_set_sensitive (GTK_WIDGET 
(gtk_builder_get_object (totem->controls, name)), state)
 
 #define totem_object_set_sensitivity2(name, state)                                     \
        {                                                                               \
@@ -75,12 +75,14 @@ struct _TotemObject {
        GtkWidget *win;
        GtkWidget *stack;
        BaconVideoWidget *bvw;
+       GtkWidget *bvw_grid;
        GtkWidget *prefs;
        GtkWindow *shortcuts_win;
+       GtkWidget *spinner;
 
        GtkWidget *grilo;
 
-       GObject *controls;
+       GtkBuilder *controls;
        GtkWidget *play_button;
        BaconTimeLabel *time_label;
        BaconTimeLabel *time_rem_label;


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