r32195 - in /desktop/experimental/totem/debian: changelog control control.in patches/02_revert_clutter.patch patches/series rules totem-plugins.install
joss at users.alioth.debian.org
joss at users.alioth.debian.org
Sat Dec 17 00:13:07 UTC 2011
Author: joss
Date: Sat Dec 17 00:13:06 2011
New Revision: 32195
URL: http://svn.debian.org/wsvn/pkg-gnome/?sc=1&rev=32195
Log:
* 02_revert_clutter.patch: un-clutter totem. Revert to the good old
XVideo code. It is less elegant, but works on many more systems.
* Update build-dependencies accordingly.
* Use dh-autoreconf.
* Create m4 directory if it does not exist (WTF?)
* Build-depend on gtk-doc-tools for autoreconf.
* totem-plugins.install: remove rotation plugin.
* Drop useless build-dependency on libmusicbrainz.
Added:
desktop/experimental/totem/debian/patches/02_revert_clutter.patch
Modified:
desktop/experimental/totem/debian/changelog
desktop/experimental/totem/debian/control
desktop/experimental/totem/debian/control.in
desktop/experimental/totem/debian/patches/series
desktop/experimental/totem/debian/rules
desktop/experimental/totem/debian/totem-plugins.install
Modified: desktop/experimental/totem/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-gnome/desktop/experimental/totem/debian/changelog?rev=32195&op=diff
==============================================================================
--- desktop/experimental/totem/debian/changelog [utf-8] (original)
+++ desktop/experimental/totem/debian/changelog [utf-8] Sat Dec 17 00:13:06 2011
@@ -1,9 +1,20 @@
-totem (3.2.1-3) UNRELEASED; urgency=low
-
+totem (3.2.1-3) experimental; urgency=low
+
+ [ Michael Biebl ]
* Remove coherence plugin leftovers. It doesn't look like this plugin is
coming back.
- -- Michael Biebl <biebl at debian.org> Wed, 14 Dec 2011 02:11:44 +0100
+ [ Josselin Mouette ]
+ * 02_revert_clutter.patch: un-clutter totem. Revert to the good old
+ XVideo code. It is less elegant, but works on many more systems.
+ * Update build-dependencies accordingly.
+ * Use dh-autoreconf.
+ * Create m4 directory if it does not exist (WTF?)
+ * Build-depend on gtk-doc-tools for autoreconf.
+ * totem-plugins.install: remove rotation plugin.
+ * Drop useless build-dependency on libmusicbrainz.
+
+ -- Josselin Mouette <joss at debian.org> Sat, 17 Dec 2011 01:12:30 +0100
totem (3.2.1-2) experimental; urgency=low
Modified: desktop/experimental/totem/debian/control
URL: http://svn.debian.org/wsvn/pkg-gnome/desktop/experimental/totem/debian/control?rev=32195&op=diff
==============================================================================
--- desktop/experimental/totem/debian/control [utf-8] (original)
+++ desktop/experimental/totem/debian/control [utf-8] Sat Dec 17 00:13:06 2011
@@ -10,6 +10,7 @@
Uploaders: Michael Biebl <biebl at debian.org>
Build-Depends: debhelper (>= 8),
cdbs (>= 0.4.90),
+ dh-autoreconf,
python (>= 2.6.6-3~),
python-gi-dev (>= 2.90.3),
libepc-ui-dev (>= 0.4.0),
@@ -34,7 +35,6 @@
librsvg2-dev (>= 2.16.0-2),
librsvg2-common (>= 2.16.0-2),
libnautilus-extension-dev (>= 2.91.4),
- libmusicbrainz4-dev (>= 2.1.1-4.1),
gnome-icon-theme (>= 2.15.90),
libdbus-glib-1-dev (>= 0.82),
intltool (>= 0.40),
@@ -54,12 +54,10 @@
gir1.2-glib-2.0,
gir1.2-gtk-3.0,
gir1.2-totem-plparser-1.0,
- libclutter-gst-dev (>= 1.3.9),
- libclutter-gtk-1.0-dev (>= 1.0.2),
- libclutter-1.0-dev (>= 1.6.8),
libmx-dev,
libgrilo-0.1-dev,
- valac-0.14
+ valac-0.14,
+ gtk-doc-tools (>= 1.14)
Standards-Version: 3.9.2
Homepage: http://www.gnome.org/projects/totem/
Vcs-Svn: svn://anonscm.debian.org/svn/pkg-gnome/desktop/unstable/totem
Modified: desktop/experimental/totem/debian/control.in
URL: http://svn.debian.org/wsvn/pkg-gnome/desktop/experimental/totem/debian/control.in?rev=32195&op=diff
==============================================================================
--- desktop/experimental/totem/debian/control.in [utf-8] (original)
+++ desktop/experimental/totem/debian/control.in [utf-8] Sat Dec 17 00:13:06 2011
@@ -5,6 +5,7 @@
Uploaders: @GNOME_TEAM@
Build-Depends: debhelper (>= 8),
cdbs (>= 0.4.90),
+ dh-autoreconf,
python (>= 2.6.6-3~),
python-gi-dev (>= 2.90.3),
libepc-ui-dev (>= 0.4.0),
@@ -29,7 +30,6 @@
librsvg2-dev (>= 2.16.0-2),
librsvg2-common (>= 2.16.0-2),
libnautilus-extension-dev (>= 2.91.4),
- libmusicbrainz4-dev (>= 2.1.1-4.1),
gnome-icon-theme (>= 2.15.90),
libdbus-glib-1-dev (>= 0.82),
intltool (>= 0.40),
@@ -49,12 +49,10 @@
gir1.2-glib-2.0,
gir1.2-gtk-3.0,
gir1.2-totem-plparser-1.0,
- libclutter-gst-dev (>= 1.3.9),
- libclutter-gtk-1.0-dev (>= 1.0.2),
- libclutter-1.0-dev (>= 1.6.8),
libmx-dev,
libgrilo-0.1-dev,
- valac-0.14
+ valac-0.14,
+ gtk-doc-tools (>= 1.14)
Standards-Version: 3.9.2
Homepage: http://www.gnome.org/projects/totem/
Vcs-Svn: svn://anonscm.debian.org/svn/pkg-gnome/desktop/unstable/totem
Added: desktop/experimental/totem/debian/patches/02_revert_clutter.patch
URL: http://svn.debian.org/wsvn/pkg-gnome/desktop/experimental/totem/debian/patches/02_revert_clutter.patch?rev=32195&op=file
==============================================================================
--- desktop/experimental/totem/debian/patches/02_revert_clutter.patch (added)
+++ desktop/experimental/totem/debian/patches/02_revert_clutter.patch [utf-8] Sat Dec 17 00:13:06 2011
@@ -1,0 +1,2019 @@
+Reverts upstream commits:
+ cb53bbda 2011-04-04 13:00:50 backend: Use clutter-gst to draw video
+ f782e2e1 2011-04-04 16:14:28 backend: Use copy/pasted version of MxAspectFrame
+ 7e74539e 2011-04-05 18:28:13 backend: Remove some dead code
+ f9e8196b 2011-04-05 18:42:41 build: Update clutter-gst dependency
+ 45cfd99b 2011-04-06 22:05:25 build: Bump clutter-gst reqs
+ 65f5b9e1 2011-04-07 18:40:19 backend: Add FIXME about motion events
+ aa649822 2011-04-08 16:06:04 backend: Remove bacon_video_widget_init_backend()
+ 67ab568f 2011-07-13 12:03:35 backend: name clutter actors so that plugins can query them
+ 0a684af8 2011-08-03 13:00:41 plugins: add rotation plugin
+
+Index: totem-3.2.1/src/backend/bacon-video-widget-gst-0.10.c
+===================================================================
+--- totem-3.2.1.orig/src/backend/bacon-video-widget-gst-0.10.c 2011-12-17 00:28:45.340452915 +0100
++++ totem-3.2.1/src/backend/bacon-video-widget-gst-0.10.c 2011-12-17 00:57:33.420901072 +0100
+@@ -46,6 +46,7 @@
+ #include <gst/gst.h>
+
+ /* GStreamer Interfaces */
++#include <gst/interfaces/xoverlay.h>
+ #include <gst/interfaces/navigation.h>
+ #include <gst/interfaces/colorbalance.h>
+ /* for detecting sources of errors */
+@@ -63,10 +64,6 @@
+ /* for the cover metadata info */
+ #include <gst/tag/tag.h>
+
+-#include <clutter-gst/clutter-gst.h>
+-#include <mx/mx.h>
+-#include "totem-aspect-frame.h"
+-
+ /* system */
+ #include <unistd.h>
+ #include <time.h>
+@@ -91,6 +88,8 @@
+
+ #define FORWARD_RATE 1.0
+ #define REVERSE_RATE -1.0
++#define SMALL_STREAM_WIDTH 200
++#define SMALL_STREAM_HEIGHT 120
+ /* Maximum size of the logo */
+ #define LOGO_SIZE 256
+ #define NANOSECS_IN_SEC 1000000000
+@@ -102,7 +101,7 @@
+
+ #define I_(string) (g_intern_static_string (string))
+
+-G_DEFINE_TYPE (BaconVideoWidget, bacon_video_widget, GTK_CLUTTER_TYPE_EMBED)
++G_DEFINE_TYPE (BaconVideoWidget, bacon_video_widget, GTK_TYPE_EVENT_BOX)
+
+ /* Signals */
+ enum
+@@ -163,8 +162,11 @@ struct BaconVideoWidgetPrivate
+
+ GstElement *play;
+ GstElement *source;
+- GstColorBalance *balance;
+- GstNavigation *navigation;
++ GstXOverlay *xoverlay; /* protect with lock */
++ GstColorBalance *balance; /* protect with lock */
++ GstNavigation *navigation; /* protect with lock */
++ guint interface_update_id; /* protect with lock */
++ GMutex *lock;
+
+ guint update_id;
+ guint fill_id;
+@@ -190,13 +192,7 @@ struct BaconVideoWidgetPrivate
+
+ gboolean got_redirect;
+
+- ClutterActor *stage;
+- ClutterActor *texture;
+- ClutterActor *frame;
+-
+- ClutterActor *logo_frame;
+- ClutterActor *logo;
+-
++ GdkWindow *video_window;
+ GdkCursor *cursor;
+
+ /* Visual effects */
+@@ -227,12 +223,15 @@ struct BaconVideoWidgetPrivate
+ gint video_fps_n;
+ gint video_fps_d;
+
++ gdouble zoom;
++
+ gchar *media_device;
+
+ BvwAudioOutputType speakersetup;
+ gint connection_speed;
+
+ GstBus *bus;
++ gulong sig_bus_sync;
+ gulong sig_bus_async;
+
+ gint eos_id;
+@@ -282,8 +281,11 @@ static void bacon_video_widget_get_prope
+
+ static void bacon_video_widget_finalize (GObject * object);
+
++static void bvw_update_interface_implementations (BaconVideoWidget *bvw);
+ static void setup_vis (BaconVideoWidget * bvw);
+ static GList * get_visualization_features (void);
++static gboolean bacon_video_widget_configure_event (GtkWidget *widget,
++ GdkEventConfigure *event, BaconVideoWidget *bvw);
+ static void size_changed_cb (GdkScreen *screen, BaconVideoWidget *bvw);
+ static void bvw_stop_play_pipeline (BaconVideoWidget * bvw);
+ static GError* bvw_error_from_gst_error (BaconVideoWidget *bvw, GstMessage *m);
+@@ -306,6 +308,8 @@ static GtkWidgetClass *parent_class = NU
+
+ static int bvw_signals[LAST_SIGNAL] = { 0 };
+
++static GThread *gui_thread;
++
+ GST_DEBUG_CATEGORY (_totem_gst_debug_cat);
+ #define GST_CAT_DEFAULT _totem_gst_debug_cat
+
+@@ -395,50 +399,6 @@ bvw_check_if_video_decoder_is_missing (B
+ }
+
+ static void
+-set_display_pixel_aspect_ratio (GdkScreen *screen,
+- 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;
+-
+-#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 */
+- ratio = (gdouble) (gdk_screen_get_width_mm (screen) * gdk_screen_get_height (screen))
+- / (gdk_screen_get_height_mm (screen) * gdk_screen_get_width (screen));
+-
+- 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->priv->logo_mode) {
+@@ -461,22 +421,42 @@ get_media_size (BaconVideoWidget *bvw, g
+ if (bvw->priv->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)))
+- set_display_pixel_aspect_ratio (gtk_widget_get_screen (GTK_WIDGET (bvw)), &disp_par);
++ if (bvw->priv->xoverlay) {
++ GObjectClass *klass;
++ GParamSpec *pspec;
++
++ klass = G_OBJECT_GET_CLASS (bvw->priv->xoverlay);
++ pspec = g_object_class_find_property (klass, "pixel-aspect-ratio");
++
++ if (pspec != NULL) {
++ GValue disp_par_prop = { 0, };
+
++ g_value_init (&disp_par_prop, pspec->value_type);
++ g_object_get_property (G_OBJECT (bvw->priv->xoverlay),
++ "pixel-aspect-ratio", &disp_par_prop);
++
++ if (!g_value_transform (&disp_par_prop, &disp_par)) {
++ GST_WARNING ("Transform failed, assuming pixel-aspect-ratio = 1/1");
++ gst_value_set_fraction (&disp_par, 1, 1);
++ }
++
++ g_value_unset (&disp_par_prop);
++ }
++ }
++
+ 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->priv->ratio_type != BVW_RATIO_AUTO) {
+ switch (bvw->priv->ratio_type) {
+@@ -503,12 +483,13 @@ get_media_size (BaconVideoWidget *bvw, g
+ movie_par_d = 0;
+ g_assert_not_reached ();
+ }
+- } else {
++ }
++ else {
+ /* Use the movie pixel aspect ratio if any */
+ movie_par_n = bvw->priv->movie_par_n;
+ movie_par_d = bvw->priv->movie_par_d;
+ }
+-
++
+ GST_DEBUG ("movie PAR is %d/%d", movie_par_n, movie_par_d);
+
+ if (bvw->priv->video_width == 0 || bvw->priv->video_height == 0) {
+@@ -568,39 +549,150 @@ static void
+ bacon_video_widget_realize (GtkWidget * widget)
+ {
+ BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
++ GdkWindowAttr attributes;
++ gint attributes_mask;
++ GdkColor black = { 0, 0, 0 };
++ GdkWindow *window;
++ GdkEventMask event_mask;
++ GtkAllocation allocation;
+ GtkWidget *toplevel;
+
++ event_mask = gtk_widget_get_events (widget)
++ | GDK_POINTER_MOTION_MASK
++ | GDK_KEY_PRESS_MASK;
++ gtk_widget_set_events (widget, event_mask);
++
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
++ window = gtk_widget_get_window (widget);
++ gdk_window_ensure_native (window);
++
++ /* Creating our video window */
++ attributes.window_type = GDK_WINDOW_CHILD;
++ attributes.x = 0;
++ attributes.y = 0;
++ gtk_widget_get_allocation (widget, &allocation);
++ attributes.visual = gdk_screen_get_system_visual (gtk_widget_get_screen (widget));
++ attributes.width = allocation.width;
++ attributes.height = allocation.height;
++ attributes.wclass = GDK_INPUT_OUTPUT;
++ attributes.event_mask = gtk_widget_get_events (widget);
++ attributes.event_mask |= GDK_EXPOSURE_MASK |
++ GDK_POINTER_MOTION_MASK |
++ GDK_BUTTON_PRESS_MASK |
++ GDK_KEY_PRESS_MASK;
++ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
++
++ bvw->priv->video_window = gdk_window_new (window,
++ &attributes, attributes_mask);
++ gdk_window_ensure_native (bvw->priv->video_window);
++ gdk_window_set_user_data (bvw->priv->video_window, widget);
++ gdk_window_set_background (window, &black);
++
++ gdk_window_set_background (window, &black);
++
+ gtk_widget_set_realized (widget, TRUE);
+
++ /* Connect to configure event on the top level window */
++ g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)),
++ "configure-event", G_CALLBACK (bacon_video_widget_configure_event), bvw);
++
+ /* get screen size changes */
+ g_signal_connect (G_OBJECT (gtk_widget_get_screen (widget)),
+- "size-changed", G_CALLBACK (size_changed_cb), bvw);
++ "size-changed", G_CALLBACK (size_changed_cb), bvw);
+
+ /* setup the toplevel, ready to be resized */
+ toplevel = gtk_widget_get_toplevel (widget);
+- if (gtk_widget_is_toplevel (toplevel) &&
+- gtk_widget_get_parent (widget) != toplevel)
++ if (gtk_widget_is_toplevel (toplevel))
+ gtk_window_set_geometry_hints (GTK_WINDOW (toplevel), widget, NULL, 0);
+
+ bacon_video_widget_gst_missing_plugins_setup (bvw);
+ }
+
+ static void
++bacon_video_widget_show (GtkWidget *widget)
++{
++ BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
++ GdkWindow *window;
++
++ window = gtk_widget_get_window (widget);
++ if (window)
++ gdk_window_show (window);
++ if (bvw->priv->video_window)
++ gdk_window_show (bvw->priv->video_window);
++
++ if (GTK_WIDGET_CLASS (parent_class)->show)
++ GTK_WIDGET_CLASS (parent_class)->show (widget);
++}
++
++static void
++bacon_video_widget_hide (GtkWidget *widget)
++{
++ BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
++ GdkWindow *window;
++
++ window = gtk_widget_get_window (widget);
++ if (window)
++ gdk_window_hide (window);
++ if (bvw->priv->video_window)
++ gdk_window_hide (bvw->priv->video_window);
++
++ if (GTK_WIDGET_CLASS (parent_class)->hide)
++ GTK_WIDGET_CLASS (parent_class)->hide (widget);
++}
++
++static gboolean
++bacon_video_widget_configure_event (GtkWidget *widget, GdkEventConfigure *event,
++ BaconVideoWidget *bvw)
++{
++ GstXOverlay *xoverlay = NULL;
++
++ g_return_val_if_fail (bvw != NULL, FALSE);
++ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), FALSE);
++
++ xoverlay = bvw->priv->xoverlay;
++
++ if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)) {
++ gst_x_overlay_expose (xoverlay);
++ }
++
++ return FALSE;
++}
++
++static void
+ size_changed_cb (GdkScreen *screen, BaconVideoWidget *bvw)
+ {
+ /* FIXME */
+ setup_vis (bvw);
+ }
+
+-static void
+-set_current_actor (BaconVideoWidget *bvw)
++static gboolean
++bacon_video_widget_draw (GtkWidget *widget, cairo_t *cr)
+ {
++ BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
++ GstXOverlay *xoverlay;
+ gboolean draw_logo;
++ XID window;
++ GtkAllocation allocation;
+
+- if (bvw->priv->stage == NULL)
+- return;
++ g_mutex_lock (bvw->priv->lock);
++ xoverlay = bvw->priv->xoverlay;
++ if (xoverlay == NULL) {
++ bvw_update_interface_implementations (bvw);
++ xoverlay = bvw->priv->xoverlay;
++ }
++ if (xoverlay != NULL)
++ gst_object_ref (xoverlay);
++
++ g_mutex_unlock (bvw->priv->lock);
++
++ window = gdk_x11_window_get_xid (bvw->priv->video_window);
++
++ if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay))
++ gst_x_overlay_set_xwindow_id (xoverlay, window);
++
++ /* Start with a nice black canvas */
++ gtk_widget_get_allocation (widget, &allocation);
+
+ /* If there's only audio and no visualisation, draw the logo as well.
+ * If we have a cover image to display, we display it regardless of whether we're
+@@ -613,32 +705,76 @@ set_current_actor (BaconVideoWidget *bvw
+
+ pixbuf = bvw_get_logo_pixbuf (bvw);
+ if (pixbuf != NULL) {
+- gboolean ret;
+- GError *err = NULL;
++ /* draw logo here */
++ gint s_width, s_height, d_width, d_height;
++ gfloat ratio;
++
++ s_width = gdk_pixbuf_get_width (pixbuf);
++ s_height = gdk_pixbuf_get_height (pixbuf);
++ d_width = allocation.width;
++ d_height = allocation.height;
++
++ /* Limit the width/height to 256×256 pixels, but only if we're displaying the logo proper */
++ if (!bvw->priv->cover_pixbuf && d_width > LOGO_SIZE && d_height > LOGO_SIZE)
++ d_width = d_height = LOGO_SIZE;
+
+- ret = clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (bvw->priv->logo),
+- gdk_pixbuf_get_pixels (pixbuf),
+- gdk_pixbuf_get_has_alpha (pixbuf),
+- gdk_pixbuf_get_width (pixbuf),
+- gdk_pixbuf_get_height (pixbuf),
+- gdk_pixbuf_get_rowstride (pixbuf),
+- gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3,
+- CLUTTER_TEXTURE_NONE, &err);
+- if (ret == FALSE) {
+- g_message ("clutter_texture_set_from_rgb_data failed %s", err->message);
+- g_error_free (err);
++ if ((gfloat) d_width / s_width > (gfloat) d_height / s_height) {
++ ratio = (gfloat) d_height / s_height;
+ } else {
+- clutter_actor_show (CLUTTER_ACTOR (bvw->priv->logo_frame));
+- clutter_actor_hide (CLUTTER_ACTOR (bvw->priv->frame));
+- return;
++ ratio = (gfloat) d_width / s_width;
+ }
++
++ /* center the current point, then scale the context so the logo fills up
++ * all the space */
++ cairo_translate (cr, allocation.width / 2, allocation.height / 2);
++ cairo_scale (cr, ratio, ratio);
++
++ /* fill with black */
++ cairo_set_source_rgb (cr, 0, 0, 0);
++ cairo_paint (cr);
++
++ /* then draw logo on top */
++ gdk_cairo_set_source_pixbuf (cr, pixbuf, - s_width / 2, - s_height / 2);
++ cairo_paint (cr);
++ }
++ } else if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)) {
++ /* no logo, use gst */
++
++ /* Paint the non-video parts black */
++ if (gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget))) {
++ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
++ cairo_paint (cr);
+ }
++
++ /* let gst paint the video */
++ if (gtk_cairo_should_draw_window (cr, bvw->priv->video_window))
++ gst_x_overlay_expose (xoverlay);
++ } else {
++ /* if not even gst exists, just paint black */
++ cairo_set_source_rgb (cr, 0, 0, 0);
++ cairo_paint (cr);
+ }
+
+- clutter_actor_show (CLUTTER_ACTOR (bvw->priv->frame));
+- clutter_actor_hide (CLUTTER_ACTOR (bvw->priv->logo_frame));
++ if (xoverlay != NULL)
++ gst_object_unref (xoverlay);
++
++ return FALSE;
+ }
+
++static GstNavigation *
++bvw_get_navigation_iface (BaconVideoWidget *bvw, gboolean update_interfaces)
++{
++ GstNavigation *nav = NULL;
++ g_mutex_lock (bvw->priv->lock);
++ if (bvw->priv->navigation == NULL && update_interfaces == TRUE)
++ bvw_update_interface_implementations (bvw);
++ if (bvw->priv->navigation)
++ nav = gst_object_ref (GST_OBJECT (bvw->priv->navigation));
++ g_mutex_unlock (bvw->priv->lock);
++
++ return nav;
++}
++
+ /* need to use gstnavigation interface for these vmethods, to allow for the sink
+ to map screen coordinates to video coordinates in the presence of e.g.
+ hardware scaling */
+@@ -651,8 +787,13 @@ bacon_video_widget_motion_notify (GtkWid
+
+ g_return_val_if_fail (bvw->priv->play != NULL, FALSE);
+
+- if (!bvw->priv->logo_mode)
+- gst_navigation_send_mouse_event (bvw->priv->navigation, "mouse-move", 0, event->x, event->y);
++ if (!bvw->priv->logo_mode) {
++ GstNavigation *nav = bvw_get_navigation_iface (bvw, FALSE);
++ if (nav) {
++ gst_navigation_send_mouse_event (nav, "mouse-move", 0, event->x, event->y);
++ gst_object_unref (GST_OBJECT (nav));
++ }
++ }
+
+ if (GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
+ res |= GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
+@@ -669,12 +810,16 @@ bacon_video_widget_button_press (GtkWidg
+ g_return_val_if_fail (bvw->priv->play != NULL, FALSE);
+
+ if (!bvw->priv->logo_mode) {
+- gst_navigation_send_mouse_event (bvw->priv->navigation,
+- "mouse-button-press", event->button, event->x, event->y);
+-
+- /* FIXME need to check whether the backend will have handled
+- * the button press
+- res = TRUE; */
++ GstNavigation *nav = bvw_get_navigation_iface (bvw, FALSE);
++ if (nav) {
++ gst_navigation_send_mouse_event (nav,
++ "mouse-button-press", event->button, event->x, event->y);
++ gst_object_unref (GST_OBJECT (nav));
++
++ /* FIXME need to check whether the backend will have handled
++ * the button press
++ res = TRUE; */
++ }
+ }
+
+ if (GTK_WIDGET_CLASS (parent_class)->button_press_event)
+@@ -692,10 +837,14 @@ bacon_video_widget_button_release (GtkWi
+ g_return_val_if_fail (bvw->priv->play != NULL, FALSE);
+
+ if (!bvw->priv->logo_mode) {
+- gst_navigation_send_mouse_event (bvw->priv->navigation,
+- "mouse-button-release", event->button, event->x, event->y);
++ GstNavigation *nav = bvw_get_navigation_iface (bvw, FALSE);
++ if (nav) {
++ gst_navigation_send_mouse_event (nav,
++ "mouse-button-release", event->button, event->x, event->y);
++ gst_object_unref (GST_OBJECT (nav));
+
+- res = TRUE;
++ res = TRUE;
++ }
+ }
+
+ if (GTK_WIDGET_CLASS (parent_class)->button_release_event)
+@@ -720,6 +869,66 @@ bacon_video_widget_get_preferred_height
+ *minimum = *natural = 180;
+ }
+
++static void
++resize_video_window (BaconVideoWidget *bvw)
++{
++ GtkAllocation allocation;
++ gfloat width, height, ratio, x, y;
++ int w, h;
++
++ g_return_if_fail (bvw != NULL);
++ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
++
++ gtk_widget_get_allocation (GTK_WIDGET (bvw), &allocation);
++
++ get_media_size (bvw, &w, &h);
++ if (!w || !h) {
++ w = allocation.width;
++ h = allocation.height;
++ }
++ width = w;
++ height = h;
++
++ /* calculate ratio for fitting video into the available space */
++ if ((gfloat) allocation.width / width >
++ (gfloat) allocation.height / height) {
++ ratio = (gfloat) allocation.height / height;
++ } else {
++ ratio = (gfloat) allocation.width / width;
++ }
++
++ /* apply zoom factor */
++ ratio = ratio * bvw->priv->zoom;
++
++ width *= ratio;
++ height *= ratio;
++ x = (allocation.width - width) / 2;
++ y = (allocation.height - height) / 2;
++
++ gdk_window_move_resize (bvw->priv->video_window, x, y, width, height);
++ gtk_widget_queue_draw (GTK_WIDGET (bvw));
++}
++
++static void
++bacon_video_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
++{
++ BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
++
++ g_return_if_fail (widget != NULL);
++ g_return_if_fail (BACON_IS_VIDEO_WIDGET (widget));
++
++ gtk_widget_set_allocation (widget, allocation);
++
++ if (gtk_widget_get_realized (widget)) {
++
++ gdk_window_move_resize (gtk_widget_get_window (widget),
++ allocation->x, allocation->y,
++ allocation->width, allocation->height);
++
++ resize_video_window (bvw);
++ }
++}
++
+ static gboolean
+ bvw_boolean_handled_accumulator (GSignalInvocationHint * ihint,
+ GValue * return_accu, const GValue * handler_return, gpointer foobar)
+@@ -750,10 +959,11 @@ bacon_video_widget_class_init (BaconVide
+ /* GtkWidget */
+ widget_class->get_preferred_width = bacon_video_widget_get_preferred_width;
+ widget_class->get_preferred_height = bacon_video_widget_get_preferred_height;
++ widget_class->size_allocate = bacon_video_widget_size_allocate;
+ widget_class->realize = bacon_video_widget_realize;
+-
+- /* FIXME: Remove those when GtkClutterEmbedded passes on GDK XI 1.2
+- * events properly */
++ widget_class->show = bacon_video_widget_show;
++ widget_class->hide = bacon_video_widget_hide;
++ widget_class->draw = bacon_video_widget_draw;
+ widget_class->motion_notify_event = bacon_video_widget_motion_notify;
+ widget_class->button_press_event = bacon_video_widget_button_press;
+ widget_class->button_release_event = bacon_video_widget_button_release;
+@@ -1143,6 +1353,7 @@ bacon_video_widget_init (BaconVideoWidge
+ BaconVideoWidgetPrivate *priv;
+
+ gtk_widget_set_can_focus (GTK_WIDGET (bvw), TRUE);
++ gtk_widget_set_double_buffered (GTK_WIDGET (bvw), FALSE);
+
+ g_type_class_ref (BVW_TYPE_METADATA_TYPE);
+ g_type_class_ref (BVW_TYPE_DVD_EVENT);
+@@ -1153,6 +1364,7 @@ bacon_video_widget_init (BaconVideoWidge
+ priv->tagcache = NULL;
+ priv->audiotags = NULL;
+ priv->videotags = NULL;
++ priv->zoom = 1.0;
+ priv->volume = -1.0;
+ priv->movie_par_n = priv->movie_par_d = 1;
+ priv->rate = FORWARD_RATE;
+@@ -1160,6 +1372,8 @@ bacon_video_widget_init (BaconVideoWidge
+ priv->tag_update_queue = g_async_queue_new_full ((GDestroyNotify) update_tags_delayed_data_destroy);
+ priv->tag_update_id = 0;
+
++ priv->lock = g_mutex_new ();
++
+ priv->seek_mutex = g_mutex_new ();
+ priv->clock = gst_system_clock_obtain ();
+ priv->seek_req_time = GST_CLOCK_TIME_NONE;
+@@ -1193,6 +1407,7 @@ static void
+ bvw_handle_application_message (BaconVideoWidget *bvw, GstMessage *msg)
+ {
+ const gchar *msg_name;
++ GtkAllocation allocation;
+
+ msg_name = gst_structure_get_name (msg->structure);
+ g_return_if_fail (msg_name != NULL);
+@@ -1203,22 +1418,18 @@ bvw_handle_application_message (BaconVid
+ 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->priv->texture, w, h);
+-
+ if (bvw->priv->auto_resize
+ && !bvw->priv->fullscreen_mode
+ && !bvw->priv->window_resized) {
+ bacon_video_widget_set_scale_ratio (bvw, 0.0);
++ } else {
++ gtk_widget_get_allocation (GTK_WIDGET (bvw), &allocation);
++ bacon_video_widget_size_allocate (GTK_WIDGET (bvw),
++ &allocation);
+ }
+ bvw->priv->window_resized = TRUE;
+- set_current_actor (bvw);
+ } else {
+ g_message ("Unhandled application message %s", msg_name);
+ }
+@@ -1227,7 +1438,16 @@ bvw_handle_application_message (BaconVid
+ static gboolean
+ bvw_do_navigation_query (BaconVideoWidget * bvw, GstQuery *query)
+ {
+- return gst_element_query (GST_ELEMENT_CAST (bvw->priv->navigation), query);
++ GstNavigation *nav = bvw_get_navigation_iface (bvw, TRUE);
++ gboolean res;
++
++ if (G_UNLIKELY (nav == NULL || !GST_IS_ELEMENT (nav)))
++ return FALSE;
++
++ res = gst_element_query (GST_ELEMENT_CAST (nav), query);
++ gst_object_unref (GST_OBJECT (nav));
++
++ return res;
+ }
+
+ static void
+@@ -1307,6 +1527,10 @@ bvw_handle_element_message (BaconVideoWi
+ g_signal_emit (bvw, bvw_signals[SIGNAL_BUFFERING], 0, percent);
+ }
+ goto done;
++ } else if (strcmp (type_name, "prepare-xwindow-id") == 0 ||
++ strcmp (type_name, "have-xwindow-id") == 0) {
++ /* we handle these synchronously or want to ignore them */
++ goto done;
+ } else if (gst_is_missing_plugin_message (msg)) {
+ bvw->priv->missing_plugins =
+ g_list_prepend (bvw->priv->missing_plugins, gst_message_ref (msg));
+@@ -1678,8 +1902,6 @@ bvw_update_tags (BaconVideoWidget * bvw,
+ bvw_check_for_cover_pixbuf (bvw);
+
+ g_signal_emit (bvw, bvw_signals[SIGNAL_GOT_METADATA], 0);
+-
+- set_current_actor (bvw);
+ }
+
+ static void
+@@ -2378,13 +2600,13 @@ parse_stream_info (BaconVideoWidget *bvw
+ g_object_get (G_OBJECT (bvw->priv->play), "n-audio", &n_audio,
+ "n-video", &n_video, NULL);
+
+- bvw_check_for_cover_pixbuf (bvw);
+-
+ bvw->priv->media_has_video = FALSE;
+ if (n_video > 0) {
+ gint i;
+
+ bvw->priv->media_has_video = TRUE;
++ if (bvw->priv->video_window)
++ gdk_window_show (bvw->priv->video_window);
+
+ for (i = 0; i < n_video && videopad == NULL; i++)
+ g_signal_emit_by_name (bvw->priv->play, "get-video-pad", i, &videopad);
+@@ -2393,14 +2615,19 @@ parse_stream_info (BaconVideoWidget *bvw
+ bvw->priv->media_has_audio = FALSE;
+ if (n_audio > 0) {
+ bvw->priv->media_has_audio = TRUE;
+- if (!bvw->priv->media_has_video) {
++ if (!bvw->priv->media_has_video && bvw->priv->video_window) {
+ gint flags;
+
+ g_object_get (bvw->priv->play, "flags", &flags, NULL);
+- if (bvw->priv->show_vfx && !bvw->priv->cover_pixbuf)
++ if (bvw->priv->show_vfx) {
++ gdk_window_show (bvw->priv->video_window);
++ gtk_widget_set_double_buffered (GTK_WIDGET (bvw), FALSE);
+ flags |= GST_PLAY_FLAG_VIS;
+- else
++ } else {
++ gdk_window_hide (bvw->priv->video_window);
++ gtk_widget_set_double_buffered (GTK_WIDGET (bvw), TRUE);
+ flags &= ~GST_PLAY_FLAG_VIS;
++ }
+ g_object_set (bvw->priv->play, "flags", flags, NULL);
+ }
+ }
+@@ -2419,8 +2646,6 @@ parse_stream_info (BaconVideoWidget *bvw
+ get_visualization_size (bvw, &bvw->priv->video_width,
+ &bvw->priv->video_height, NULL, NULL);
+ }
+-
+- set_current_actor (bvw);
+ }
+
+ static void
+@@ -2451,6 +2676,9 @@ bacon_video_widget_finalize (GObject * o
+ * called again (main loop might be run again to display error dialog) */
+ gst_bus_set_flushing (bvw->priv->bus, TRUE);
+
++ if (bvw->priv->sig_bus_sync)
++ g_signal_handler_disconnect (bvw->priv->bus, bvw->priv->sig_bus_sync);
++
+ if (bvw->priv->sig_bus_async)
+ g_signal_handler_disconnect (bvw->priv->bus, bvw->priv->sig_bus_async);
+
+@@ -2504,6 +2732,11 @@ bacon_video_widget_finalize (GObject * o
+ bvw->priv->update_id = 0;
+ }
+
++ if (bvw->priv->interface_update_id) {
++ g_source_remove (bvw->priv->interface_update_id);
++ bvw->priv->interface_update_id = 0;
++ }
++
+ if (bvw->priv->tagcache) {
+ gst_tag_list_free (bvw->priv->tagcache);
+ bvw->priv->tagcache = NULL;
+@@ -2535,6 +2768,7 @@ bacon_video_widget_finalize (GObject * o
+ bvw->priv->mount_cancellable = NULL;
+ }
+
++ g_mutex_free (bvw->priv->lock);
+ g_mutex_free (bvw->priv->seek_mutex);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+@@ -3495,6 +3729,7 @@ bacon_video_widget_open (BaconVideoWidge
+ gboolean
+ bacon_video_widget_play (BaconVideoWidget * bvw, GError ** error)
+ {
++ GtkAllocation allocation;
+ GstState cur_state;
+
+ g_return_val_if_fail (bvw != NULL, FALSE);
+@@ -3502,6 +3737,16 @@ bacon_video_widget_play (BaconVideoWidge
+ g_return_val_if_fail (GST_IS_ELEMENT (bvw->priv->play), FALSE);
+ g_return_val_if_fail (bvw->priv->mrl != NULL, FALSE);
+
++ /* We hide the video window for now. Will show when video of vfx comes up */
++ if (bvw->priv->video_window) {
++ gdk_window_hide (bvw->priv->video_window);
++ /* We also take the whole widget until we know video size */
++ gtk_widget_get_allocation (GTK_WIDGET (bvw), &allocation);
++ gdk_window_move_resize (bvw->priv->video_window, 0, 0,
++ allocation.width,
++ allocation.height);
++ }
++
+ if (bvw->priv->ready_idle_id) {
+ g_source_remove (bvw->priv->ready_idle_id);
+ bvw->priv->ready_idle_id = 0;
+@@ -3864,7 +4109,12 @@ bacon_video_widget_close (BaconVideoWidg
+ static void
+ bvw_do_navigation_command (BaconVideoWidget * bvw, GstNavigationCommand command)
+ {
+- gst_navigation_send_command (bvw->priv->navigation, command);
++ GstNavigation *nav = bvw_get_navigation_iface (bvw, TRUE);
++ if (nav == NULL)
++ return;
++
++ gst_navigation_send_command (nav, command);
++ gst_object_unref (GST_OBJECT (nav));
+ }
+
+ /**
+@@ -3988,10 +4238,7 @@ bacon_video_widget_set_logo (BaconVideoW
+ if (error) {
+ g_warning ("An error occurred trying to open logo %s: %s", name, error->message);
+ g_error_free (error);
+- return;
+ }
+-
+- set_current_actor (bvw);
+ }
+
+ /**
+@@ -4017,10 +4264,21 @@ bacon_video_widget_set_logo_mode (BaconV
+ if (priv->logo_mode != logo_mode) {
+ priv->logo_mode = logo_mode;
+
+- set_current_actor (bvw);
++ if (priv->video_window) {
++ if (logo_mode) {
++ gdk_window_hide (priv->video_window);
++ gtk_widget_set_double_buffered (GTK_WIDGET (bvw), TRUE);
++ } else {
++ gdk_window_show (priv->video_window);
++ gtk_widget_set_double_buffered (GTK_WIDGET (bvw), FALSE);
++ }
++ }
+
+ g_object_notify (G_OBJECT (bvw), "logo_mode");
+ g_object_notify (G_OBJECT (bvw), "seekable");
++
++ /* Queue a redraw of the widget */
++ gtk_widget_queue_draw (GTK_WIDGET (bvw));
+ }
+ }
+
+@@ -4377,13 +4635,8 @@ get_visualization_size (BaconVideoWidget
+ g_return_if_fail (h != NULL);
+ g_return_if_fail (bvw->priv->visq < G_N_ELEMENTS (vis_qualities));
+
+- if (gtk_widget_get_realized (GTK_WIDGET (bvw)) == FALSE) {
+- if (fps_n)
+- *fps_n = 1;
+- if (fps_d)
+- *fps_d = 1;
++ if (!bvw->priv->video_window)
+ return;
+- }
+
+ *h = vis_qualities[bvw->priv->visq].height;
+ new_fps_n = vis_qualities[bvw->priv->visq].fps;
+@@ -4391,9 +4644,9 @@ get_visualization_size (BaconVideoWidget
+ screen = gtk_widget_get_screen (GTK_WIDGET (bvw));
+ *w = *h * gdk_screen_get_width (screen) / gdk_screen_get_height (screen);
+
+- if (fps_n)
++ if (fps_n)
+ *fps_n = new_fps_n;
+- if (fps_d)
++ if (fps_d)
+ *fps_d = 1;
+ }
+
+@@ -4439,11 +4692,7 @@ setup_vis (BaconVideoWidget * bvw)
+
+ GST_DEBUG ("setup_vis called, show_vfx %d, vis element %s",
+ bvw->priv->show_vfx, bvw->priv->vis_element_name);
+-
+- /* Check to see if we have an embedded cover image. If we do, don't show visualisations.
+- * FIXME probably wrong now, hide that and use an OSD instead */
+- bvw_check_for_cover_pixbuf (bvw);
+-
++
+ if (bvw->priv->show_vfx && !bvw->priv->cover_pixbuf && bvw->priv->vis_element_name) {
+ GstElement *vis_element = NULL, *vis_capsfilter = NULL;
+ GstPad *pad = NULL;
+@@ -4539,17 +4788,26 @@ setup_vis (BaconVideoWidget * bvw)
+ }
+ }
+
++ /* Check to see if we have an embedded cover image. If we do, don't show visualisations. */
++ bvw_check_for_cover_pixbuf (bvw);
++
+ if (bvw->priv->media_has_audio &&
+- !bvw->priv->media_has_video) {
++ !bvw->priv->media_has_video && bvw->priv->video_window) {
+ gint flags;
+
+ g_object_get (bvw->priv->play, "flags", &flags, NULL);
+ if (bvw->priv->show_vfx && !bvw->priv->cover_pixbuf) {
++ gdk_window_show (bvw->priv->video_window);
++ gtk_widget_set_double_buffered (GTK_WIDGET (bvw), FALSE);
+ flags |= GST_PLAY_FLAG_VIS;
+ } else {
++ gdk_window_hide (bvw->priv->video_window);
++ gtk_widget_set_double_buffered (GTK_WIDGET (bvw), TRUE);
+ flags &= ~GST_PLAY_FLAG_VIS;
+ }
+ g_object_set (bvw->priv->play, "flags", flags, NULL);
++
++ gtk_widget_queue_draw (GTK_WIDGET (bvw));
+ }
+
+ beach:
+@@ -4580,7 +4838,6 @@ bacon_video_widget_set_show_visualizatio
+
+ bvw->priv->show_vfx = show_visualizations;
+ setup_vis (bvw);
+- set_current_actor (bvw);
+ }
+
+ static gboolean
+@@ -4795,6 +5052,9 @@ bacon_video_widget_set_scale_ratio (Baco
+
+ GST_DEBUG ("ratio = %.2f", ratio);
+
++ if (bvw->priv->video_window == NULL)
++ return;
++
+ if (!bvw->priv->media_has_video && bvw->priv->show_vfx) {
+ get_visualization_size (bvw, &w, &h, NULL, NULL);
+ } else {
+@@ -4829,42 +5089,41 @@ bacon_video_widget_set_scale_ratio (Baco
+ /**
+ * bacon_video_widget_set_zoom:
+ * @bvw: a #BaconVideoWidget
+- * @mode: the #BvwZoomMode
++ * @zoom: a percentage zoom factor
+ *
+- * Sets the zoom type applied to the video when it is displayed.
++ * Sets the zoom factor applied to the video when it is displayed,
++ * as an integeric percentage between %0 and %1
++ * (e.g. set @zoom to %1 to not zoom at all).
+ **/
+ void
+ bacon_video_widget_set_zoom (BaconVideoWidget *bvw,
+- BvwZoomMode mode)
++ double zoom)
+ {
+ g_return_if_fail (bvw != NULL);
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
+
+- if (bvw->priv->frame == NULL)
+- return;
+-
+- totem_aspect_frame_set_expand (TOTEM_ASPECT_FRAME (bvw->priv->frame),
+- (mode == BVW_ZOOM_EXPAND));
++ bvw->priv->zoom = zoom;
++ if (bvw->priv->video_window != NULL)
++ resize_video_window (bvw);
+ }
+
+ /**
+ * bacon_video_widget_get_zoom:
+ * @bvw: a #BaconVideoWidget
+ *
+- * Returns the zoom mode applied to videos displayed by the widget.
++ * Returns the zoom factor applied to videos displayed by the widget,
++ * as an integeric percentage between %0 and %1
++ * (e.g. %1 means no zooming at all).
+ *
+- * Return value: a #BvwZoomMode
++ * Return value: the zoom factor
+ **/
+-BvwZoomMode
++double
+ bacon_video_widget_get_zoom (BaconVideoWidget *bvw)
+ {
+- gboolean expand;
+-
+ g_return_val_if_fail (bvw != NULL, 1.0);
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 1.0);
+
+- expand = totem_aspect_frame_get_expand (TOTEM_ASPECT_FRAME (bvw->priv->frame));
+- return expand ? BVW_ZOOM_EXPAND : BVW_ZOOM_NONE;
++ return bvw->priv->zoom;
+ }
+
+ /* Search for the color balance channel corresponding to type and return it. */
+@@ -4913,6 +5172,8 @@ bacon_video_widget_get_video_property (B
+ g_return_val_if_fail (bvw != NULL, 65535/2);
+ g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 65535/2);
+
++ g_mutex_lock (bvw->priv->lock);
++
+ ret = 0;
+
+ if (bvw->priv->balance && GST_IS_COLOR_BALANCE (bvw->priv->balance))
+@@ -4936,7 +5197,7 @@ bacon_video_widget_get_video_property (B
+
+ GST_DEBUG ("channel %s: returning value %d", found_channel->label, ret);
+ g_object_unref (found_channel);
+- return ret;
++ goto done;
+ } else {
+ ret = -1;
+ }
+@@ -4944,6 +5205,9 @@ bacon_video_widget_get_video_property (B
+
+ GST_DEBUG ("nothing found for type %d, returning value %d", type, ret);
+
++done:
++
++ g_mutex_unlock (bvw->priv->lock);
+ return ret;
+ }
+
+@@ -5871,6 +6135,9 @@ bacon_video_widget_get_current_frame (Ba
+ /* */
+ /* =========================================== */
+
++/* applications must use exactly one of bacon_video_widget_get_option_group()
++ * OR bacon_video_widget_init_backend(), but not both */
++
+ /**
+ * bacon_video_widget_get_option_group:
+ *
+@@ -5884,10 +6151,26 @@ bacon_video_widget_get_current_frame (Ba
+ GOptionGroup*
+ bacon_video_widget_get_option_group (void)
+ {
+- gtk_clutter_init (NULL, NULL);
+ return gst_init_get_option_group ();
+ }
+
++/**
++ * bacon_video_widget_init_backend:
++ * @argc: pointer to application's argc
++ * @argv: pointer to application's argv
++ *
++ * Initialises #BaconVideoWidget's GStreamer backend. If this fails
++ * for the GStreamer backend, your application will be terminated.
++ *
++ * Applications must call either this or bacon_video_widget_get_option_group() exactly
++ * once; but not both.
++ **/
++void
++bacon_video_widget_init_backend (int *argc, char ***argv)
++{
++ gst_init (argc, argv);
++}
++
+ GQuark
+ bacon_video_widget_error_quark (void)
+ {
+@@ -5899,6 +6182,191 @@ bacon_video_widget_error_quark (void)
+ return q;
+ }
+
++/* fold function to pick the best colorspace element */
++static gboolean
++find_colorbalance_element (GstElement *element, GValue * ret, GstElement **cb)
++{
++ GstColorBalanceClass *cb_class;
++
++ GST_DEBUG ("Checking element %s ...", GST_OBJECT_NAME (element));
++
++ if (!GST_IS_COLOR_BALANCE (element))
++ return TRUE;
++
++ GST_DEBUG ("Element %s is a color balance", GST_OBJECT_NAME (element));
++
++ cb_class = GST_COLOR_BALANCE_GET_CLASS (element);
++ if (GST_COLOR_BALANCE_TYPE (cb_class) == GST_COLOR_BALANCE_HARDWARE) {
++ gst_object_replace ((GstObject **) cb, (GstObject *) element);
++ /* shortcuts the fold */
++ return FALSE;
++ } else if (*cb == NULL) {
++ gst_object_replace ((GstObject **) cb, (GstObject *) element);
++ return TRUE;
++ } else {
++ return TRUE;
++ }
++}
++
++static gboolean
++bvw_update_interfaces_delayed (BaconVideoWidget *bvw)
++{
++ GST_DEBUG ("Delayed updating interface implementations");
++ g_mutex_lock (bvw->priv->lock);
++ bvw_update_interface_implementations (bvw);
++ bvw->priv->interface_update_id = 0;
++ g_mutex_unlock (bvw->priv->lock);
++
++ return FALSE;
++}
++
++/* Must be called with bvw->priv->lock held */
++static void
++bvw_update_interface_implementations (BaconVideoWidget *bvw)
++{
++ GstColorBalance *old_balance = bvw->priv->balance;
++ GstXOverlay *old_xoverlay = bvw->priv->xoverlay;
++ GstElement *video_sink = NULL;
++ GstElement *element = NULL;
++ GstIterator *iter;
++ GstElement *play;
++
++ if (g_thread_self() != gui_thread) {
++ if (bvw->priv->balance)
++ gst_object_unref (bvw->priv->balance);
++ bvw->priv->balance = NULL;
++ if (bvw->priv->xoverlay)
++ gst_object_unref (bvw->priv->xoverlay);
++ bvw->priv->xoverlay = NULL;
++ if (bvw->priv->navigation)
++ gst_object_unref (bvw->priv->navigation);
++ bvw->priv->navigation = NULL;
++
++ if (bvw->priv->interface_update_id)
++ g_source_remove (bvw->priv->interface_update_id);
++ bvw->priv->interface_update_id =
++ g_idle_add ((GSourceFunc) bvw_update_interfaces_delayed, bvw);
++ return;
++ }
++
++ play = gst_object_ref(bvw->priv->play);
++
++ g_mutex_unlock (bvw->priv->lock);
++ g_object_get (bvw->priv->play, "video-sink", &video_sink, NULL);
++ g_assert (video_sink != NULL);
++ g_mutex_lock (bvw->priv->lock);
++
++ gst_object_unref(play);
++
++ /* We try to get an element supporting XOverlay interface */
++ if (GST_IS_BIN (video_sink)) {
++ GST_DEBUG ("Retrieving xoverlay from bin ...");
++ element = gst_bin_get_by_interface (GST_BIN (video_sink),
++ GST_TYPE_X_OVERLAY);
++ } else {
++ element = gst_object_ref(video_sink);
++ }
++
++ if (GST_IS_X_OVERLAY (element)) {
++ GST_DEBUG ("Found xoverlay: %s", GST_OBJECT_NAME (element));
++ bvw->priv->xoverlay = GST_X_OVERLAY (element);
++ } else {
++ GST_DEBUG ("No xoverlay found");
++ if (element)
++ gst_object_unref (element);
++ bvw->priv->xoverlay = NULL;
++ }
++
++ /* Try to find the navigation interface */
++ if (GST_IS_BIN (video_sink)) {
++ GST_DEBUG ("Retrieving navigation from bin ...");
++ element = gst_bin_get_by_interface (GST_BIN (video_sink),
++ GST_TYPE_NAVIGATION);
++ } else {
++ element = gst_object_ref(video_sink);
++ }
++
++ if (GST_IS_NAVIGATION (element)) {
++ GST_DEBUG ("Found navigation: %s", GST_OBJECT_NAME (element));
++ bvw->priv->navigation = GST_NAVIGATION (element);
++ } else {
++ GST_DEBUG ("No navigation found");
++ if (element)
++ gst_object_unref (element);
++ bvw->priv->navigation = NULL;
++ }
++
++ /* Find best color balance element (using custom iterator so
++ * we can prefer hardware implementations to software ones) */
++
++ /* FIXME: this doesn't work reliably yet, most of the time
++ * the fold function doesn't even get called, while sometimes
++ * it does ... */
++ iter = gst_bin_iterate_all_by_interface (GST_BIN (bvw->priv->play),
++ GST_TYPE_COLOR_BALANCE);
++ /* naively assume no resync */
++ element = NULL;
++ gst_iterator_fold (iter,
++ (GstIteratorFoldFunction) find_colorbalance_element, NULL, &element);
++ gst_iterator_free (iter);
++
++ if (element) {
++ bvw->priv->balance = GST_COLOR_BALANCE (element);
++ GST_DEBUG ("Best colorbalance found: %s",
++ GST_OBJECT_NAME (bvw->priv->balance));
++ } else if (GST_IS_COLOR_BALANCE (bvw->priv->xoverlay)) {
++ bvw->priv->balance = GST_COLOR_BALANCE (bvw->priv->xoverlay);
++ gst_object_ref (bvw->priv->balance);
++ GST_DEBUG ("Colorbalance backup found: %s",
++ GST_OBJECT_NAME (bvw->priv->balance));
++ } else {
++ GST_DEBUG ("No colorbalance found");
++ bvw->priv->balance = NULL;
++ }
++
++ if (old_xoverlay)
++ gst_object_unref (GST_OBJECT (old_xoverlay));
++
++ if (old_balance)
++ gst_object_unref (GST_OBJECT (old_balance));
++
++ gst_object_unref (video_sink);
++}
++
++static void
++bvw_element_msg_sync (GstBus *bus, GstMessage *msg, gpointer data)
++{
++ BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (data);
++
++ g_assert (msg->type == GST_MESSAGE_ELEMENT);
++
++ if (msg->structure == NULL)
++ return;
++
++ /* This only gets sent if we haven't set an ID yet. This is our last
++ * chance to set it before the video sink will create its own window */
++ if (gst_structure_has_name (msg->structure, "prepare-xwindow-id")) {
++ XID window;
++
++ GST_DEBUG ("Handling sync prepare-xwindow-id message");
++
++ g_mutex_lock (bvw->priv->lock);
++ bvw_update_interface_implementations (bvw);
++ if (bvw->priv->xoverlay == NULL) {
++ GstObject *sender = GST_MESSAGE_SRC (msg);
++ if (sender && GST_IS_X_OVERLAY (sender))
++ bvw->priv->xoverlay = GST_X_OVERLAY (gst_object_ref (sender));
++ }
++ g_mutex_unlock (bvw->priv->lock);
++
++ g_return_if_fail (bvw->priv->xoverlay != NULL);
++ g_return_if_fail (bvw->priv->video_window != NULL);
++
++ window = gdk_x11_window_get_xid (bvw->priv->video_window);
++ gst_x_overlay_set_xwindow_id (bvw->priv->xoverlay, window);
++ }
++}
++
+ static gboolean
+ bvw_set_playback_direction (BaconVideoWidget *bvw, gboolean forward)
+ {
+@@ -5961,8 +6429,21 @@ bvw_set_playback_direction (BaconVideoWi
+ return retval;
+ }
+
++static void
++got_new_video_sink_bin_element (GstBin *video_sink, GstElement *element,
++ gpointer data)
++{
++ BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (data);
++
++ g_mutex_lock (bvw->priv->lock);
++ bvw_update_interface_implementations (bvw);
++ g_mutex_unlock (bvw->priv->lock);
++}
++
+ /**
+ * bacon_video_widget_new:
++ * @width: initial or expected video width, in pixels, or %-1
++ * @height: initial or expected video height, in pixels, or %-1
+ * @error: a #GError, or %NULL
+ *
+ * Creates a new #BaconVideoWidget.
+@@ -5975,16 +6456,13 @@ bvw_set_playback_direction (BaconVideoWi
+ * Return value: a new #BaconVideoWidget, or %NULL; destroy with gtk_widget_destroy()
+ **/
+ GtkWidget *
+-bacon_video_widget_new (GError ** error)
++bacon_video_widget_new (int width, int height,
++ GError ** error)
+ {
+ BaconVideoWidget *bvw;
+ GstElement *audio_sink = NULL, *video_sink = NULL;
+ gchar *version_str;
+ GstPlayFlags flags;
+- ClutterColor black = { 0x00, 0x00, 0x00, 0xff };
+- ClutterConstraint *constraint;
+- GstElement *balance, *sink, *bin;
+- GstPad *pad, *ghostpad;
+
+ #ifndef GST_DISABLE_GST_DEBUG
+ if (_totem_gst_debug_cat == NULL) {
+@@ -6043,61 +6521,69 @@ bacon_video_widget_new (GError ** error)
+
+ audio_sink = gst_element_factory_make ("autoaudiosink", "audio-sink");
+
++ if (width > 0 && width < SMALL_STREAM_WIDTH &&
++ height > 0 && height < SMALL_STREAM_HEIGHT) {
++ GST_INFO ("forcing ximagesink, image size only %dx%d", width, height);
++ video_sink = gst_element_factory_make ("ximagesink", "video-sink");
++ } else {
++ video_sink = gst_element_factory_make ("gconfvideosink", "video-sink");
++ if (video_sink == NULL) {
++ g_warning ("Could not create element 'gconfvideosink'");
++ /* Try to fallback on ximagesink */
++ video_sink = gst_element_factory_make ("ximagesink", "video-sink");
++ }
++ }
+
+- bvw->priv->stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (bvw));
+- clutter_stage_set_color (CLUTTER_STAGE (bvw->priv->stage), &black);
++ /* Set the display if the video sink supports it */
++ if (g_object_class_find_property (G_OBJECT_GET_CLASS (video_sink), "display")) {
++ const char *display;
+
+- /* Bin */
+- bin = gst_bin_new ("video_sink_bin");
++ display = gdk_get_display_arg_name();
++ if (display != NULL)
++ g_object_set (G_OBJECT (video_sink), "display", display, NULL);
++ }
+
+- /* Video sink, with aspect frame */
+- bvw->priv->texture = g_object_new (CLUTTER_TYPE_TEXTURE,
+- "disable-slicing", TRUE,
+- NULL);
+- sink = clutter_gst_video_sink_new (CLUTTER_TEXTURE (bvw->priv->texture));
+- bvw->priv->navigation = GST_NAVIGATION (sink);
+- if (sink == NULL)
+- g_critical ("Could not create Clutter video sink");
+-
+- /* The logo */
+- bvw->priv->logo_frame = totem_aspect_frame_new ();
+- clutter_actor_set_name (bvw->priv->logo_frame, "logo-frame");
+- bvw->priv->logo = clutter_texture_new ();
+- mx_bin_set_child (MX_BIN (bvw->priv->logo_frame), bvw->priv->logo);
+- clutter_container_add_actor (CLUTTER_CONTAINER (bvw->priv->stage), bvw->priv->logo_frame);
+- mx_bin_set_fill (MX_BIN (bvw->priv->logo_frame), FALSE, FALSE);
+- mx_bin_set_alignment (MX_BIN (bvw->priv->logo_frame), MX_ALIGN_MIDDLE, MX_ALIGN_MIDDLE);
+- clutter_actor_set_size (bvw->priv->logo, LOGO_SIZE, LOGO_SIZE);
+- constraint = clutter_bind_constraint_new (bvw->priv->stage, CLUTTER_BIND_SIZE, 0.0);
+- clutter_actor_add_constraint_with_name (bvw->priv->logo_frame, "size", constraint);
+- clutter_actor_hide (CLUTTER_ACTOR (bvw->priv->logo_frame));
+-
+- /* The video */
+- bvw->priv->frame = totem_aspect_frame_new ();
+- clutter_actor_set_name (bvw->priv->frame, "frame");
+- mx_bin_set_child (MX_BIN (bvw->priv->frame), bvw->priv->texture);
+-
+- clutter_container_add_actor (CLUTTER_CONTAINER (bvw->priv->stage), bvw->priv->frame);
+- constraint = clutter_bind_constraint_new (bvw->priv->stage, CLUTTER_BIND_SIZE, 0.0);
+- clutter_actor_add_constraint_with_name (bvw->priv->frame, "size", constraint);
+-
+- clutter_actor_raise (CLUTTER_ACTOR (bvw->priv->frame),
+- CLUTTER_ACTOR (bvw->priv->logo_frame));
+-
+- gst_bin_add (GST_BIN (bin), sink);
+-
+- /* Add video balance */
+- balance = gst_element_factory_make ("videobalance", "video_balance");
+- gst_bin_add (GST_BIN (bin), balance);
+- bvw->priv->balance = GST_COLOR_BALANCE (balance);
+- pad = gst_element_get_static_pad (balance, "sink");
+- ghostpad = gst_ghost_pad_new ("sink", pad);
+- gst_element_add_pad (bin, ghostpad);
++ if (video_sink) {
++ GstStateChangeReturn ret;
+
+- gst_element_link (balance, sink);
++ /* need to set bus explicitly as it's not in a bin yet and
++ * poll_for_state_change() needs one to catch error messages */
++ gst_element_set_bus (video_sink, bvw->priv->bus);
++ /* state change NULL => READY should always be synchronous */
++ ret = gst_element_set_state (video_sink, GST_STATE_READY);
++ if (ret == GST_STATE_CHANGE_FAILURE) {
++ /* Drop this video sink */
++ gst_element_set_state (video_sink, GST_STATE_NULL);
++ gst_object_unref (video_sink);
++ /* Try again with ximagesink */
++ video_sink = gst_element_factory_make ("ximagesink", "video-sink");
++ gst_element_set_bus (video_sink, bvw->priv->bus);
++ ret = gst_element_set_state (video_sink, GST_STATE_READY);
++ if (ret == GST_STATE_CHANGE_FAILURE) {
++ GstMessage *err_msg;
+
+- video_sink = bin;
+- gst_element_set_state (video_sink, GST_STATE_READY);
++ err_msg = gst_bus_poll (bvw->priv->bus, GST_MESSAGE_ERROR, 0);
++ if (err_msg == NULL) {
++ g_warning ("Should have gotten an error message, please file a bug.");
++ g_set_error_literal (error, BVW_ERROR, BVW_ERROR_VIDEO_PLUGIN,
++ _("Failed to open video output. It may not be available. "
++ "Please select another video output in the Multimedia "
++ "Systems Selector."));
++ } else if (error) {
++ *error = bvw_error_from_gst_error (bvw, err_msg);
++ gst_message_unref (err_msg);
++ }
++ goto sink_error;
++ }
++ }
++ } else {
++ g_set_error_literal (error, BVW_ERROR, BVW_ERROR_VIDEO_PLUGIN,
++ _("Could not find the video output. "
++ "You may need to install additional GStreamer plugins, "
++ "or select another video output in the Multimedia Systems "
++ "Selector."));
++ goto sink_error;
++ }
+
+ if (audio_sink) {
+ GstStateChangeReturn ret;
+@@ -6153,8 +6639,7 @@ bacon_video_widget_new (GError ** error)
+ }
+
+ /* set back to NULL to close device again in order to avoid interrupts
+- * being generated after startup while there's nothing to play yet
+- * FIXME not needed anymore, PulseAudio? */
++ * being generated after startup while there's nothing to play yet */
+ gst_element_set_state (audio_sink, GST_STATE_NULL);
+
+ do {
+@@ -6202,6 +6687,25 @@ bacon_video_widget_new (GError ** error)
+ g_signal_connect (bvw->priv->play, "text-tags-changed",
+ G_CALLBACK (text_tags_changed_cb), bvw);
+
++ /* assume we're always called from the main Gtk+ GUI thread */
++ gui_thread = g_thread_self();
++
++ /* we want to catch "prepare-xwindow-id" element messages synchronously */
++ gst_bus_set_sync_handler (bvw->priv->bus, gst_bus_sync_signal_handler, bvw);
++
++ bvw->priv->sig_bus_sync =
++ g_signal_connect (bvw->priv->bus, "sync-message::element",
++ G_CALLBACK (bvw_element_msg_sync), bvw);
++
++ if (GST_IS_BIN (video_sink)) {
++ /* video sink bins like gconfvideosink might remove their children and
++ * create new ones when set to NULL state, and they are currently set
++ * to NULL state whenever playbin re-creates its internal video bin
++ * (it sets all elements to NULL state before gst_bin_remove()ing them) */
++ g_signal_connect (video_sink, "element-added",
++ G_CALLBACK (got_new_video_sink_bin_element), bvw);
++ }
++
+ return GTK_WIDGET (bvw);
+
+ /* errors */
+Index: totem-3.2.1/configure.in
+===================================================================
+--- totem-3.2.1.orig/configure.in 2011-12-17 00:28:44.952451020 +0100
++++ totem-3.2.1/configure.in 2011-12-17 00:46:31.137663344 +0100
+@@ -47,7 +47,7 @@ GTK_REQS=2.99.3
+ TOTEM_PLPARSER_REQS=2.32.4
+ GNOMEICON_REQS=2.15.90
+ DBUS_REQS=0.82
+-VALA_REQS=0.12.1
++VALA_REQS=0.11.1
+ PEAS_REQS=1.1.0
+ PYTHON_REQS=2.3
+ PYGOBJECT_REQS=2.90.3
+@@ -68,7 +68,7 @@ AC_SUBST(TOTEM_API_VERSION)
+ AC_DEFINE_UNQUOTED(TOTEM_API_VERSION, ["$TOTEM_API_VERSION"], [Define to the Totem plugin API version])
+
+ # The full list of plugins
+-allowed_plugins="bemused brasero-disc-recorder chapters dbusservice im-status gromit iplayer lirc media-player-keys ontop opensubtitles properties publish pythonconsole rotation save-file samplepython sample-vala screensaver screenshot sidebar-test skipto youtube zeitgeist-dp grilo"
++allowed_plugins="bemused brasero-disc-recorder chapters dbusservice im-status gromit iplayer lirc media-player-keys ontop opensubtitles properties publish pythonconsole save-file samplepython sample-vala screensaver screenshot sidebar-test skipto youtube zeitgeist-dp grilo"
+
+ PLUGINDIR='${libdir}/totem/plugins'
+ AC_SUBST(PLUGINDIR)
+@@ -78,9 +78,6 @@ dnl release versions.
+ GST_MAJORMINOR=0.10
+ GST_REQS=0.10.30
+ GSTPLUG_REQS=0.10.30
+-CLUTTER_REQS=1.6.8
+-CLUTTER_GST_REQS=1.3.9
+-CLUTTER_GTK_REQS=1.0.2
+
+ HAVE_GSTREAMER=no
+
+@@ -114,7 +111,7 @@ if test "x$enable_easy_codec_installatio
+ ])
+ fi
+
+-MM="gstreamer-0.10 >= $GST_REQS gstreamer-base-0.10 >= $GST_REQS gstreamer-plugins-base-0.10 >= $GSTPLUG_REQS gstreamer-tag-0.10 >= $GSTPLUG_REQS clutter-1.0 >= $CLUTTER_REQS clutter-gst-1.0 >= $CLUTTER_GST_REQS clutter-gtk-1.0 mx-1.0"
++MM="gstreamer-0.10 >= $GST_REQS gstreamer-base-0.10 >= $GST_REQS gstreamer-plugins-base-0.10 >= $GSTPLUG_REQS gstreamer-tag-0.10 >= $GSTPLUG_REQS"
+ PKG_CHECK_MODULES(GST, $MM)
+ GST_LIBS="$GST_LIBS -lgstbase-$GST_MAJORMINOR -lgstinterfaces-$GST_MAJORMINOR -lgstvideo-$GST_MAJORMINOR -lgstaudio-$GST_MAJORMINOR -lgstpbutils-$GST_MAJORMINOR -lgsttag-$GST_MAJORMINOR"
+ AC_SUBST(GST_LIBS)
+@@ -220,7 +217,6 @@ PKG_CHECK_MODULES([DEPENDENCY],[
+ gmodule-2.0
+ totem-plparser >= $TOTEM_PLPARSER_REQS
+ gstreamer-tag-0.10 >= 0.10.26
+- clutter-gtk-1.0 >= $CLUTTER_GTK_REQS
+ cairo])
+
+ PKG_CHECK_MODULES(MM, $MM)
+@@ -457,12 +453,6 @@ for plugin in ${used_plugins}; do
+ add_plugin="0"
+ fi
+ ;;
+- rotation)
+- if test "${with_vala}" != "yes" ; then
+- plugin_error_or_ignore "you need vala installed to use the rotation plugin"
+- add_plugin="0"
+- fi
+- ;;
+ sample-vala)
+ if test "${with_vala}" != "yes" ; then
+ plugin_error_or_ignore "you need vala installed to use the sample-vala plugin"
+@@ -788,7 +778,6 @@ src/plugins/media-player-keys/Makefile
+ src/plugins/opensubtitles/Makefile
+ src/plugins/opensubtitles/org.gnome.totem.plugins.opensubtitles.gschema.xml.in
+ src/plugins/properties/Makefile
+-src/plugins/rotation/Makefile
+ src/plugins/save-file/Makefile
+ src/plugins/sidebar-test/Makefile
+ src/plugins/skipto/Makefile
+Index: totem-3.2.1/src/backend/bacon-video-widget.h
+===================================================================
+--- totem-3.2.1.orig/src/backend/bacon-video-widget.h 2011-12-17 00:28:45.276452603 +0100
++++ totem-3.2.1/src/backend/bacon-video-widget.h 2011-12-17 00:46:31.137663344 +0100
+@@ -28,7 +28,7 @@
+ #ifndef HAVE_BACON_VIDEO_WIDGET_H
+ #define HAVE_BACON_VIDEO_WIDGET_H
+
+-#include <clutter-gtk/clutter-gtk.h>
++#include <gtk/gtk.h>
+ /* for optical disc enumeration type */
+ #include <totem-disc.h>
+
+@@ -51,7 +51,7 @@ typedef struct BaconVideoWidgetCommon Ba
+ **/
+ typedef struct {
+ /*< private >*/
+- GtkClutterEmbed parent;
++ GtkEventBox parent;
+ BaconVideoWidgetPrivate *priv;
+ } BaconVideoWidget;
+
+@@ -62,7 +62,7 @@ typedef struct {
+ **/
+ typedef struct {
+ /*< private >*/
+- GtkClutterEmbedClass parent_class;
++ GtkEventBoxClass parent_class;
+
+ void (*error) (GtkWidget *bvw, const char *message,
+ gboolean playback_stopped, gboolean fatal);
+@@ -139,8 +139,11 @@ typedef enum {
+ GQuark bacon_video_widget_error_quark (void) G_GNUC_CONST;
+ GType bacon_video_widget_get_type (void);
+ GOptionGroup* bacon_video_widget_get_option_group (void);
++/* This can be used if the app does not use popt */
++void bacon_video_widget_init_backend (int *argc, char ***argv);
+
+-GtkWidget *bacon_video_widget_new (GError **error);
++GtkWidget *bacon_video_widget_new (int width, int height,
++ GError **error);
+
+ char *bacon_video_widget_get_backend_name (BaconVideoWidget *bvw);
+
+@@ -368,19 +371,6 @@ typedef enum {
+ BVW_RATIO_DVB = 4
+ } BvwAspectRatio;
+
+-/**
+- * BvwZoomMode:
+- * @BVW_ZOOM_NONE: No video zooming/cropping
+- * @BVW_ZOOM_EXPAND: Fill area with video, and crop the excess
+- *
+- * The zoom mode used by the video widget, as set by
+- * bacon_video_widget_set_zoom().
+- **/
+-typedef enum {
+- BVW_ZOOM_NONE = 0,
+- BVW_ZOOM_EXPAND = 1
+-} BvwZoomMode;
+-
+ void bacon_video_widget_set_deinterlacing (BaconVideoWidget *bvw,
+ gboolean deinterlace);
+ gboolean bacon_video_widget_get_deinterlacing (BaconVideoWidget *bvw);
+@@ -394,8 +384,8 @@ void bacon_video_widget_set_scale_ratio
+ float ratio);
+
+ void bacon_video_widget_set_zoom (BaconVideoWidget *bvw,
+- BvwZoomMode mode);
+-BvwZoomMode bacon_video_widget_get_zoom (BaconVideoWidget *bvw);
++ double zoom);
++double bacon_video_widget_get_zoom (BaconVideoWidget *bvw);
+
+ int bacon_video_widget_get_video_property (BaconVideoWidget *bvw,
+ BvwVideoProperty type);
+Index: totem-3.2.1/src/backend/Makefile.am
+===================================================================
+--- totem-3.2.1.orig/src/backend/Makefile.am 2011-12-17 00:28:45.236452408 +0100
++++ totem-3.2.1/src/backend/Makefile.am 2011-12-17 00:46:31.137663344 +0100
+@@ -12,7 +12,6 @@ bvw_test_CPPFLAGS = \
+
+ bvw_test_CFLAGS = \
+ $(DEPENDENCY_CFLAGS) \
+- $(MM_CFLAGS) \
+ $(AM_CFLAGS)
+
+ bvw_test_LDADD = \
+@@ -54,9 +53,7 @@ libbaconvideowidget_la_SOURCES = \
+ video-utils.c video-utils.h \
+ bacon-video-widget-gst-0.10.c \
+ bacon-video-widget-gst-missing-plugins.c \
+- bacon-video-widget-gst-missing-plugins.h \
+- totem-aspect-frame.h \
+- totem-aspect-frame.c
++ bacon-video-widget-gst-missing-plugins.h
+
+ libbaconvideowidget_la_CPPFLAGS = \
+ -D_REENTRANT \
+Index: totem-3.2.1/data/totem.ui
+===================================================================
+--- totem-3.2.1.orig/data/totem.ui 2011-12-17 00:28:44.916450849 +0100
++++ totem-3.2.1/data/totem.ui 2011-12-17 00:46:31.141663355 +0100
+@@ -362,15 +362,36 @@
+ <property name="hide-if-empty">False</property>
+ </object>
+ </child>
+-
++ </object>
++ </child>
++ <child>
++ <object class="GtkActionGroup" id="zoom-action-group">
+ <child>
+- <object class="GtkToggleAction" id="zoom-toggle">
++ <object class="GtkAction" id="zoom-in">
+ <property name="label" translatable="yes">Zoom In</property>
+ <property name="stock-id">gtk-zoom-in</property>
+ <property name="tooltip" translatable="yes">Zoom in</property>
+- <signal name="activate" handler="zoom_toggle_action_callback"/>
++ <signal name="activate" handler="zoom_in_action_callback"/>
++ </object>
++ <accelerator key="R" modifiers="GDK_CONTROL_MASK"/>
++ </child>
++ <child>
++ <object class="GtkAction" id="zoom-reset">
++ <property name="label" translatable="yes">Zoom Reset</property>
++ <property name="stock-id">gtk-zoom-100</property>
++ <property name="tooltip" translatable="yes">Zoom reset</property>
++ <signal name="activate" handler="zoom_reset_action_callback"/>
++ </object>
++ <accelerator key="0" modifiers="GDK_CONTROL_MASK"/>
++ </child>
++ <child>
++ <object class="GtkAction" id="zoom-out">
++ <property name="label" translatable="yes">Zoom Out</property>
++ <property name="stock-id">gtk-zoom-out</property>
++ <property name="tooltip" translatable="yes">Zoom out</property>
++ <signal name="activate" handler="zoom_out_action_callback"/>
+ </object>
+- <accelerator key="Z" modifiers="GDK_CONTROL_MASK"/>
++ <accelerator key="T" modifiers="GDK_CONTROL_MASK"/>
+ </child>
+ </object>
+ </child>
+@@ -431,7 +452,9 @@
+ <menuitem name="zoom-1-1" action="zoom-1-1"/>
+ <menuitem name="zoom-2-1" action="zoom-2-1"/>
+ </menu>
+- <menuitem name="zoom-toggle" action="zoom-toggle"/>
++ <menuitem name="zoom-in" action="zoom-in"/>
++ <menuitem name="zoom-reset" action="zoom-reset"/>
++ <menuitem name="zoom-out" action="zoom-out"/>
+ <separator/>
+ <menu name="aspect-ratio" action="aspect-ratio-menu">
+ <menuitem name="aspect-ratio-auto" action="aspect-ratio-auto"/>
+Index: totem-3.2.1/src/backend/bvw-test.c
+===================================================================
+--- totem-3.2.1.orig/src/backend/bvw-test.c 2011-12-17 00:28:45.200452237 +0100
++++ totem-3.2.1/src/backend/bvw-test.c 2011-12-17 00:46:31.141663355 +0100
+@@ -76,6 +76,8 @@ int main
+ GOptionGroup *baconoptiongroup;
+ GError *error = NULL;
+ GtkWidget *win, *bvw;
++ guint32 height = 500;
++ guint32 width = 500;
+
+ #ifdef GDK_WINDOWING_X11
+ XInitThreads ();
+@@ -105,13 +107,12 @@ int main
+ }
+
+ win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+- gtk_window_set_default_size (GTK_WINDOW (win), 500, 500);
++ gtk_window_set_default_size (GTK_WINDOW (win), width, height);
+ g_signal_connect (G_OBJECT (win), "destroy",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+- bvw = bacon_video_widget_new (NULL);
++ bvw = bacon_video_widget_new (width, height, NULL);
+ bacon_video_widget_set_logo (BACON_VIDEO_WIDGET (bvw), "totem");
+- bacon_video_widget_set_show_visualizations (BACON_VIDEO_WIDGET (bvw), TRUE);
+
+ g_signal_connect (G_OBJECT (bvw), "eos", G_CALLBACK (on_eos_event), NULL);
+ g_signal_connect (G_OBJECT (bvw), "got-metadata", G_CALLBACK (on_got_metadata), NULL);
+@@ -126,13 +127,10 @@ int main
+ gtk_widget_show (win);
+ gtk_widget_show (bvw);
+
+- if (filenames && filenames[0]) {
+- test_bvw_set_mrl (bvw, filenames[0]);
+- argument = g_strdup (filenames[0]);
+- bacon_video_widget_play (BACON_VIDEO_WIDGET (bvw), NULL);
+- } else {
+- bacon_video_widget_set_logo_mode (BACON_VIDEO_WIDGET (bvw), TRUE);
+- }
++ mrl = NULL;
++ test_bvw_set_mrl (bvw, (filenames && filenames[0]) ? filenames[0] : LOGO_PATH);
++ argument = g_strdup ((filenames && filenames[0]) ? filenames[0] : LOGO_PATH);
++ bacon_video_widget_play (BACON_VIDEO_WIDGET (bvw), NULL);
+
+ gtk_main ();
+
+Index: totem-3.2.1/browser-plugin/totem-plugin-viewer.c
+===================================================================
+--- totem-3.2.1.orig/browser-plugin/totem-plugin-viewer.c 2011-12-17 00:28:44.872450633 +0100
++++ totem-3.2.1/browser-plugin/totem-plugin-viewer.c 2011-12-17 00:46:31.141663355 +0100
+@@ -1760,7 +1760,7 @@ totem_embedded_construct (TotemEmbedded
+
+ /* if (emb->hidden || emb->audioonly != FALSE)
+ * FIXME disable video decoding */
+- emb->bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (&err));
++ emb->bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (width, height, &err));
+
+ /* FIXME: check the UA strings of the legacy plugins themselves */
+ /* FIXME: at least hxplayer seems to send different UAs depending on the protocol!? */
+Index: totem-3.2.1/src/totem-menu.c
+===================================================================
+--- totem-3.2.1.orig/src/totem-menu.c 2011-12-17 00:28:45.108451785 +0100
++++ totem-3.2.1/src/totem-menu.c 2011-12-17 00:46:31.141663355 +0100
+@@ -53,7 +53,9 @@ G_MODULE_EXPORT void fullscreen_action_c
+ G_MODULE_EXPORT void zoom_1_2_action_callback (GtkAction *action, Totem *totem);
+ G_MODULE_EXPORT void zoom_1_1_action_callback (GtkAction *action, Totem *totem);
+ G_MODULE_EXPORT void zoom_2_1_action_callback (GtkAction *action, Totem *totem);
+-G_MODULE_EXPORT void zoom_toggle_action_callback (GtkToggleAction *action, Totem *totem);
++G_MODULE_EXPORT void zoom_in_action_callback (GtkAction *action, Totem *totem);
++G_MODULE_EXPORT void zoom_reset_action_callback (GtkAction *action, Totem *totem);
++G_MODULE_EXPORT void zoom_out_action_callback (GtkAction *action, Totem *totem);
+ G_MODULE_EXPORT void next_angle_action_callback (GtkAction *action, Totem *totem);
+ G_MODULE_EXPORT void dvd_root_menu_action_callback (GtkAction *action, Totem *totem);
+ G_MODULE_EXPORT void dvd_title_menu_action_callback (GtkAction *action, Totem *totem);
+@@ -1073,11 +1075,21 @@ zoom_2_1_action_callback (GtkAction *act
+ }
+
+ void
+-zoom_toggle_action_callback (GtkToggleAction *action,
+- Totem *totem)
++zoom_in_action_callback (GtkAction *action, Totem *totem)
+ {
+- bacon_video_widget_set_zoom (totem->bvw,
+- gtk_toggle_action_get_active (action) ? BVW_ZOOM_EXPAND : BVW_ZOOM_NONE);
++ totem_action_zoom_relative (totem, ZOOM_IN_OFFSET);
++}
++
++void
++zoom_reset_action_callback (GtkAction *action, Totem *totem)
++{
++ totem_action_zoom_reset (totem);
++}
++
++void
++zoom_out_action_callback (GtkAction *action, Totem *totem)
++{
++ totem_action_zoom_relative (totem, ZOOM_OUT_OFFSET);
+ }
+
+ void
+@@ -1367,6 +1379,7 @@ void
+ totem_ui_manager_setup (Totem *totem)
+ {
+ totem->main_action_group = GTK_ACTION_GROUP (gtk_builder_get_object (totem->xml, "main-action-group"));
++ totem->zoom_action_group = GTK_ACTION_GROUP (gtk_builder_get_object (totem->xml, "zoom-action-group"));
+
+ /* FIXME: Moving these to GtkBuilder depends on bug #457631 */
+ if (gtk_widget_get_direction (totem->win) == GTK_TEXT_DIR_RTL) {
+Index: totem-3.2.1/src/totem-object.c
+===================================================================
+--- totem-3.2.1.orig/src/totem-object.c 2011-12-17 00:28:45.072451608 +0100
++++ totem-3.2.1/src/totem-object.c 2011-12-17 00:46:31.145663367 +0100
+@@ -81,6 +81,12 @@
+ #define SEEK_FORWARD_LONG_OFFSET 10*60
+ #define SEEK_BACKWARD_LONG_OFFSET -3*60
+
++#define ZOOM_UPPER 2.0
++#define ZOOM_RESET 1.0
++#define ZOOM_LOWER 0.1
++#define ZOOM_DISABLE (ZOOM_LOWER - 1)
++#define ZOOM_ENABLE (ZOOM_UPPER + 1)
++
+ #define DEFAULT_WINDOW_W 650
+ #define DEFAULT_WINDOW_H 500
+
+@@ -1996,14 +2002,58 @@ totem_object_action_seek_time (TotemObje
+ totem_seek_time_rel (totem, msec, FALSE, accurate);
+ }
+
+-void
+-totem_action_set_zoom (TotemObject *totem,
+- gboolean zoom)
++static void
++totem_action_zoom (TotemObject *totem, double zoom)
+ {
+ GtkAction *action;
++ gboolean zoom_reset, zoom_in, zoom_out;
++
++ if (totem->bvw == NULL)
++ return;
++
++ if (zoom == ZOOM_ENABLE)
++ zoom = bacon_video_widget_get_zoom (totem->bvw);
++
++ if (zoom == ZOOM_DISABLE) {
++ zoom_reset = zoom_in = zoom_out = FALSE;
++ } else if (zoom < ZOOM_LOWER || zoom > ZOOM_UPPER) {
++ return;
++ } else {
++ bacon_video_widget_set_zoom (totem->bvw, zoom);
++ zoom_reset = (zoom != ZOOM_RESET);
++ zoom_out = zoom != ZOOM_LOWER;
++ zoom_in = zoom != ZOOM_UPPER;
++ }
++
++ action = gtk_action_group_get_action (totem->zoom_action_group,
++ "zoom-in");
++ gtk_action_set_sensitive (action, zoom_in);
++
++ action = gtk_action_group_get_action (totem->zoom_action_group,
++ "zoom-out");
++ gtk_action_set_sensitive (action, zoom_out);
++
++ action = gtk_action_group_get_action (totem->zoom_action_group,
++ "zoom-reset");
++ gtk_action_set_sensitive (action, zoom_reset);
++}
+
+- action = gtk_action_group_get_action (totem->main_action_group, "zoom-toggle");
+- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), zoom);
++void
++totem_action_zoom_relative (TotemObject *totem, double off_pct)
++{
++ double zoom;
++
++ if (totem->bvw == NULL)
++ return;
++
++ zoom = bacon_video_widget_get_zoom (totem->bvw);
++ totem_action_zoom (totem, zoom + off_pct);
++}
++
++void
++totem_action_zoom_reset (TotemObject *totem)
++{
++ totem_action_zoom (totem, ZOOM_RESET);
+ }
+
+ /**
+@@ -2656,6 +2706,14 @@ property_notify_cb_volume (BaconVideoWid
+ }
+
+ static void
++property_notify_cb_logo_mode (BaconVideoWidget *bvw, GParamSpec *spec, TotemObject *totem)
++{
++ gboolean enabled;
++ enabled = bacon_video_widget_get_logo_mode (totem->bvw);
++ totem_action_zoom (totem, enabled ? ZOOM_DISABLE : ZOOM_ENABLE);
++}
++
++static void
+ property_notify_cb_seekable (BaconVideoWidget *bvw, GParamSpec *spec, TotemObject *totem)
+ {
+ update_seekable (totem);
+@@ -3143,10 +3201,10 @@ totem_object_action_remote (TotemObject
+ BVW_DVD_ROOT_MENU);
+ break;
+ case TOTEM_REMOTE_COMMAND_ZOOM_UP:
+- totem_action_set_zoom (totem, TRUE);
++ totem_action_zoom_relative (totem, ZOOM_IN_OFFSET);
+ break;
+ case TOTEM_REMOTE_COMMAND_ZOOM_DOWN:
+- totem_action_set_zoom (totem, FALSE);
++ totem_action_zoom_relative (totem, ZOOM_OUT_OFFSET);
+ break;
+ case TOTEM_REMOTE_COMMAND_EJECT:
+ totem_action_eject (totem);
+@@ -3606,12 +3664,12 @@ totem_action_handle_key_press (TotemObje
+ case GDK_KEY_r:
+ case GDK_KEY_R:
+ case GDK_KEY_ZoomIn:
+- totem_action_set_zoom (totem, TRUE);
++ totem_action_zoom_relative (totem, ZOOM_IN_OFFSET);
+ break;
+ case GDK_KEY_t:
+ case GDK_KEY_T:
+ case GDK_KEY_ZoomOut:
+- totem_action_set_zoom (totem, FALSE);
++ totem_action_zoom_relative (totem, ZOOM_OUT_OFFSET);
+ break;
+ case GDK_KEY_Eject:
+ totem_action_eject (totem);
+@@ -3683,7 +3741,7 @@ totem_action_handle_key_press (TotemObje
+ break;
+ case GDK_KEY_0:
+ if (event->state & GDK_CONTROL_MASK)
+- totem_action_set_zoom (totem, FALSE);
++ totem_action_zoom_reset (totem);
+ else
+ totem_action_set_scale_ratio (totem, 0.5);
+ break;
+@@ -3707,18 +3765,18 @@ totem_action_handle_key_press (TotemObje
+ break;
+ case GDK_KEY_equal:
+ if (event->state & GDK_CONTROL_MASK)
+- totem_action_set_zoom (totem, TRUE);
++ totem_action_zoom_relative (totem, ZOOM_IN_OFFSET);
+ break;
+ case GDK_KEY_hyphen:
+ if (event->state & GDK_CONTROL_MASK)
+- totem_action_set_zoom (totem, FALSE);
++ totem_action_zoom_relative (totem, ZOOM_OUT_OFFSET);
+ break;
+ case GDK_KEY_plus:
+ case GDK_KEY_KP_Add:
+ if (!(event->state & GDK_CONTROL_MASK)) {
+ totem_action_next (totem);
+ } else {
+- totem_action_set_zoom (totem, TRUE);
++ totem_action_zoom_relative (totem, ZOOM_IN_OFFSET);
+ }
+ break;
+ case GDK_KEY_minus:
+@@ -3726,7 +3784,7 @@ totem_action_handle_key_press (TotemObje
+ if (!(event->state & GDK_CONTROL_MASK)) {
+ totem_action_previous (totem);
+ } else {
+- totem_action_set_zoom (totem, FALSE);
++ totem_action_zoom_relative (totem, ZOOM_OUT_OFFSET);
+ }
+ break;
+ case GDK_KEY_KP_Up:
+@@ -4219,7 +4277,7 @@ video_widget_create (TotemObject *totem)
+ GtkContainer *container;
+ BaconVideoWidget **bvw;
+
+- totem->bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (&err));
++ totem->bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (-1, -1, &err));
+
+ if (totem->bvw == NULL) {
+ totem_action_error_and_exit (_("Totem could not startup."), err != NULL ? err->message : _("No reason."), totem);
+@@ -4227,6 +4285,8 @@ video_widget_create (TotemObject *totem)
+ g_error_free (err);
+ }
+
++ totem_action_zoom (totem, ZOOM_RESET);
++
+ g_signal_connect_after (G_OBJECT (totem->bvw),
+ "button-press-event",
+ G_CALLBACK (on_video_button_press_event),
+@@ -4298,6 +4358,8 @@ video_widget_create (TotemObject *totem)
+
+ g_signal_connect (G_OBJECT (totem->bvw), "notify::volume",
+ G_CALLBACK (property_notify_cb_volume), totem);
++ g_signal_connect (G_OBJECT (totem->bvw), "notify::logo-mode",
++ G_CALLBACK (property_notify_cb_logo_mode), totem);
+ g_signal_connect (G_OBJECT (totem->bvw), "notify::seekable",
+ G_CALLBACK (property_notify_cb_seekable), totem);
+ update_volume_sliders (totem);
+Index: totem-3.2.1/src/totem-private.h
+===================================================================
+--- totem-3.2.1.orig/src/totem-private.h 2011-12-17 00:28:45.028451391 +0100
++++ totem-3.2.1/src/totem-private.h 2011-12-17 00:46:31.145663367 +0100
+@@ -80,6 +80,7 @@ struct _TotemObject {
+
+ /* UI manager */
+ GtkActionGroup *main_action_group;
++ GtkActionGroup *zoom_action_group;
+ GtkUIManager *ui_manager;
+
+ GtkActionGroup *devices_action_group;
+@@ -176,7 +177,8 @@ GtkWidget *totem_volume_create (void);
+ void totem_action_open (Totem *totem);
+ void totem_action_open_location (Totem *totem);
+ void totem_action_eject (Totem *totem);
+-void totem_action_set_zoom (Totem *totem, gboolean zoom);
++void totem_action_zoom_relative (Totem *totem, double off_pct);
++void totem_action_zoom_reset (Totem *totem);
+ void totem_action_show_help (Totem *totem);
+ void totem_action_show_properties (Totem *totem);
+ gboolean totem_action_open_files (Totem *totem, char **list);
Modified: desktop/experimental/totem/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-gnome/desktop/experimental/totem/debian/patches/series?rev=32195&op=diff
==============================================================================
--- desktop/experimental/totem/debian/patches/series [utf-8] (original)
+++ desktop/experimental/totem/debian/patches/series [utf-8] Sat Dec 17 00:13:06 2011
@@ -1,2 +1,3 @@
01_fake_keypresses.patch
#70_bbc_plugin.patch
+02_revert_clutter.patch
Modified: desktop/experimental/totem/debian/rules
URL: http://svn.debian.org/wsvn/pkg-gnome/desktop/experimental/totem/debian/rules?rev=32195&op=diff
==============================================================================
--- desktop/experimental/totem/debian/rules [utf-8] (original)
+++ desktop/experimental/totem/debian/rules [utf-8] Sat Dec 17 00:13:06 2011
@@ -1,6 +1,10 @@
#!/usr/bin/make -f
#-*- makefile -*-
+post-patches::
+ mkdir -p m4
+
+include /usr/share/cdbs/1/rules/autoreconf.mk
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/gnome.mk
include /usr/share/cdbs/1/rules/utils.mk
Modified: desktop/experimental/totem/debian/totem-plugins.install
URL: http://svn.debian.org/wsvn/pkg-gnome/desktop/experimental/totem/debian/totem-plugins.install?rev=32195&op=diff
==============================================================================
--- desktop/experimental/totem/debian/totem-plugins.install [utf-8] (original)
+++ desktop/experimental/totem/debian/totem-plugins.install [utf-8] Sat Dec 17 00:13:06 2011
@@ -16,7 +16,6 @@
usr/lib/totem/plugins/properties
usr/lib/totem/plugins/publish
usr/lib/totem/plugins/pythonconsole
-usr/lib/totem/plugins/rotation
usr/lib/totem/plugins/save-file
usr/lib/totem/plugins/screensaver
usr/lib/totem/plugins/screenshot
More information about the pkg-gnome-commits
mailing list